目覚ましスヌーズの繰り返し処理｜文章題で身に付くプログラミング思考入門️（8/25）

## はじめに

あなたは、朝はどうやって起きていますか？
スマホのアラームは、身近な繰り返し処理の例ですね。

毎日決まった行動を繰り返したいとき、機械に頼ると非常に便利ですよね。

『文章題で身に付くプログラミング思考入門️』は、日常や文章問題からプログラミング思考を身に付けていく、簡単で身近で、あなたをちょっと輝かせてくれるシリーズです。

今回は、繰り返し処理について考えていきましょう。
だいぶボリュームのある記事になってしまいましたが、とても大事なことを書きました。

## 前回のまとめ


前回の記事は[こちら](https://qiita.com/yuki-TheWaggle/items/8132190b747f97815b5b)
第一回は[こちら](https://qiita.com/yuki-TheWaggle/items/a6845c85a464c3c46ab2)

## 対象者
- プログラミングの考え方を学びたい人
- プログラミングに挫折したことのある人
- 論理的思考を鍛えたい人
- 文系の人
- エンジニアの思考を理解したい人

## 概要

### アラームとスヌーズを考えてみる
さて、あなたはいつも何時に起きていますか？
アラームが鳴ったらすぐに目覚めますか？

私は最近、スマホを握ったまま秒でスヌーズしています。
この間は1時間半も寝坊しました。焦りました。

目覚ましアラームのスムーズ機能は便利な繰り返し機能ですね。

:::note warn
ここから先はフィクションです。実際のプログラム上でどのように実装されているのかは確認していません。
:::

さて、スヌーズ機能とはどんなものでしょうか？
アラームが鳴り、スヌーズをし、アラームを止めるまでの一連の流れを考えてみましょう。

```
1. アラームが鳴る
2. スヌーズを選択する
3. （1〜2の繰り返し）
4. アラームを止める
```

こんな感じですね。

分解してみましょうか。
アラームとスヌーズは別で設定できますよね。
ということは、別の機能だと予想できますね。

一旦、アラーム機能だけ取り出して考えてみましょう。

```
【アラーム機能】
1. アラームを鳴らす
2. アラームを止める
```

同じように、スヌーズ機能だけ取り出して考えてみましょう。
一定時間経ったらアラームが鳴る仕組みがスヌーズ機能ですから、

```
【スヌーズ機能】
1. 一定時間（iPhoneなら9分間）待つ
2. アラームを鳴らす
```

こんな感じでしょうかね。このように、

**必要最低限のシンプルな部品に分解して、組み合わせて大きなものを作っていくという考え方は、拡張性をもたらします。**

レゴブロックみたいなものです。
シンプルな部品だからこそ、自由に組み合わせて壮大な作品を作ることができます。

さて、アラームとスヌーズの関係性を考えてみましょう。
スヌーズはアラームがないとそもそも動きませんから、**アラームはスヌーズの土台ということになりますね。**
レゴで言うと平べったくて大きいやつですね。『基礎板』という名前だそうです。
その上にスヌーズ機能が乗っかります。

ということで、土台であるアラーム機能についてもう少し考えてみましょう。

アラーム機能を使うためには設定が必要です。
何時に鳴らしたいのかを事前に設定しておいて、実際にその時間になったらアラームが鳴り始めますよね。

```
【開始条件】
- 現在時刻がアラーム時刻になったら
```

そして、永遠に鳴り止まないアラームは困りますから、ユーザーが自由に止められるようにすることも大切です。

```
【終了条件】
- ユーザーがアラーム停止を選択したら
```

この一連のアラーム機能の中に、スヌーズが組み込まれますね。

ちなみに、iPhoneだとサイドボタンを押したら一瞬でスヌーズが再設定されるので、試したことのない人はやってみてください。
iPhoneを握ったまま寝るだけです。二度寝派のあなたにおすすめです。

```
【スヌーズの継続条件】
- ユーザーがスヌーズを再設定したら
```

こんな感じでしょうかね。だいぶ分解できました。
これらの繰り返しや組み合わせで、スマホのアラームが鳴り続けるわけです。

### 整理して組み合わせてみる

ちょっと整理しましょう。
繰り返し処理のプログラムを実行するためには、

- 開始条件
- 継続条件
- 終了条件

が必要です。つまり、

- 【開始条件】どのタイミングで始めるか？
- 【継続条件】どのような条件下で繰り返すか？
- 【終了条件】どのようにして終わるか？

ということですね。

さて、先ほど分解した要素を一旦広げてみましょう。

```
【アラーム機能】
1. アラームを鳴らす
2. アラームを止める

【スヌーズ機能】
1. 一定時間待つ
2. アラームを鳴らす

【開始条件】
- 現在時刻がアラーム時刻になったら

【終了条件】
- ユーザーがアラーム停止を選択したら

【スヌーズの継続条件】
- ユーザーがスヌーズを再設定したら
```

それでは、これらの要素を入れ替えたり組み込んだりしてみましょう。
まずは、アラームが鳴り始めるところからです。
つまり、土台のアラーム機能を作りましょう。
プログラム側の目線で見ていきます。

```
1. 現在時刻がアラーム時刻になったら
　　1-1. アラームを鳴らす
  
2. ユーザーがアラーム停止を選択したら
　　2-1. アラームを止める
```

シンプルですね。
次に、アラームの中にスヌーズ機能を組み込みましょう。
実際のところ、ユーザーはアラームが鳴ったら、アラームを停止するか／スヌーズを再設定するかのどちらかを選択しますね。
この流れに沿って手順も括ってやりましょう。

```
1. 現在時刻がアラーム時刻になったら
　　1-1. アラームを鳴らす

2. （ユーザーの選択）
　　2-1. ユーザーがアラーム停止を選択したら
　　　　2-1-1. アラームを止める

　　2-2. ユーザーがスヌーズを再設定したら
　　　　2-2-1. 一定時間待つ
　　　　2-2-2. アラームを鳴らす
```

こう見てみると、`2. （ユーザーの選択）`で、どちらも選ばれなかった場合はどうなるんだろう？と不安になりますね。なりますよね？
足しましょう。
どちらも選ばれなかったら、スヌーズさせることにしましょうか。

```
1. 現在時刻がアラーム時刻になったら
　　1-1. アラームを鳴らす

2. （ユーザーの選択）
　　2-1. ユーザーがアラーム停止を選択したら
　　　　2-1-1. アラームを止める

　　2-2. ユーザーがスヌーズを再設定したら
　　　　2-2-1. 一定時間待つ
　　　　2-2-2. アラームを鳴らす

　　2-3. どちらでもないなら
　　　　2-3-1. 一定時間待つ
　　　　2-3-2. アラームを鳴らす
```

シンプルなアラーム機能とスヌーズ機能ができました。

### 発展

同じ処理が2回出てきましたね。

> 2-2-1. 一定時間待つ
> 2-2-2. アラームを鳴らす


> 2-3-1. 一定時間待つ
> 2-3-2. アラームを鳴らす

`【スヌーズ機能】`としてまとめてしまいましょう。
同じことを繰り返すのと、新しく2回考えるのとでは、前者の方がリソースを省けます。

```
1. 現在時刻がアラーム時刻になったら
　　1-1. アラームを鳴らす

2. （ユーザーの選択）
　　2-1. ユーザーがアラーム停止を選択したら
　　　　2-1-1. アラームを止める

　　2-2. ユーザーがスヌーズを再設定したら
　　　　2-2-1. 【スヌーズ機能】

　　2-3. どちらでもないなら
　　　　2-3-1. 【スヌーズ機能】

【スヌーズ機能】
1. 一定時間待つ
2. アラームを鳴らす
```

なお、このように処理をまとめたものを`関数`と言います。

さて、大事なのは、

- 条件に当てはまらなければ、処理は実行されない
- 処理は、上から順に実行される
- 開始条件・継続条件・終了条件を明確にする

という点です。

> 条件に当てはまらなければ、処理は実行されない
- #### あらかじめ、条件とその時の処理を想定して洗い出しておきましょう。
  - 「もし`〇〇`ならば、`◆◆◆`」の
      - `〇〇`が条件
      - `◆◆◆`が処理
      です。詳しくは[前回の記事](https://qiita.com/yuki-TheWaggle/items/8132190b747f97815b5b)に書いてあります。
  - あらかじめ想定しておかなければ、プログラムを事前に組んでやることができません。
  - とりあえず、仮定で良いのです。想定できたものから試して、改良を重ねましょう。

> 処理は、上から順に実行される
- #### 処理の順番を考えましょう。
  - プログラムは書かれた順に上から実行されます。
  - 繰り返し処理を終了する時用のコードを上に書いた方が効率的です。プログラムが終了される場合、その他の条件を照らし合わせる計算は不要ですね。プログラムを先に終わらせてしまって、下に書かれた処理が計算されないようにした方が、無駄を減らせます。

> 開始条件・継続条件・終了条件を明確にする

- #### 必ず終了させましょう。
  - よくある落とし穴は、繰り返し処理が永遠に続いてしまうパターンです。
  - どうやったらプログラムが終わるのか、しっかり意識して組み込みましょう。

### プログラムと柔軟性
ところで、アラーム機能そのものも繰り返しできますね。
毎日指定や曜日指定など、ユーザーの都合が良いように指定できます。

先ほどは`スヌーズの継続条件`だけ考えました。
平日だけアラームを繰り返したい場合、`アラームの継続条件`はどうなるでしょうか？


```
【アラームの継続条件】
- 今日が土曜日または日曜日でないならば
```
とできそうですね。
つまり、月〜金曜日のいずれかであればアラームを起動させて、アラームの中身は先ほど作ったアルゴリズムを再利用すれば実装できるのではないでしょうか。

繰り返し処理は、このように入れ子にすることも多いです。
完成された部品であれば、再利用して活用することができます。

部品をどのように作り、どのように組み合わせ、ユーザーにどのような価値を提供するのか。
コンピュータに柔軟性はありません。
**私たちが柔軟性と適応力を持ち、創造力を最大限に発揮して、コンピュータをコントロールしましょう。**

次回は、データの再利用について解説していきます。

## まとめ
- あらかじめ、条件とその時の処理を想定して洗い出しておきましょう。
- 処理の順番を考えましょう。
- 必ず終了させましょう。

## 最後に
ここまで読んでくださってありがとうございます！
少しでも役に立ったら「いいね」をください。続ける励みになります。
今回、どこまで書こうか書くまいか迷いました。難易度の塩梅が難しかった、、コメントでフィードバックをいただけたら嬉しいです。