6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

html+css+jsの3ファイルだけで本格的マインスイーパーを作った (Qiita内で遊べるよ!!)

Last updated at Posted at 2019-10-04

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つの機能を実装して本格的なゲームを実現した。

  1. 複数の難易度を選択可能
  2. 行列や地雷の数をユーザーが自由に設定可能
  3. クリア後にツイッターでシェア可能

コーディングはコードの短さよりも見やすさ、実装のしやすさを優先している。

ソースコード

最初にある通り、html,CSS,JavaScriptの3ファイルのみを使った。
pngなどの外部ファイルは一切使わずにマインスイーパーの完成させた。
ソースコードの内容はCodePenを参照。

html

ボタンや数値入力などのゲームのUIを設定している。
スタイルはCSS、ボタン関数などはjsから呼び出し、このファイルはUIの追加時以外は触らなくて済むようにしている。

CSS

ボタンなどのUIのデザインやテキストサイズなどを設定している。
特筆するような事は無いが、16進数のカラーコードによる色指定は個人的に好みでは無いので名前で色指定している。

JavaScript

マインスイーパーの実装を行なっている。
今回のゲームは結構多機能だが300行+α程度で済んだ。
以下、実装においてハマった所や注意が必要な所のみを掻い摘んで解説する。
とりあえず全文読みたい人はinitGame()関数から読み進めると良いかも。

周りに地雷が無いマスを開けた時、周りのマスも開ける

当初はマスのonclick()内でclickNoMine()openAroundCell()の処理も書き、openAroundCell()では各マスのonclick()を呼んでいた。

変更前のopenAroundCell
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を使った音声再生のやり方

  1. 再生したい音声ファイルを入手する
  • 今回は効果音ラボ様のファイルをお借りしました。この場を借りて感謝します。
  1. ファイルをData URIに変換する
  1. 変換した文字列をソースコードに埋め込む
  2. new Audio({Data URI文字列}).play();で音を再生する

タブを変えるとタイマー停止が動作しない

当初はsetIntervalclearIntervalを使ってタイマーを実装していたのだが、タブの切り替えなどを行うとclearIntervalが動作しない。
なのでやや不恰好だがisGameActiveがtrueならsetTimeoutし続ける手法に変えた。

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?