研修生にプログラム教育をするときに、研修生にわかりやすい教材はないかと考えていたのだが、クラシックゲームのようなものなら、楽しく覚えられるのではないかと思い、オセロゲームを作りながらjQueryの学習をすることにした。
とりあえず、私が動くプログラムを作ってみようと思い、ざっくり動くものを作った。
そして、研修生にプログラミングのレクチャーを始めたのだが、私自身、後から気づき学ぶ点があったので書き留めておこうと思い、ブログに残す。
最初に私が作ったもの。
制作手順とプログラムの考え方
用意するもの
・Windwosマシン
(テキストエディタ、ブラウザ[IE11以上、Firefox、Chrome等])
Windowsマシンでツールを使わずにプログラミング学習をしようと思い、テキストエディタとブラウザのみでプログラミングします。
STEP1 : HTMLの書き方、CSSの書き方、JavascriptやjQueryの書き方 の前提知識の学習
基本的な使い方を知らないと発展形は作れません。
前提知識の学習はこのブログでは割愛します。
STEP2 : オセロ板を作る
CSSのgridを使えば比較的簡単に8×8マスの板が作れます。
jQuery
//板
var OthelloBoard = $("<div>").addClass("grid-container");
//マス
var Zone = $("<div>").addClass("grid-item");
var i=0;
while(i++<64){
$(".grid-container").append(Zone.clone(true));
};
$("body").append(OthelloBoard);
CSS
.grid-container{
display: grid;
grid-template-rows: 20px 20px 20px 20px 20px 20px 20px 20px 20px ;
grid-template-columns: 20px 20px 20px 20px 20px 20px 20px 20px ;
grid-gap: 2px;
}
.grid-item{
display: grid;
grid-template-rows: 20px ;
grid-template-columns: 20px;
border: 1px solid #000;
}
STEP3 : マスをクリックした時に碁石を置く
オセロはマスに碁石を置いていくゲームですので、碁石を置くという動きをプログラミングします。
考え方:
jQueryの「.click(function(){})」または、「.on("click",function(){})」というメソッドを利用して、クリック時のイベントを作ります。
※CSSのheightとwidthが16pxになっている理由は、
マスが20pxであるためそれに碁石が収まるサイズにするためです。
border(碁石の淵線)が1pxのため、上下左右に1pxの幅が必要です。
その線の内側が碁石の幅になるため、
幅:20px-左:1px-右:1px がwidthの値になります。 高さ:20px-上:1px-下:1px がheightの値になります。
jQuery
//マス
var Zone = $("<div>").addClass("grid-item");
//碁石
var Stone = $("<div>").addClass("stone");
Zone.click(function(){
$(this).append(Stone.clone("true"));
});
CSS
.stone{
border-radius: 50%;
background-color:black;
}
STEP4 : 黒白の碁石を交互に置く
オセロは黒い碁石から始まり、白い碁石の人と交互に置いていきます。また、一度置いたマスには置けません。このコーディングをします。
交互に碁石の色を変える考え方:
碁石を配置後に次の碁石を準備する
2重配置防止に関する考え方:
clickイベント後にoff("click")で碁石を配置するイベントを除去する。
jQuery
//マス
var Zone = $("<div>").addClass("grid-item");
//黒い碁石
var blackStone = $("<div>").addClass("stone").css("background-color","black");
//白い碁石
var whiteStone = $("<div>").addClass("stone").css("background-color","white");
//次の碁石
var nextStone = blackStone;
Zone.click(function(){
$(this).append(nextStone.clone("true"));
if(Stone == blackStone){
//置いた碁石が黒なので、次の碁石は白をセット
nextStone = whiteStone;
}else{
//置いた碁石が黒ではないため、次の碁石は黒をセット
next Stone = blackStone;
}
//2重配置を防止する
$(this).off("click");
});
CSS
.stone{
border-radius: 50%;
}
STEP5 : 黒と白の碁石がオセロ板の中心部に2つずつ斜めに配置された状態が初期状態
オセロは開始前に中心部に以下のように配置されている状態にしなければなりません。
作成したマスの所定の位置に碁石を配置します。
また、初期配置したところは、clickイベントを取り除いておきます。
考え方:
見た目では8×8のマスの並びですが、64個のマスが並んでいると考えると目的のマスを特定できます。
行4列4に配置している黒碁石のマスは、28番目のマスになり、行4列5のマスは29番目、行5列4のマスは36番目、行5列5のマスは37番目といえます。
指定番目の要素を選択するjQueryでの書き方は、 $("ターゲット:eq(番)") を使います。
:eq(番)で指定できる番号は0からスタートします。そのため28番目ならば、27になります。
jQuery
//マス
var Zone = $("<div>").addClass("grid-item");
//黒い碁石
var blackStone = $("<div>").addClass("stone").css("background-color","black");
//白い碁石
var whiteStone = $("<div>").addClass("stone").css("background-color","white");
while(i++<64){
$(".grid-container").append(Zone.clone(true));
};
STEP6 : 同じ色の碁石で縦横斜めに異なる色の碁石を1つ以上挟むことができるマスでなければ碁石を置けない
碁石を配置できる条件を以下のように整理します。
1.クリックしたマスから上下左右斜めに1マス異なる位置マスが別の色の碁石が配置されていなければ配置できません。
※以下の図では、黒色の碁石を配置しようと考えた場合、碁石の周りの青色のマスの位置に白色の碁石が必ず必要になります。
右JQueryの緑色部分のようにif(stone.length>0) とDOMオブジェクトのみをif文判定すると存在する場合にtrue、存在しない場合はfalseとなります。
2.1を満たす方向は、同じ色の碁石があり、未異なる色の碁石が1つ以上同じ色の碁石のマスまで連続配置されていなければならない。
※以下の図では、青丸のところに黒碁石を置くとすると、1の条件を満たす方向は、上、右、下のみになります。さらに上は白碁石が連続しているが、黒碁石がないので挟めません。右は間に碁石がないマスがあるので挟めません。下方法(赤色のマスの方向)は白碁石の先に黒碁石があるので挟めます。
※右JSでオレンジ色の部分、attrでcolorプロパティを追加しています。これは.css("background-color")の値で比較しようとすると、"black"や"rgb(0,0,0)"などブラウザによってCSSの値が異なって認識してしまいますので、色を固定の値で判別させるためです。
3.クリックした位置からマスの隅まで確認していき、挟めることができれば配置可能と判断できる。
例)黒石の順のケース
クリックした位置→白(1つ以上の連続)→黒
1方向でも配置可能ならば、碁石を配置する(STEP.4参照)
※複数の条件で1つでも満たす場合という判定には、boolean型のフラグ変数を用います。(右JQueryの桃色字部分)。
初めにfalse(配置できない)にしておき、条件を満たした時点でtrue(配置できる)に変更します。
jQuery
//マス
var Zone = $("<div>").addClass("grid-item");
//黒い碁石
var blackStone = $("<div>").addClass("stone").css("background-color","black").attr("color","black");
//白い碁石
var whiteStone = $("<div>").addClass("stone").css("background-color","white").attr("color","white");
//次の人の変数を作成var nextStone = blackStone;
//クリック時の動作
Zone.click(function(){
//クリックしたマスのINDEX
var index=($(".grid-item").index(this));
//左方向最大マス数
var leftmax = index % 8;
~省略(各方向への最大マス数)~
//判定フラグ(Boolean型)
var ok = false;
//左にチェックする
for(i=1;i<=leftmax;i++){
var stone=$('.grid-item:eq('+(index-i)+')').children("div"); //配置済み碁石を取得
if(i==1){ //1つ目のマスの処理
if(stone.length == 0 || stone.attr("color") == nextStone.attr("color")){
break; //チェック対象外
}
}else{ //2つ目以降のマスの処理
if(stone.length > 0){
if(stone.attr("color") == nextStone.attr("color")){
ok = true;
//反転処理
while(--i > 0){
~省略(挟んだ石を反転する処理)~
}
break;
}
}else{
break; //石が未配置のためチェック終了
}
}
}
~省略(同様に右、上、下、右斜め上、左斜め上、右斜め下、左斜め下のチェック)~
//碁石配置とターン変更処理
if(ok){
$(this).append(nextStone.clone());
if(Stone.attr("color") == blackStone.attr("color")){
//置いた碁石が黒なので、次の碁石は白をセット
nextStone = whiteStone.clone();
}else{
//置いた碁石が黒ではないため、次の碁石は黒をセット
next Stone = blackStone.clone();
}
//2重配置を防止する
$(this).off("click");
~省略(次の順の人が置ける場所があるかチェック)~
~省略(勝敗の計算)~
}else{
alert("そこには置けません");
}
});
//8×8マス作成
while(i++<64){
$(".grid-container").append(Zone.clone(true));
};
Part.1はここまで。
次回 Part.2で続きを記載します。
次回の内容
STEP7 : 上下左右斜めに挟むことが可能かチェックする
STEP8 : 同じ色の碁石で縦横斜めに挟まれた異なる色の碁石は同じ色の碁石に取り換えられる
STEP9 : 碁石が置ける場所がない場合、異なる碁石の順になる
STEP10 : すべてマスが碁石で埋まるか、黒白両方の碁石が置ける場所がなくなった時点で終了する
STEP11 : ゲームの勝敗の計算