最短以外は不正解!8パズルでゲームをつくるの続きです。今回はゲーム開始以降の処理を実装します。

ゲーム開始時の処理

ゲームを開始するための処理を示します。

問題は全部で31手問題まであります。1手問題みたいなのは簡単すぎるので省略し、4手、8手、10手、それ以降は31手まで連続する数で問題をつくります。最初の配列 move_limits に値を格納しているのはそのための処理です。

そのあと前回の処理で取得した問題のなかから◯手問題をランダムに選択してこれを出題することにします。そのあとボタンの表示非表示の切り替えと各フラグの変更、消費時間を計測するための現在時刻の取得などをおこないます。

出題する問題の取得

出題する問題を取得する処理を示します。

move_limitsに格納された要素の先頭をみればこれから出題すべき問題が何手問題かわかります。幅優先探索で問題を取得した以上、問題は辞書順に格納されているので、先頭に近いものは単調な問題である可能性があります。

そのため最初の2個は捨てていますが、最終問題は2パターンしかないのでこれだと31手問題が出題されないという問題が発生します。「どうせAIを使ったりチートしなければ20手問題くらいが限界でしょ」なんて考えていたら本当に「30手問題を正解したが31手問題が表示されない」というリプが届いてびっくり。テストはきちんとしましょう(自戒)。

問題を表示する処理を示します。移動回数を示すグローバル変数を0にリセットして先述のsetPieces関数で描画されるようにします。またcanvasのうえにあるdiv要素に現在何手問題かと現在の移動回数を表示させます。

ピースを移動させる処理

ピースを移動させる処理を示します。移動はキー操作とcanvasのクリック、タップでおこなえるようにします。

まずmove関数を示します。引数はピースを移動させる方向を示します(’U’, ‘D’, ‘L’, ‘R’のいずれか)。

まず9番ピースはどのオブジェクトなのかを配列 pieces のなかから探し、これと引数から実際に移動させるピースを特定することができます。移動対象が存在しない場合は不正な操作がおこなわれようとしたことになるので警告音を鳴らして処理を終了します。そうでない場合は移動中であることを示すフラグ moving をセットして移動処理を開始します。

移動処理はいきなり場所を入れ替えるのではなくスライドしているように見せるために数回にわけて座標を変更する非同期処理でおこないます。移動の結果、パズルを完成させることができたら次のステージに移動し、上限回数に達しても完成していない場合は失敗なのでそのステージを最初からやりなおさせる処理をおこないます。

キー操作

キーを押下することで移動させる処理を示します。

canvasがクリック・タップされたときに移動させる処理

canvasがクリック・タップされたときに移動させる処理を示します。クリックされたピースがどれか、9番ピースとの位置関係からその移動方向を求め、移動可能であればそれを移動させます。

スコアランキングへの登録

ステージクリアしたらプレイヤー名とステージ番号、かかった時間をサーバーへ送ります。サーバー側でどのような処理がおこなわれるかは次回示します。

ギブアップ時の処理

ギブアップを選択したときにおこなわれる処理を示します。この場合は解を示してゲームオーバーとします。

解は幅優先探索で取得します。