今回も、書籍ゲームで学ぶJavascript入門で紹介されている
神経衰弱ゲームの知識定着のために自分なりに解説をしてみます。
##シャッフル処理
書籍の中では、
まず配列のprototypeの中に、
配列をシャッフルをする処理を記述してあります。(書籍と記述が異なります。)
Array.prototype.shuffle = function(){
var length = array.length;
for(var i = length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = this[i];
this[i] = this[j];
this[j] = tmp;
}
return this;
}
トランプが10枚あるなら
10枚目のカードを、乱数で決めた2番目と入れ替える
9枚目のカードを、乱数で決めた5番目と入れ替える
8枚目のカードを、、、を繰り返して配列をバラバラにしている処理です。
ここでのthisは配列です。
こちらでシャッフルします。
var cards=[]
for(var i=1 ;i<=10;i++){
cards.push(i);
cards.push(i); //1-10が2枚ずつの配列を
cards.shuffle();
}
##トランプを表示させる
読み込み際に以下のhtmlを出力するようにjsで記述できればOKです。
<table id="table">
<tr>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
</tr>
<tr>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
</tr>
<tr>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
</tr>
<tr>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
<td class="card back"></td>
</tr>
</table>
元々のhtmlは
<body onload="init()">
<h2>経過時間:<span id="time">0</span>秒</h2>
</body>
前回の15puzzleにもありましたがこのような記述となります。
//初期化
funcion init(){
var table = document.getElementById("table")
for (var i =0; i<4; i++){
var tr = document.createElement("tr")//
for( var j =0;j<5;J++){
var td=document.createElement("td");//tdを作成
td.className = "card back";
td.number = cards[i*5+j]; //0-19まで すでに数字はバラバラにしておく必要がある。
td.onclick = flip; //flip関数を設定。後ほど記述
tr.appendChild(td); // trのお尻にtdの閉じタグ
}
table.appendChild(tr); tableのお尻にtrの閉じタグ
}
}
また開いたと同時に経過時間を表示させるために、
1秒おきに時間を取得して、開いた時間と引き算をして経過時間を表すtick関数も走らせます。
startTime = new Date();
timer = setInterval(tick,1000);
function tick(){
var now = new Date();//今時間をnowに入れる
var elapsed = Math.floor((now.getTime()-startTime.getTime())/1000);
document.getElementById("time").textContent = elapsed;
}
}
##トランプの裏返しの処理
oncilckで設定したflip関数を走らせます。
funciont flip(e){
var src = e.srcElement //押したtdの情報が取れます。
var num = src.number //initでnumberを値を設定しました。
src.className = "card";
src.textContent = num; //値をtextContentに入れて表示されます。
//1枚目
if(prevCard ==null){ //1枚目では未定義です。
prevCard = src;
return;
}
//2枚目
if(preCard.number ==num){//番号が一致
if(++score ==10){ //1ペアになれば、1追加
clearInterval(timer) //10ペア完成したら タイマーを止める。
}
prevCard = null;
トランプをめくったときには、className="card"となり表を向いた表示がされます。
ただ数字が一致しない場合はclassName = "card back"と裏を向く処理が必要です。
preCardと構造が同じならif(preCard == num)があるのでそれのelseで、裏返しの処理となります。
else{
src.className = "card back"; 2枚目を裏に
src.textContent ="";
prevCard.className = "card back";
prevCard.textContent ="";
prevCard = null;初期化
}
プログラムは瞬時に働くので、これだと瞬時に表に戻ってしまいます。
前引いた番号を自分で覚えるのが神経衰弱の面白さなので、1秒間待ってから消す作業に移ります。
setTimeout(function(){
src.className = "card back";
src.textContent = "";
prevCard.className ="card back";
prevCard.textContent ="";
prevCard =null;
},1000) //1秒後に実行
ところでsetTimeoutには戻り値があります。
戻り値timeId (数字)です。
setTimeoutで実行した処理を止めるため
clearTimeout(timeId)でプログラムを止めることができます。
setTimeoutが実際にプログラムが動きだす前から、timeIdを吐き出しています。
timeId = setTimeout(処理、100000)なら、100000を待たなくてもコードがそこを通れば
timeIdは出ます。
書籍ではこのような記述がされています。
flipTimer =setTimeout(function(){
src.className = "card back";
src.textContent = "";
prevCard.className ="card back";
prevCard.textContent ="";
prevCard =null;
flipTimer = null;
},1000) //1秒後に実行
中のfunctionが実行される前から、setTimeoutは戻り値を返しますので
flipTimerにはtimeIdを持つわけです。
そして実際にfunctionが走ると、flipTimerをnullにされます。
flipTimerが値が持ってる1秒間は、他のトランプをクリックしても開かせない処理に。
flipTimerが値を持っていない時は、2枚は裏に戻ったので、クリックしたら開く処理に。
function flip(e){
var src =e.srcElement;
//fliptimerが値があるのは、2枚開いてる間 or すでに表になってるカードを押してる
if(flipTime ||src.textContent !=""){
return; //何もしない
}