html,CSS,JavaScriptの3ファイルのみを使ってマインスイーパーを作った。
CodePen上に書いたので、ページに埋め込む事でQiitaの記事内でも遊べます。
マインスイーパーで遊ぼう!
See the Pen Minesweeper by T.D (@td12734) on CodePen.
遊び方
- 左クリック:ボタンを押す、マスを開く
- 右クリック:マスの上に旗を立てる、マスの上の旗を取り除く
- キーボード:カスタムゲーム設定画面で数値を入力する
地雷がないマスを全て開けるゲームです。
ゲームルール
- Easy
- 9*9マス、10地雷
- Windows版の初級と同様
- Normal
- 16*16マス、40地雷
- Windows版の中級と同様
- Hard
- 30*16マス、99地雷
- Windows版の上級と同様
- Lunatic
- 40*25マス、225地雷
- オリジナルの鬼畜難易度
- Custom
- 縦横サイズはそれぞれ2~99、地雷の数は1~(マス数-1)まで自由に設定可能
- 沼
細かい仕様など
- マスを開けた時、隣接するマス全てに地雷がない時は隣接するマスも自動で開ける
- マスを開けた時、隣接するマスに地雷が存在する時は地雷の数を表示する
- 旗が立っているマスの上でクリックしても何も発生しない
- クリアした後、ボタンからツイート可能
- 最初に開けたマスには地雷が無い
- 地雷では無いマスが9マス以上のとき、最初に開けた周囲のマスには地雷が無い
- ゲーム画面が1画面に収まらない場合はスクロールバーが出現する
- カスタムゲームのランダムでは地雷の個数は250個以下、地雷の割合は25%以下に抑えられる
今回目指したこと
ただ作るのもつまらないのでクオリティが高いゲームを作ることにした。
そこで以下の3つの機能を実装して本格的なゲームを実現した。
- 複数の難易度を選択可能
- 行列や地雷の数をユーザーが自由に設定可能
- クリア後にツイッターでシェア可能
コーディングはコードの短さよりも見やすさ、実装のしやすさを優先している。
ソースコード
最初にある通り、html,CSS,JavaScriptの3ファイルのみを使った。
pngなどの外部ファイルは一切使わずに
マインスイーパーの完成させた。
ソースコードの内容はCodePenを参照。
html
ボタンや数値入力などのゲームのUIを設定している。
スタイルはCSS、ボタン関数などはjsから呼び出し、このファイルはUIの追加時以外は触らなくて済むようにしている。
CSS
ボタンなどのUIのデザインやテキストサイズなどを設定している。
特筆するような事は無いが、16進数のカラーコードによる色指定は個人的に好みでは無いので名前で色指定している。
JavaScript
マインスイーパーの実装を行なっている。
今回のゲームは結構多機能だが300行+α程度で済んだ。
以下、実装においてハマった所や注意が必要な所のみを掻い摘んで解説する。
とりあえず全文読みたい人はinitGame()
関数から読み進めると良いかも。
周りに地雷が無いマスを開けた時、周りのマスも開ける
当初はマスのonclick()
内でclickNoMine()
とopenAroundCell()
の処理も書き、openAroundCell()
では各マスのonclick()
を呼んでいた。
if (cell.column > 0 && cell.row > 0) gameTable.rows[cell.column - 1].cells[cell.row - 1].onclick();
if (cell.column > 0) gameTable.rows[cell.column - 1].cells[cell.row].onclick();
if (cell.column > 0 && cell.row < rowLen - 1) gameTable.rows[cell.column - 1].cells[cell.row + 1].onclick();
...
一見すると問題無さそうだが、実行するとtoo much recursion
エラーが出た。
調べてみたところ、再帰処理が多すぎるとエラーが出るようだ。
なので現在のようにonclick自体は呼ばないようにしてエラーを回避した。
wavファイルを再生したい
地雷を踏んだ時の爆発音と地雷以外の全てのマスを開けた時のファンファーレ音を再生したい。
だが、CodePenにそれらはアップロードできず、直リンクで外部サイトから取ってくるのも迷惑が掛かる。
そこで今回は音声データをData URI
に変換し、変換した文字列をソースコードに埋め込んで音を再生する手法を取った。
ん?html、css、jsの3ファイルだけ使うと書いてあるのに音声ファイルを使うのはタイトル詐欺だって???
今回使ったのはData URI
であってファイル
ではないからセーフなんDA☆
Data URIを使った音声再生のやり方
- 再生したい音声ファイルを入手する
- 今回は効果音ラボ様のファイルをお借りしました。この場を借りて感謝します。
- ファイルをData URIに変換する
- Data URI Scheme 変換を使うのが楽です。
- 変換した文字列をソースコードに埋め込む
-
new Audio({Data URI文字列}).play();
で音を再生する
タブを変えるとタイマー停止が動作しない
当初はsetInterval
とclearInterval
を使ってタイマーを実装していたのだが、タブの切り替えなどを行うとclearInterval
が動作しない。
なのでやや不恰好だがisGameActive
がtrueならsetTimeout
し続ける手法に変えた。