whileループ 7. ループをネストする

ネストという言葉は前にも一度出てきましたね。「入れ子」という意味です。「ループをネストする」というのは「ループの中に別のループを入れる」ということを指します。
どちらも{}という記号でループ内容をサンドしているので、見た目が紛らわしいですが、「ループの中身は行頭を字下げする」という書き方をすると少し見やすくなります。字下げとはインデントとも呼びますが、行の頭に空白を入れて右へズラすことをいいます。Swift Playgroundでは空白(半角スペース)を4つ入れるのを字下げのルールとしているようなので、それに従いましょう。字下げするのはwhile {行と最後の}行の間の処理です。{の後で改行ボタンを押すと自動で空白4つ分字下げをしてくれる場合もあります。今回のようにループがネスト(入れ子)になる場合、内側のループの{}の中身は4+4で8文字分字下げすることになります。ループが深くなればなるほど4文字ずつ右にズレていくイメージです。
字下げはしてもしなくてもプログラムの動きには影響しませんが、コードが複雑になって頭がこんがらがって来た時に必ず助けになりますので、するクセをつけておくと良いでしょう。

さてステージは、うずまき状に内側へと進んでいく作りです。一番中にいくと行き止まって進めなくなるので、全体としては行き止まりまで進むことにします。次に曲がり角ですが、そこには必ず宝石があるようです。「宝石があるまでは直進し、宝石まで来たら(取ってから)左に曲がる」というループを内側に置きます。これを行き止まるまでループするのです。

なお字下げルールは、whileだけでなく、func文やif文など{}で処理内容を挟む場合全般に使用します。

whileループ 6. 方法はたくさん

ステージの長さが毎回変化するので、まずは毎回端まで進むようなループを考えます。
次に真正面に進む間、各コマにスイッチ(開または閉)があり、右側に必ず宝石、その向こうにスイッチが必ず存在します。左端と右端のスイッチは反対になっているようです。
ここもタイトル通りたくさんのやり方が考えられます。

以下の例では、
スイッチの開閉をあまり意識しないで済むよう、「閉ならオンにする」という関数switchOn()を作成し、開閉どちらでもスイッチがあればswitchOnを呼び出す、というコードにしました。ループの中では、メインストリートのスイッチを処理、右の宝石とゲット、さらに向こうのスイッチを処理、戻る、という処理を連続して行っていますが、スイッチの部分に関してはswitchOn()を呼び出すだけにできるので、ループ内の見通しが良くなります。

もう少し無駄のないコードにするとしたら、「そもそもメインストリート上のスイッチが閉だった場合、そこをオンにすれば、反対側のスイッチまでは行く必要がなく、宝石だけとって戻ればいい」という考え方があります。是非チャレンジしてみてください。メインストリート上のスイッチが閉か開から別々の処理に分岐するか別々の関数を呼び出すのです。

whileループ 5. 回る

このステージは本当に色々なやり方ができます。
例はあくまで例として考えて、自分なりのやり方を考えてみましょう。

こちらの例では、まず宝石が2つずつ並んだ辺をひとまとまりのパターンとして、それを4回繰り替えるという考え方をしています。またパターン内で2つの宝石を取るのも移動を含めて繰り返しにできたので、結果として、4回のループの中で2回の子ループを回すという形になっています。辺から辺への移動をどこに入れ込むか、各ループの基点(スタート地点)をどこにするかが思案のしどころでしょう。

whileループ 4. 2つのループ

isBlockedが使えないよう、わざわざ曲がり角の先に1つコマが置かれてますね。
それ以外の条件(パターン)を見つけましょう。

例では同じループの中でスイッチの状態が変わる(変える)ところがポイントです。閉スイッチと開スイッチが混在してますが、どのみち閉だったらオンにしないとならず、その後であれば同じ様に曲がり角の条件として利用できるわけです。

whileループ 3. 正しいループを使う

ここもワープを考えると、実はひたすら単純なパターンを繰り返しているステージであるということに気付くと思います。
その1ループ分をコードにし、さいごまで繰り返すwhileループを作りましょう。

下の例ではループ構造とループの中身をわけて見通し易い様に、中身をfuncで関数にしてみました。こうしておくとwhile文の{}の中がシンプルになって、どこでなにをしているのか読み取りやすくなります。