三目ならべ

jQueryを使って、三目ならべを作ってみます。人対人で、二人が交互に操作してゲームをするという想定です。
jQueryの初心者向けです。(所要時間:2時間程度)

image

図1.三目ならべの完成図

前提条件

3目ならべのゲームボードは下記のHTMLを使います。
メッセージは、この段階では固定のメッセージ表示します。

image

図1.三目ならべゲームボード

以下にHTMLとCSSを示します。

1
2
3
4
5
6
7
8
<style>
 *     {margin:0; padding:0;}
 body  {width:100%; height:100%;}
 #bordnname {font-size:large; color:#fff; background-color:#921; padding:4px;}
 #bord {border-collapse:collapse; border-spacing:0px;}
 #bord td.cell {font-size:200%; width:1.2em; height:1.2em; text-align:center; vertical-align:middle; border:solid 1px #ccc;}
 #message {color:#d00;}
</style>
1
2
3
4
5
6
7
8
9
<div>
 <p id="bordnname">三目並べ</p>
 <table id="bord"><tbdy>
   <tr><td class="cell empty"><td><td class="cell empty"><td><td class="cell empty"><td></tr>
   <tr><td class="cell empty"><td><td class="cell empty"><td><td class="cell empty"><td></tr>
   <tr><td class="cell empty"><td><td class="cell empty"><td><td class="cell empty"><td></tr>
 </tbdy></table>
 <span id="message">ここにメッセージを表示する予定です。 これを元に、三目並べを作ってみましょう。</span>
</div>

それぞれのマス目には、利用目的で二つのクラスを設定しています。
(1)cellクラスが、マス目の見栄えを表現しています。
(2)emptyクラスは、この段階ではつかっていません。
次のステップで、マス目が空(カラ)か、空でないかの識別として利用します。

このHTMLをもとに、三目ならべのゲームを作ってみましょう。

3目ならべのロジック

問 題 (1) jQueryを使って、三目ならべの操作、空いているマス目に〇×を交互に駒打ちせよ。

サンプル1にjavascript(jQuery)を記述して、〇×交互に、空いているマスに駒打するように改良してください。
制御は、tdタグのemptyクラスは、empty=空を意味しています。
このemptyクラスが残るマス目は、まだ何も駒打ちされていない空であり、emptyクラスがないマス目は、既に駒打ちしたと判断しさせます。
つまり、emptyクラスのマス目に駒打ちされた場合、そのマス目の、emptyクラスを取り除けばよいことになります。
ただし、勝敗判定は、次の問題で行いますので、ここでは無視してください。

image

図2.三目ならべの駒打ち

解 答 (1) jQueryを使った三目ならべの駒打ちロジック

1
2
3
4
5
6
7
8
9
$(function(){
  "use strict";
  var order = 0;
  var mark = ["○""×"];
  $(document).on('click','#bord td.empty',function(){
    $(this).text(mark[order]).removeClass("empty");
    order = ++order%2;
  });
})

交互に駒打ちする、”交互”は、order変数(3行目)を使っています。
0:〇の順番、1:×の順番に交互になるようにしています(7行目)。
このorder値は、0/1の2値になるため、〇×の文字配列の要素位置と一致する仕組みとなります。

空のマス目(td)クリックは、document.on()の表現を使っています(6行目)。
$(要素).click()は、静的HTML用で、今回のケースのような動的に変わるHTMLでは使えません。

問 題 (2) 問題1のjavascriptを改良して、3目ならべの勝敗判定せよ。

サンプル2をさらに改良して、勝敗判定を行います。
どちらかが勝った場合、span#message領域に、”〇(×)勝ちです”と出力します。
この勝敗が決定された後は、駒打ちは動作は終了するようにします。

image

図3.三目ならべの判定

解 答 (2) javascriptを使って、3目ならべの勝敗判定ロジック

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<script>
$(function(){
  "use strict";
  var order = 0;
  var n, nx, ny, bi;
  var mark = ["○""×"];
 
  $("#message").text(mark[order] + "の順番です。");
 
  $(".cell").on("click", function(){
    if(!$(this).hasClass("empty")){
      return;
    }
    $(this).text(mark[order]).removeClass("empty");
 
    n = $('#bord .cell').index(this); // セル番号
    nx = n % 3;      // x座標
    ny = (n - nx)/3; // y座標
    b = false;       // 勝敗決定
 
    // 縦方向判定
    for(i=0; i<3; i++){
      if($('#bord .cell').eq(ny*3 + i).text()!==mark[order]){
        break;
      }
    }
    if(i===3){
      b = true;
    }
    // 横方向判定
    if(!b){
      for(i=0; i<3; i++){
        if($('#bord .cell').eq(i*3 + nx).text()!==mark[order]){
          break;
        }
      }
      if(i===3){
        b = true;
      }
    }
    // 斜め判定
    if(!b && (n===0 || n===4 || n===8)){
      b = ($('#bord .cell').eq(0).text()===mark[order]
          && $('#bord .cell').eq(4).text()===mark[order]
          && $('#bord .cell').eq(8).text()===mark[order]);
    }
    if(!b && (n===2 || n===4 || n===6)){
      b = ($('#bord .cell').eq(2).text()===mark[order]
          && $('#bord .cell').eq(4).text()===mark[order]
          && $('#bord .cell').eq(6).text()===mark[order]);
    }
 
    if(b){
      $(".empty").removeClass("empty");
      $("#message").text(mark[order] + "勝ちです。");
    }else{
      order = (++order)%2;
      $("#message").text(mark[order] + "の順番です。");
    }
  });
})
</script>
1
2
3
4
5
6
7
8
9
<div>
 <p id="bordnname">三目ならべ</p>
 <table id="bord"><tbdy>
   <tr><td class="cell empty"><td><td class="cell empty"><td><td class="cell empty"><td></tr>
   <tr><td class="cell empty"><td><td class="cell empty"><td><td class="cell empty"><td></tr>
   <tr><td class="cell empty"><td><td class="cell empty"><td><td class="cell empty"><td></tr>
 </tbdy></table>
 <span id="message"></span>
</div>

まず、打たれた駒が、マス目の左上から何番目かを求めます。(16行目)
この何番目の値から、マス目のx-y座標を取り出しています。(17-18行目)

次に、打たれたマス目のx-y座標を用いて、縦方向、横方向、続いて斜め勝敗判定を行っています。

勝敗判定は、少し長い(21-51行目)ですが、やってることは単純です。

縦方向の判定は、駒打ちセルを含む縦3つのセルを調べて、自分のマークと違うマーク(または、空セル)だった場合、ループを抜けます。(22-26行目)
3回ループをしたということは、3マスとも自分のマークが並んでいた=勝利判定になります。(27-29行目)
二つある斜め方向の判定は、斜めのマス目の値を調べてマークが並んでいるかを調べています。(42-51行目)

勝敗が決定した場合(変数bが真値)、残りの空セルの、emptyクラスを取り除いています。(54行目)
そして、勝者宣言として、メッセージを出力します。(55行目)

ただし、勝敗が決定しない(ゲーム続行中)は、次の方の順番をメッセージ表示してます。(57行目)

セルの位置取得

今回のポイントは、以下の点です。
・index関数、指定要素が同種要素の何番目かを取得します。
・要素番号から、x座標(右方向)、y座標(下方向)にjavascriptの演算で求めます。

今回の問題は、3目ならべという簡単なゲームでした。
いかがでしたか、簡単でしたか? 次回は、オセロゲームを扱ってみましょう。

更新日付:2017/06/25 20:38:00