ここでもまずナビゲーション処理を先に考えましょう。
開始位置から見て左側が宝石ゾーン、右側がスイッチゾーンです。一件面倒くさそうな配置ですが、ワープゾーンがあるので、右へ右へと曲がっていけば宝石ゾーン→スイッチゾーンを通過できることに気付きます。
そこで、宝石ゾーンとスイッチゾーンで共通となる前進処理をfunc文でgo()という関数にまとめます。内容は「行き止まったら右に曲がりつつ前進」というものです。
続いて、宝石ゾーンの処理です。宝石ゾーンの終わりは厳密には判定できません。宝石の数は不定ですし、一周したとかワープゾーンに載ったなんてことを判定する方法もありません。そこで、「最初に閉スイッチに載った」ら宝石ゾーンは終了として、ループを抜けて次に進むことにしました。
続くスイッチゾーンのwhileループでは、いよいよ取った宝石数とこれから開けていくスイッチ数を比較しながらの繰り返ししなります。この時点でgemCounterはある程度の数字が入っているはずです。一方switchCounterはまだ0で、ループを経て増えていきます。switchCounterの方が少ないうちはループを続け、同じかそれ以上になったらループを抜けます(抜けた後になにもコードがないので、終了となります)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//カウンター変数2つを用意 var gemCounter = 0 var switchCounter = 0 //行き止まったら右に曲がりつつ、1歩進む func go() { if isBlocked { turnRight() } moveForward() } //宝石ゾーンの処理 while !isOnClosedSwitch { //閉スイッチを見つけるまで繰り返す if isOnGem { collectGem() gemCounter += 1 } go() } //スイッチゾーンの処理 while switchCounter < gemCounter { //取った宝石数と開けたスイッチ数を比較 if isOnClosedSwitch { toggleSwitch() switchCounter += 1 } go() } |
今回別にgo()関数を作って共通部分をまとめることは要求されていません。ただこのように別々のゾーンの処理の中に同じことをやればいいんだなって気付いた部分があったら、funcで関数にまとめて、それぞれから1行で呼び出せるようにしておくと、コード全体が短く、見通しやすくなります。またその部分に手直しが必要になった時に、1カ所直すだけでそれを呼び出す全ての部分に反映されるので手間が省けるのでオススメです。