robozzle like 42
を思い出しながら実装してみたやつです
renderFunction(0)
を実行する非同期関数renderFunction(0)
を実行中に呼び出されることを防ぐため、.disabled = true
でボタンを半透明にし、実行できなくする- 操作回数上限である
timeout
を考慮し、time = 0
しておく - 前回の
run()
時の変更を上書きするためflag = false
しておく renderFunction(0)
が実行しおわるまで待つ- 実行し終わったら操作終了の原因が
timeout
かどうかを確認する(timeout
が原因だったらalert
で通知しinit()
で初期化) - コンソールに
End
を出力 - 最後に
.disabled = false
でもう一度実行できるようにする
- 実行し終わったら操作終了の原因が
- Run時のレンダリングはF1(
f[0]
)のみ recursive
関数に引数(f[i], 0, f[i]の長さ
)を渡し呼び出す
fi[j]
が実行可能か判定し、順次実行していく関数(以下、操作終了の条件)- 操作回数が設定された
timeout
を超えている fi
の長さとj
が一致する(0はじまりなので一致したら範囲外)flag
が立っている(Runしてから一度Game clear
かRange over
している)
- 操作回数が設定された
star
が0
のときn
を1カウントアップし、flag
を立て、操作終了することで次のレベルに進む処理を行うboard
の外へアクセスしたか、tiles[y][x]
が-1
のときf[i]
の入力以外を現在のレベルへ初期化し、flag
を立て、操作終了する- 操作終了の条件に当てはまらず、かつ移動元のタイルが操作条件に当てはまる色のとき、
await sleep(speed)
とmoveRocket(command)
を実行する。そうでなければ、今回の操作を待ち時間(await sleep(speed)
)ごとスキップしてawait recursive(fi, j+1, len)
を実行する(再帰)。
command
に応じて操作を変える(f[i][j]
がとりうる値を参照)- 移動先のタイルに星があれば星なしに変え、
star
から1引く(以下タイル番号)0
:赤色1
:緑色2
:青色3
:赤色/星あり4
:緑色/星あり5
:青色/星あり
y
はy軸の増減分(command
とrocketRotate
から自動割り出し)x
はx軸の増減分(command
とrocketRotate
から自動割り出し)
"board"
board[y][x]
のとき対応したタイル番号を示しているboard[y][x]
が-1
のときは、範囲外となる
"point"
- Rocketの初期座標(
y, x
)と向き(rotate
) - 常に
[y, x, rotate]
の形式になる
- Rocketの初期座標(
"fn"
f[i]
に入力できるコマンドの数- 常に
[f1, f2, f3]
の形式になる
"timeout"
- 無限ループを回避するための、操作回数上限
- 常に
[command, condition]
の形式になる j
回目の操作ではcondition
の条件をみたしたときにcommand
を実行できる。command
(操作)-1
: 動かない0
: 直進1
: 右90度方向転換2
: 左90度方向転換3
: 赤にぬりかえ4
: 緑にぬりかえ5
: 青にぬりかえ6
: f1実行7
: f2実行8
: f3実行
condition
(操作条件)-1
: 操作条件なし0
: タイルが赤のとき操作可能1
: タイルが緑のとき操作可能2
: タイルが青のとき操作可能
// LEVEL[0]
f[0] = [[0, 2], [1, 0], [1, 0], [6, 0]];
- レベルアップ時に
f
の枠が更新されない問題を解決