JavaScript - 神経衰弱ゲームの作り方 Part 1 - カードをシャッフルする
カードを生成して数字を割り振ろう
JavaScript で神経衰弱ゲームを作る方法を、2回に分けて解説します。今回作る神経衰弱は、カードを2枚クリックして数字を揃えていくゲームです。
- Part 1(この記事)では、ゲームに使うカードを用意します。カードは JavaScript で生成し、そのカードに数字をランダムに割り振ります。ゲームを開始するたびに数字の位置が変わるようにすることで、カードをシャッフルします。
- Part 2 では、カードをクリックしてめくれるようにし、数字が揃ったかどうかをチェックします。全部を揃え終わったら自動的にカードをリセットし、繰り返し遊べるようにコーディングします。
この記事を読むと分かること
querySelector()
querySelectorAll()
document.createElement()
classList.add()
appendChild()
forEach()
for
ループ- 配列
- Fisher-Yates アルゴリズム(配列のシャッフル)
サンプルプロジェクト
最初に、神経衰弱ゲームの動きを確認しておきましょう。
- クリックでカードをめくる
- 一度にめくれるのは2枚まで
- 数字が揃ったら、そのカードはクリックに反応しなくなる
- 数字が揃わなかったら、カードは伏せられる
HTML と CSS
まずは HTML です。今回は、JavaScript でカードを生成します。生成したカードを表示するエリア(ゲームコンテナ)を <div>
要素で用意しておきましょう。
<div class="wrapper">
<h1>Memory Game</h1>
<!-- ゲームコンテナ -->
<div class="game-container"></div>
</div>
続いて CSS です。カードを並べて伏せてあるときの見た目(数字は見えない状態)のほかに、カードをめくったときの見た目(数字が見える状態)のクラス show
を用意します。これは、この後の JavaScript で CSS クラスの付け外しをして、カードを裏返すために必要になります。
* {
box-sizing: border-box;
}
body {
margin: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
background-color: lightgray;
}
h1 {
text-align: center;
}
.game-container {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
width: 500px;
}
/* カードを伏せてあるときの見た目 */
.game-card {
width: 100px;
height: 100px;
color: transparent; /* 数字は透明にして見えなくする */
background-color: #4FA0F8; /* カードは青色 */
display: flex;
font-size: xx-large;
font-weight: bold;
align-items: center;
justify-content: center;
border: 2px solid black;
border-radius: 10px;
cursor: pointer;
margin:3px;
-webkit-user-select: none;
user-select: none;
}
/* カードをめくったときの見た目 */
.show {
color: black; /* 数字を黒にする */
background-color: white; /* カードを白にする */
}
JavaScript
さて、次は JavaScript です。今回の Part 1 では、ゲームに使うカードを作成していきます。カードのシャッフルは、カードの位置を変更するのではなく、割り振る数字をランダムに変更することで表現しますよ。
配列と変数
最初に数字を用意しましょう。今回作る神経衰弱ゲームは数字を揃えるゲームなので、数字をペアで配列 numbers
に格納します。
// 数字をペアで格納した配列
const numbers = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6];
配列に保存した数字(要素)の数 numbers.length
は、この後のコードで利用します。変数で参照できるように、cardNumbers
に入れておきましょう。
const numbers = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6];
// 配列の要素数
const cardNumbers = numbers.length;
続いてはカードです。後で生成する複数のカードを格納するための変数 cards
を宣言します。最初は空っぽであることを示すために、null
で初期化してください。
const numbers = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6];
const cardNumbers = numbers.length;
// カード
let cards = null;
Become a Pyxofy Member
最新記事をメールで受信 Pyxofy メンバー限定公開記事が読み放題
いつでも登録解除できます。スパムメールは送りません。
カードを生成する - createCards
配列と変数を用意できたら、カードを生成しましょう。カードを生成する処理を、関数 createCards
として定義していきますよ。
// カードを生成する
function createCards() {
// 1. ゲームコンテナを取得する
// 2. 配列の要素数と同じだけ繰り返してカードを生成する
// 3. すべてのカードを変数に格納する
}
1. ゲームコンテナを取得する
まずは、カードを配置する場所となるゲームコンテナを取得して、変数 gameContainer
で参照できるようにしておきます。
- ゲームコンテナを
querySelector()
メソッドで取得し、変数gameContainer
に格納します。
function createCards() {
// 1. ゲームコンテナを取得する
const gameContainer = document.querySelector('.game-container');
// 2. 配列の要素数と同じだけ繰り返してカードを生成する
// 3. すべてのカードを変数に格納する
}
2. 配列の要素数と同じだけ繰り返してカードを生成する
ここからが、実際にカードを作る処理です。カードは、for
文の繰り返しで生成します。作るカードの枚数は、配列に格納してある数字と同じ数です。
- カードを生成する処理を、配列の要素数
cardNumbers
と同じ数だけ繰り返します。
function createCards() {
const gameContainer = document.querySelector('.game-container');
// 2. 配列の要素数と同じだけ繰り返してカードを生成する
for (let i = 0; i < cardNumbers; i++) {
// カードを生成する処理
// …
}
// 3. すべてのカードを変数に格納する
}
for
文について詳しくは以下の記事をご覧ください。
for
文の中身となる「カードを生成する処理」を書いていきましょう。
document.createElement()
メソッドで<div>
要素を生成し、変数card
に格納します。この<div>
要素一つひとつがカードになります。
function createCards() {
const gameContainer = document.querySelector('.game-container');
// 2. 配列の要素数と同じだけ繰り返してカードを生成する
for (let i = 0; i < cardNumbers; i++) {
// カード(div要素)を生成する
const card = document.createElement('div');
}
// 3. すべてのカードを変数に格納する
}
- 生成したカード(
<div>
要素)に、classList.add()
メソッドでgame-card
クラスを追加します。これによって、CSS で指定したカードの見た目が設定されます。
function createCards() {
const gameContainer = document.querySelector('.game-container');
// 2. 配列の要素数と同じだけ繰り返してカードを生成する
for (let i = 0; i < cardNumbers; i++) {
const card = document.createElement('div');
// クラスを追加する(カードの見た目を設定)
card.classList.add('game-card');
}
// 3. すべてのカードを変数に格納する
}
- 生成したカード(
<div>
要素)を、appendChild()
メソッドでゲームコンテナに追加します。
function createCards() {
const gameContainer = document.querySelector('.game-container');
// 2. 配列の要素数と同じだけ繰り返してカードを生成する
for (let i = 0; i < cardNumbers; i++) {
const card = document.createElement('div');
card.classList.add('game-card');
// ゲームコンテナにカード(div要素)を追加する
gameContainer.appendChild(card);
}
// 3. すべてのカードを変数に格納する
}
ここまでで、カードを12枚作るコードができました。
3. すべてのカードを変数に格納する
生成したすべてのカードをまとめて参照できるよう、変数 cards
に保存しましょう。
- すべてのカードを
querySelectorAll()
メソッドで取得し、変数cards
に格納します。
function createCards() {
const gameContainer = document.querySelector('.game-container');
for (let i = 0; i < cardNumbers; i++) {
const card = document.createElement('div');
card.classList.add('game-card');
gameContainer.appendChild(card);
}
// 3. すべてのカードを変数に格納する
cards = document.querySelectorAll('.game-card');
}
以上で、カードを生成する関数 createCards
を定義できました。関数 createCards
を呼び出すと、ブラウザには以下のように表示されますよ。
配列の数字をシャッフルする - shuffleNumbers
カードを生成したら、今度は、そこに表示する数字を用意します。
神経衰弱が楽しいのは、どこにどの数字が隠れているのかが分からないところですよね。そのためには、配列内に順番にまとめた数字をシャッフルして、ランダムに並べ替える必要があります。配列内の要素をランダムに並べ替えたいときは、Fisher-Yates アルゴリズムを使用すると偏りのないシャッフル結果を得ることができますよ。
// Fisher-Yatesアルゴリズムを利用したシャッフル
// 配列の数字をランダムに並び替える(シャッフルする)
// 配列の最後の要素(i番目)から繰り返し処理を始める
for (let i = cardNumbers - 1; i > 0; i--) {
// 0からi番までのランダムなインデックス(番号)を取得してjに格納する
const j = Math.floor(Math.random() * (i + 1));
// i番目(現在処理中)の要素とj番目の要素を置き替える
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}
すべてのカードに数字を割り振る
ランダムに並べ替えた数字を、生成したカードに割り振りましょう。「数字を割り振る」という処理をカード1枚1枚に行うために、forEach()
メソッドを使用します。
cards
:生成したすべてのカードを参照します。forEach()
:すべてのカードに対して処理を行います。card
:処理の対象となっているカードを表す変数です。i
:処理の対象となっているカードのインデックス(番号)を表します。
for (let i = cardNumbers - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}
// すべてのカードに数字を割り振る
cards.forEach((card, i) => {
// 数字を割り振る
});
forEach()
メソッドで実行する文を書きましょう。シャッフルした配列から一つずつ数字を取得して、カードに表示されるようにしますよ。
numbers[i]
と書くと、処理中のカードと同じインデックス(i
)に対応する数字を、配列numbers
から取得することができます。その値を、処理中のカードのtextContent
プロパティに代入します。
for (let i = cardNumbers - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}
cards.forEach((card, i) => {
// 数字を割り振る
card.textContent = numbers[i]
});
以上で、配列の数字をシャッフルし、すべてのカードに割り振るコードができました。このコードは、神経衰弱ゲームを繰り返し楽しむために、簡単に再利用できるようにします。shuffleNumbers
という名前で関数にまとめておきましょう。
// 数字をシャッフルしてすべてのカードに割り振る
function shuffleNumbers() {
// 配列の数字をシャッフルする
for (let i = cardNumbers - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}
// すべてのカードに数字を割り振る
cards.forEach((card, i) => {
card.textContent = numbers[i]
});
}
では、ここまで書いたコードで数字がどのように表示されるのかを試してみます。ただ、現在のカードは伏せられた状態(数字が透明で見えない)なので、CSS で用意した show
クラスをお試しで追加してから実行してみましょう。
お試し表示:
const numbers = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6];
const cardNumbers = numbers.length;
let cards = null;
function createCards() {
const gameContainer = document.querySelector('.game-container');
for (let i = 0; i < cardNumbers; i++) {
const card = document.createElement('div');
card.classList.add('game-card');
//----------- お試し表示 ----------
card.classList.add('show'); // カードの背景色を白、文字を黒にする
//--------------------------------
gameContainer.appendChild(card);
}
cards = document.querySelectorAll('.game-card');
}
function shuffleNumbers() {
for (let i = cardNumbers - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}
cards.forEach((card, i) => {
card.textContent = numbers[i]
});
}
// カードを生成し、数字を割り振る
createCards();
shuffleNumbers();
結果は下のようになります。コードを再実行するたびに、どこにどの数字が表示されるかはランダムに変わりますよ。
Part 1 で解説した全コード
神経衰弱ゲームの作り方 Part 1 はここまでとなります。解説してきた全コードを下にまとめました。
// カードをシャッフルするコード
// 使用する数字
const numbers = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6];
// 数字の数
const cardNumbers = numbers.length;
// 初めはカード無し
let cards = null;
// カードを生成する
function createCards() {
const gameContainer = document.querySelector('.game-container');
for (let i = 0; i < cardNumbers; i++) {
const card = document.createElement('div');
card.classList.add('game-card');
gameContainer.appendChild(card);
}
// 生成したすべてのカードを変数に格納
cards = document.querySelectorAll('.game-card');
}
// 配列の数字をシャッフルする
function shuffleNumbers() {
for (let i = cardNumbers - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}
// すべてのカードに数字を割り振る
cards.forEach((card, i) => {
card.textContent = numbers[i]
});
}
createCards();
shuffleNumbers();
最後に、下の CodePen で実際に遊んでみてください。
See the Pen JavaScript - Memory Game by Pyxofy (@pyxofy) on CodePen.
まとめ
今回は、JavaScript で神経衰弱ゲームを作る方法の Part 1 として、カードをシャッフルするコードを紹介しました。
カードは HTML で用意することもできますが、ここでは JavaScript の document.createElement()
メソッドで生成しました。カードに何の数字が隠れているかを分からなくするために、Fisher-Yates アルゴリズムを利用して配列の数字をシャッフルできるようにしたので、何度でもゲームを楽しむことができますよ。Part 2 では、カードをクリックしてめくれるようにしてゲームを完成させます。お楽しみに!
最後まで読んでいただき、ありがとうございます。この記事をシェアしてくれると嬉しいです!
SNSで Pyxofy とつながりましょう! LinkedIn・ Threads・ Mastodon・ X (Twitter) @pyxofy・ Facebook
Pyxofy 新規メンバー登録
最新記事をメールで受信 Pyxofy メンバー限定公開コンテンツにアクセス
いつでも登録解除できます。スパムメールは送りません。