LoginSignup
1
2

More than 3 years have passed since last update.

javascript 神経衰弱ゲーム(自分なりの解説)

Last updated at Posted at 2020-06-24

今回も、書籍ゲームで学ぶJavascript入門で紹介されている
神経衰弱ゲームの知識定着のために自分なりに解説をしてみます。

シャッフル処理

書籍の中では、
まず配列のprototypeの中に、
配列をシャッフルをする処理を記述してあります。(書籍と記述が異なります。)

shuffle.js
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は配列です。

こちらでシャッフルします。

js.shuffte.js
var cards=[]
for(var i=1 ;i<=10;i++){
 cards.push(i); 
 cards.push(i); //1-10が2枚ずつの配列を

cards.shuffle();
}

トランプを表示させる

読み込み際に以下のhtmlを出力するようにjsで記述できればOKです。

card.html
<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は

base.html
  <body onload="init()">
    <h2>経過時間:<span id="time">0</span></h2>
  </body>

前回の15puzzleにもありましたがこのような記述となります。

create.js
//初期化
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関数も走らせます。

tick.js
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関数を走らせます。

flip.js
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で、裏返しの処理となります。

flip.js
else{
src.className = "card back"; 2枚目を裏に
src.textContent ="";
prevCard.className = "card back";
prevCard.textContent ="";
prevCard = null;初期化
}

プログラムは瞬時に働くので、これだと瞬時に表に戻ってしまいます。
前引いた番号を自分で覚えるのが神経衰弱の面白さなので、1秒間待ってから消す作業に移ります。

flip.js
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は出ます。

書籍ではこのような記述がされています。

flip.js
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枚は裏に戻ったので、クリックしたら開く処理に。

flip.js
function flip(e){
var src =e.srcElement;
//fliptimerが値があるのは、2枚開いてる間 or すでに表になってるカードを押してる
if(flipTime ||src.textContent !=""){ 

   return; //何もしない
}

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2