2019.09.17

マルバツゲームを作ってみよう~その5:ゲーム終了・初期化処理編


「マルバツゲームを作ってみよう」の連載第5回目です。

今回は「ゲーム終了・初期化処理編」ということで、ゲーム終了時の処理(リセットボタンの表示等)と、リセットボタンを押した際の初期化処理(ゲーム開始画面に戻る)を実装します!

今回が本連載の最終回となります。ついにマルバツゲームが完成しますので、どうぞ楽しみにしてください!😆

今回実装する機能

今回実装するのは、以下の機能です。

ゲーム終了時処理

  • ゲーム終了時に全てのマス目をクリックできないようにする
  • そろったラインをハイライトする
  • リセットボタンを表示する

ゲーム初期化処理

  • リセットボタンを押すと、ゲーム開始時の画面に戻る
画面遷移図

それではまいりましょう。

ゲーム終了時処理

勝敗がつくか引き分けになることによって、ゲームが終了した際には、以下の処理を実行します。

  • ゲーム終了時に全てのマス目をクリックできないようにする
  • そろったラインをハイライトする
  • リセットボタンを表示する

順に実装していきましょう。

実装

マス目をクリックできないようにする

ゲームが終わったのにマス目をクリックしてマークが記入できたりしたら、変な感じですよね。
ということで、ゲームが終了したらマス目をクリックできないようにします。

これは全てのマス目にjs-unclickableをつけるだけですので簡単ですね。

app.js
// ゲーム終了時の処理
function gameOver() {
  // 全てのマスをクリックできないようにする
  squaresArray.forEach(function (square) {
    square.classList.add('js-unclickable');
  });
}

そろったラインをハイライトする

勝ったときに、どのラインがそろったのか一目でわかるように、ハイライトしたいと思います。

まずハイライト用のCSSクラスを用意します。

app.css
.js-highLight {
  background-color: #fff2cc;
}

これをそろったライン(以降「ウィニングライン」と呼ぶことにします)につければいいですね。

次にそのウィニングラインを取得します。
「ウィニングライン」というのはすなわち、(前回を思い出してほしいのですが)勝敗判定でtrueを返したlineのことです。 なので勝敗判定関数の中に、ウィニングラインを取得するコードを追加します。

app.js
// ウィニングラインを入れる変数
let winningLine = null;

// 勝敗判定
function isWinner(symbol) { 
  const result = lineArray.some(function (line) {
    const subResult = line.every(function (square) {
      // 省略
    });
    
    // trueを返したlineをwinningLineに代入
    if (subResult) { winningLine = line }
    
    return subResult;
  });
  return result;
}

あとはwinningLinejs-highLightをつけてあげるだけです。

app.js
// ゲーム終了時の処理
function gameOver() {
  // 全てのマスをクリックできないようにする
  squaresArray.forEach(function (square) {
    square.classList.add('js-unclickable');
  });

  // 勝ったときのマス目をハイライトする
  if (winningLine) {
    winningLine.forEach(function (square) {
      square.classList.add('js-highLight');
    });
  }

}

引き分けの場合、ウィニングラインはありませんので、ウィニングラインがあったときのみ処理するように、全体をif で囲っています。

リセットボタンを表示する

リセットボタンが出っぱなしになっていましたので、まず隠しましょう笑。
js-hiddenをリセットボタンにつけます。

index.html
<div class="btn-container">
  <div class="js-hidden" id="reset-btn">
    <span class="btn btn-reset">もう一回遊ぶ</span>
  </div>
</div>

spanタグに直接js-hiddenをつけると、btnクラスとスタイルの競合を起してしまったため(js-hiddendisplay: none;が、btndisplay: inline-blockで上書きされてしまう)、divで囲ってそっちにjs-hiddenクラスをつけることにしました。

またjavascript から操作するために、id="reset-btn"を付与しています。

これでリセットボタンが隠れましたね。

隠したリセットボタンをゲーム終了時に表示させる処理を書きます。

app.js
// リセットボタン取得
const resetBtn = document.getElementById('reset-btn');

// ゲーム終了時の処理
function gameOver() {
  // 全てのマスをクリックできないようにする
  squaresArray.forEach(function (square) {
    square.classList.add('js-unclickable');
  });

  // 勝ったときのマス目をハイライトする
  if (winningLine) {
    winningLine.forEach(function (square) {
      square.classList.add('js-highLight');
    });
  }

  // リセットボタン表示
  resetBtn.classList.remove('js-hidden');
}

これでgameOver()関数は完成です!
squares.addEventListener()内に組み込んでいきます。

app.js
// マス目をクリックしたときにイベント発火
squaresArray.forEach(function (square) {
  square.addEventListener('click', function () {

    if (flag === true) {
      // 省略
      // マル勝利判定
      if (isWinner('maru')) {
        setMessage('maru-win');
        gameOver();
        return;
      }
      // 省略
    } else {
      // 省略
      // バツ勝利判定
      if (isWinner('batsu')) {
        setMessage('batsu-win');
        gameOver();
        return;
      }
      // 省略
    }

    counter--;
    // 引き分け
    if (counter === 0) {
      setMessage('draw');
      gameOver();
    }

  });
});

以上でゲームが終わった時に、ゲーム終了時処理が走るようになりました。

See the Pen tic-tac-toe4-3 by Shinichi Kurita (@kuri-ta) on CodePen.

ゲーム初期化処理

いよいよ最後の機能になりました。
リセットボタンを押すと、記入されたマルバツのマーク等が消え、ゲーム開始時の画面に戻るという処理を実装していきます。

実装

それほど難しい内容でもないので、完成形を一気に載せてしまいます。

app.js
// ゲーム初期化
function initGame() {
  flag = false;
  counter = 9;
  winningLine = null;
  squaresArray.forEach(function (square) {
    square.classList.remove('js-maru-checked');
    square.classList.remove('js-batsu-checked');
    square.classList.remove('js-unclickable');
    square.classList.remove('js-highLight');
  });
  setMessage('batsu-turn');
  resetBtn.classList.add('js-hidden');
}

まずflagcounterwinningLineといった変数の値を初期化し、squareについたクラスを取り除きます。
そしてメッセージに「×のばん」をセットし、最後にリセットボタンを隠すようにします。

リセットボタンを押したときに上の処理が走るようにします。

app.js
resetBtn.addEventListener('click', function () {
  initGame();
});

ゲーム初期化処理ができました。

以上で、マルバツゲームの完成です!🎉🎉🎉

See the Pen tic-tac-toe4-4 by Shinichi Kurita (@kuri-ta) on CodePen.

お疲れ様でした😌

最後に

全5回にわたってマルバツゲームを作ってきました。皆さん、いかがでしたでしょうか?

確かに、内容としては、プログラミングが得意な中学生だったら作れてしまいそうなものだったかもしれません。
でも、「じゃあ今更マルバツゲームなんて作る意味なくない?」というと、そんなことはないと思います。
それを言い出したら何も始められませんからね😅

中学生向けだろうと、車輪の再発明だろうと、作っちゃえばいいと思います!(少なくとも業務外でやる分には)

作った分だけ強くなれる。そう信じて、ガンガン実装していきましょう~💪

連載記事


<!-- Font Awesome Free 5.0.13 by @fontawesome - https://fontawesome.com --><!-- License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) -->