jQueryでオセロをつくる Part.2

 

 前回のつづきです。jQueryでオセロゲームを作っていきます。

制作手順とプログラムの考え方

STEP7 : 上下左右斜めに挟むことが可能かチェックする

 

オセロは同じ色の石で挟むことでリバースし、自石の色に染めていきます。

石を置く位置から8方向(左右上下、斜め4方向)に隅のマスまで確認していきます。

 

石を置く位置(index位置=一番左上から右方向に順番に0..1..2..と番号を振ったもの、例:index=8は2行目の一番左)とします。

 

index位置から隅のマスまでのマス数の考え方は右図をみてください。

 

最大マス数が8マスなので、

左 : index位置 % 8

右 : 7 - (index位置 % 8)

上 : index / 8

下 : 7 - (index / 8)

ですね。

 

斜め方向は、たとえば、右上方向ならば、右方向と上方向の最大マス数のうち、小さい値の方が隅のマスまでのマス数になります。

 

私たちの頭の中では以下のような2次元のマスでイメージしています。

 

1.左方向は-1ずつ一番左のマスまで確認していきます。

2.右方向は+1ずつ一番右のマスまで確認していきます。

 

上下方向、斜め方向は以下図のように2次元の碁盤イメージから1行の配列のイメージにして考えると分かりやすくなります。

1行にしてみると、上下方向は8ずつ離れて並んでおり、右斜め下、左斜め上方向は9ずつ離れて並んでいます。

右斜め上、左斜め下方向は7ずつ離れて並んでいることがわかりますね。

 

つまり、
3.上方向は-8ずつ一番上のマスまで確認していきます。

4.下方向は+8ずつ一番下のマスまで確認していきます。

5.左上方向は-9ずつ隅のマスまで確認していきます。

6.右下方向は+9ずつ隅のマスまで確認していきます。

7.右上方向は-7ずつ隅のマスまで確認していきます。

8.左下方向は+7ずつ隅のマスまで確認していきます。

jQuery

 /**
  * Function : チェック最大マス数取得
  */
 $.checkIndex = function(index){
  var chkList = {
   left : index%8,
   right : 7-(index%8),
   up : parseInt(index/8,10),
   down : parseInt(7-(index/8),10)
  };
  chkList["leftup"] =  chkList.up < chkList.left ? chkList.up : chkList.left;
  chkList["rightup"] = chkList.up < chkList.right ? chkList.up : chkList.right;
  chkList["leftdown"] = chkList.down < chkList.left ? chkList.down : chkList.left;
  chkList["rightdown"] = chkList.down < chkList.right ? chkList.down : chkList.right;
  
  return chkList;
 }

index位置からの隅マスまでのマス数の考え方

マスの並びの考え方について

 //最大マス数のリストを作成する

  var chkList = $.checkIndex(index);
  //クリックしたマスから8方向に向かって挟めるかどうか確認する(挟める場合はリバースする)
  $.each(chkList,function(key,len){
   if($.checkStone({allow:key,max:len,index:index})) ok = true;
  });

 

/**
  * Function : 指定方向へ石をリバースする処理
  */
 $.checkStone = function(options){
 
  var opts = $.extend({
   allow : "left",
   index: 0 ,
   max : 0 ,
   reverse : true , //初期値は反転機能をON
   color : nextStone.attr("color") //初期値は次の石の色
  }, options );
  
  //各方向へマスをチェックしていく際の加減算値
  var step = {
   right : 1,
   left : -1,
   up : -8,
   down : 8,
   rightup : -7,
   leftdown : 7,
   rightdown : 9,
   leftup : -9
  };
       
        for(i=1;i<=opts.max;i++){
   //配置済の碁石を取得
   var stone=$('.grid-item:eq('+(opts.index+i*step[opts.allow])+')').children("div");
   
   if(i==1){//1つ目のマスの処理
    if(stone.length==0||stone.attr("color")==opts.color){
     //石がない、もしくはすでに配置されている石が指定の色と同じ場合はチェック対象外
     return false;
    }
   }else{//2つ目以降のマス目の処理
    if(stone.length>0){
     if(stone.attr("color")==opts.color){
      if(opts.reverse){
       //反転処理(STEP 8参照)
      }
      //すでに配置された石と指定の色が同じ→挟めると判断
      return true;
     }
    }else{
     return false;//石が未配置のためチェック終了
    }
    
   }
  }
  
  return false; //最大マスチェックしたが対象ではなかった
 }


