神経衰弱の制作
1〜13までの数字を4つ使った神経衰弱ゲームです。
まずはbody要素内のtable要素にid属性を付与します。
<body onload="init()">
<table id="table"></table>
</body>
次にグローバル変数に配列cardsとpreCard,flipTimerを定義します。
後で制作したカードをシャッフルできるように、Arrayオブジェクトにprototypeプロパティでshuffle関数を定義します。この関数は配列の一番後ろの要素とランダムに取得した要素の値を交換していく関数です。(一番後ろの要素が繰り返すごとに1ずつ減っていくので全てのカードをシャッフルできる)
<script>
let cards = [], prevCard, flipTimer;
Array.prototype.shuffle = function() {
for(let i = this.length - 1; i >= 0; i--) {
let r = Math.floor(Math.random() * (i + 1));
let s = this[i];
this[i] = this[r];
this[r] = s;
}
return this;
}
init関数を定義します。
function init() {
for(let i = 1; i < 14; i++)
{
cards.push(i);
cards.push(i);
cards.push(i);
cards.push(i);
}
cards.shuffle();
const table = document.getElementById("table");
for(let i = 0; i < 4; i++) {
let tr = document.createElement("tr");
for(let j = 0; j < 13; j++) {
let td = document.createElement("td");
let value = cards[i * 13 + j];
td.value = value;
td.className = "card";
td.onclick = flip;
tr.appendChild(td);
}
table.appendChild(tr);
}
}
最初の部分で1〜13までの数字を4つ配列cardsに追加します。
その後、配列cardsを先ほど定義したshuffleメソッドでシャッフルします。
function init() {
for(let i = 1; i < 14; i++)
{
cards.push(i);
cards.push(i);
cards.push(i);
cards.push(i);
}
cards.shuffle();
シャッフルした52枚のカードを並べます。
「let value = cards[i * 13 + j]」で52枚のカードを毎回、変数valueに代入します。td要素にはクリックしたときにflip関数が発火するようにします。
const table = document.getElementById("table");
for(let i = 0; i < 4; i++) {
let tr = document.createElement("tr");
for(let j = 0; j < 13; j++) {
let td = document.createElement("td");
let value = cards[i * 13 + j];
td.value = value;
td.className = "card";
td.onclick = flip;
tr.appendChild(td);
}
table.appendChild(tr);
}
}
次にflip関数を定義します。
function flip(e) {
let src = e.target;
if(flipTimer || src.textContent != "") {
return;
}
let value = src.value;
src.className = "";
src.textContent = value;
if(prevCard == null) {
prevCard = src;
return;
}
if(prevCard.value === value) {
prevCard = null;
clearTimeout(flipTimer);
} else {
flipTimer = setTimeout(function() {
src.className = "card";
src.textContent = "";
prevCard.className = "card";
prevCard.textContent = "";
prevCard = null;
flipTimer = NaN;
}, 1000);
}
}
クリックしたカードのデータを取得できるように、引数に「e」を指定します。
最初のif文では、変数flipTimerに値がある場合とクリックしたカードに数字の表示がある場合に処理を中断するようにしています。
次にクリックしたカードに数字の表示がない場合に自身の値を表示させて、if文で変数prevCardに最初にクリックした1枚目のカードとして値を代入します。
function flip(e) {
let src = e.target;
if(flipTimer || src.textContent != "") {
return;
}
let value = src.value;
src.className = "";
src.textContent = value;
if(prevCard == null) {
prevCard = src;
return;
}
下記ではif文で最初にクリックしたカードと2回目にクリックしたカードが同じ値かどうか判定しています。
同じでなかったときは変数flipTimerにsetTimeoutメソッドを代入します。setTimeoutメソッドは指定した時間が経過した場合に、指定した関数を発火させることができます。ここでは、1000ミリ秒(1秒)経過したら一枚目と二枚目のカードを裏返しに戻します。
一枚目と二枚目が同じかどうかに関係なく、変数prevCardの値を空にします。「flipTimer = NaN」でsetTimeoutが一度発火したら解除されるようにしています。
if(prevCard.value === value) {
prevCard = null;
} else {
flipTimer = setTimeout(function() {
src.className = "card";
src.textContent = "";
prevCard.className = "card";
prevCard.textContent = "";
prevCard = null;
flipTimer = NaN;
}, 1000);
}
下記のコードをコピーしてファイルに貼り付ければ試すことができます。
「.cardセレクタ」のbackground-imageのurl内だけ何か画像を貼り付けてください。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>b</title>
<style>
td {
width: 50px;
height: 75px;
font-size: 30px;
text-align: center;
border: 1px solid black;
border-radius: 5px;
}
.card {
background-image: url(card.png);
background-size: 50px 75px;
}
</style>
<script>
let cards = [], prevCard, flipTimer;
Array.prototype.shuffle = function() {
for(let i = this.length - 1; i >= 0; i--) {
let r = Math.floor(Math.random() * (i + 1));
let s = this[i];
this[i] = this[r];
this[r] = s;
}
return this;
}
function init() {
for(let i = 1; i < 14; i++)
{
cards.push(i);
cards.push(i);
cards.push(i);
cards.push(i);
}
cards.shuffle();
const table = document.getElementById("table");
for(let i = 0; i < 4; i++) {
let tr = document.createElement("tr");
for(let j = 0; j < 13; j++) {
let td = document.createElement("td");
let value = cards[i * 13 + j];
td.value = value;
td.className = "card";
td.onclick = flip;
tr.appendChild(td);
}
table.appendChild(tr);
}
}
function flip(e) {
let src = e.target;
if(flipTimer || src.textContent != "") {
return;
}
let value = src.value;
src.className = "";
src.textContent = value;
if(prevCard == null) {
prevCard = src;
return;
}
if(prevCard.value === value) {
prevCard = null;
} else {
flipTimer = setTimeout(function() {
src.className = "card";
src.textContent = "";
prevCard.className = "card";
prevCard.textContent = "";
prevCard = null;
flipTimer = NaN;
}, 1000);
}
}
</script>
</head>
<body onload="init()">
<table id="table"></table>
</body>
</html>