この記事は タンク・チェンジの問題を解く(Cマガ電脳クラブ 第127回)の続きです。

タンク・チェンジは1989年10月号から2006年4月号まで全199号が発行されたプログラミング技術情報誌『C MAGAZINE』内のCマガ電脳クラブというコーナーで出題された問題ですが、これをそのままパズルゲームにしてみようというのが今回の試みとなります。

HTML部分

HTML部分を示します。戦車が位置する広場に該当する部分がボタンになっていて、クリックして戦車が移動させたい戦車と移動先を指定します。広場をつなぐ斜めの道をHTMLだけでは表現するのが難しかったので(やろうとすればできなくはないが…)この部分はcanvasを用いることにしました。戦車描画用の画像と効果音用の音声データが別途必要です。

style.css

Positionクラスの定義

場所を指定するために使うPositionクラスを定義します。

グローバル変数の定義

グローバル変数を以下のように定義します。

ページが読み込まれたときの処理

ページが読み込まれたときの処理を示します。

ゲームをしていてどうしても答えがわからない場合は答えを表示する降参ボタンを用意しましたが、これはゲーム時のみ表示させます。最初は非表示にします。

戦車は縦横ではなく斜めに移動します。斜めに接する要素の位置を決めるときに CSSに直接書くよりJavaScriptで操作したほうがやりやすいと考えて、ここで座標を決定します。グローバル変数の二次元配列 matMoveButtons にひとつとびにボタン要素が格納されてるので、nullではないものを見つけたときはここで座標や見た目を設定します。

そのあと画像を読み込んで戦車を表示するためのimg要素を合計 6 個生成します。そして戦車の位置を記録する2次元配列を初期化、通路の描画、イベントリスナの追加、ボリューム設定用のコントロールの初期化などをおこないます。

ボリューム設定

定番のボリューム設定を可能にする処理です。スライダーを動かすとボリューム調整とテストができるようにしています。

戦車の位置の初期化

戦車の位置を初期化する処理を示します。0~2が青い戦車、3~5が赤い戦車の位置です。-1 は戦車が存在しない(または移動不能)位置です。

戦車を初期位置に表示する処理を示します。配列で指定された要素の上に重なるように戦車を表示させます。show関数では戦車と広場の中心同士が重なるように戦車の座標を求めています。

通路を描画する処理

canvasに通路を描画する処理を示します。広場の中心を通って広場を斜めに結ぶように通路を描画します。

イベントリスナの追加

イベントリスナを追加する処理を示します。スタートボタンや降参ボタンをクリックしたときの処理や広場やその上に表示されている戦車の画像をクリックしたときの処理を定義しています。

戦車をクリックしたときはボタン要素が画像で覆われているため画像しかクリックできないはずなのですが、サイズ差によって端のほうをクリックした場合に反応してしまう場合があります。そのため phase が 0 と 2 のときはここでもイベントが発火する場合の対策をしています。戦車のクリックとみなさなければならない場合は戦車の画像がクリックされたときと同じ処理をしています。

スタートボタンがクリックされたときはphase と moveCount をリセットして初期位置に配置・表示させ、スタートボタンの非表示と降参ボタンの表示をしています。また次にどうするかユーザーが迷わないように次にする操作(ゲーム開始直後であれば移動させたい青い戦車の指定)を表示させています。

降参ボタンがクリックされたときはその状態から全探索をして最短手順を表示させます。もし手詰まりで最短手順が存在しない場合はその旨を表示します。答えを表示し終わったら最後にスタートボタンを再表示させます。

移動する戦車を指定する処理と実際に移動する処理は次回とします。