STEP8 : 同じ色の碁石で縦横斜めに挟まれた異なる色の碁石は同じ色の碁石に取り換えられる

 

 index位置から挟めるかチェックしていき、挟める場合は、挟めると判断できた位置からindex方向に逆移動しながら、碁石を置き換えます。

jQuery

 while(--i>0){
        $('.grid-item:eq('+(opts.index+i*step[opts.allow])+')').children("div").remove();
        $('.grid-item:eq('+(opts.index+i*step[opts.allow])+')').append(nextStone.clone(true));
 }

STEP9 : 碁石が置ける場所がない場合、異なる碁石の順になる

 

 石を配置後、全マスを対象にまだ石が置かれていないマスを対象(index位置として)に相手の石の色で挟めることが可能かどうかのチェックを行う。

jQuery

 /**
  * Function : 全マスチェック
  */
 $.allcheck = function(color){
  var ok = false;
  for(index=0;index<64;index++){
   //対象のマスにある石
   var stone=$('.grid-item:eq('+index+')').children("div");
   if(stone.length == 0) { //空のマスのみチェック
   
    //最大マス数のリストを作成する
    var chkList = $.checkIndex(index);
    
    //該当マスから8方向に向かって挟めるかどうか確認する。1か所でも挟めるならば、$.eachを抜ける
    $.each(chkList,function(key,len){
     if($.checkStone({allow:key,max:len,index:index,reverse:false,color:color})) {
      ok=true;
      return false; //$.each内のreturn falseはループを抜けるという意味になる。
     }
    });
    if(ok) return true;
   }
  }
  return false;
 }

STEP10 : すべてマスが碁石で埋まるか、黒白両方の碁石が置ける場所がなくなった時点で終了する

 

jQuery

 //クリックしたマスから8方向に向かって挟めるかどうか確認する(挟める場合はリバースする)
  $.each(chkList,function(key,len){
   if($.checkStone({allow:key,max:len,index:index})) ok = true;
  });
  
  //ターン変更処理
  if(ok){
   //石を置いてもいいと判断されるので
   $(this).append(nextStone.clone())
   //クリックイベントを除去(石を配置済み)
   $(this).off("click");
      
   //石を持ち変える処理
   if(nextStone.attr("color") == blackStone.attr("color")){
    if($.allcheck("white")){
     nextStone = whiteStone.clone();
     $("#message").text("白の番です。");
    }else if($.allcheck("black")){
     $("#message").text("白は置けません。黒の番です。");
    }else{
     $("#message").text("Game end");
    }
   }else{
    if($.allcheck("black")){
     nextStone = blackStone.clone();
     $("#message").text("黒の番です。");
    }else if($.allcheck("white")){
     $("#message").text("黒は置けません。白の番です。");
    }else{
     $("#message").text("Game end");
    }
   }
   
  }else{
   $("#message").text("そこへは置けません。");
  }

STEP11 : ゲームの勝敗の計算

GameEndになった場合、マス上の石の色を数えて、多い方が勝ちですね。

jQuery

var num_b=$(".grid-item div[color='black']").length;
var num_w=$(".grid-item div[color='white']").length;
 num_b > num_w ? alert("黒の勝ち") : num_b < num_w ? alert("白の勝ち") : alert("引き分け");

ダウンロード
オセロサンプルコード
オセロサンプル.js
js ファイル 6.0 KB