【初心者向け】第六回 メモ帳だけでゲーム作ってみた〈神経衰弱編〉

今回も、前回までと同様に、パソコンにある「メモ帳」だけを使って、トランプのゲームの「神経衰弱」を作っていきたいと思います!

前回の記事をまだ読んでいない方は、先にそちらを是非読んでみてください!


今回作るもの

前回は、エンターキーを押すことによってカードを裏返すコードを組みましたね!

  1. 準備編
  2. カードの枠を表示させよう!
  3. カードの数字を表示させよう!
  4. キー入力で動かせるようにしよう!
  5. キー入力でカードをひっくり返すようにしよう! ←前回
  6. 乱数を使ってカードを並べ替えよう! ←今回

そして今回は、ゲームを始めたときにカードをシャッフルして、神経衰弱として遊べるようにしていきたいと思います!

完成イメージは以下の通りです!

今回で、神経衰弱を完成させ、遊ぶことができるようになります!

(カードのシャッフルは、完全にランダムで行われるようにするので、クリアするのも一苦労です💦)


今回必要になる知識

今回はコードを組んでいく上で、1つだけ必要になってくる知識があります!

それが、乱数です!

乱数について、下の記事で詳しく解説したので、乱数についてあまり知らない人は、先にそちらを是非読んでみてください!

【誰でもわかる!】乱数とは

プログラミングを勉強し、実際にゲームを作ろうとしたときに出てくる「乱数」に皆さんは困ったことがありませんか? …


コードを書いていこう!

ここからは、前回までと同様に、またまたメモ帳にコードを書いていきましょう!

まず初めに、シャッフルをする前に前回のコードでは少し不具合が起きる可能性があるので、そちらを先に解消していきたいと思います!


二枚目をめくってから裏返すまで操作できないようにする

二枚目のカードが一枚目のカードの数字と違うときに1秒間裏返したままにするというコードを前回組みました。

ですが、前回のコードのままでは、その一秒間の間に矢印キーでポインターを動かすとおかしくなってしまいます。

なので、それを防ぐために、

二枚目をめくってからそれをもとに戻すまでの1秒間を操作できないようにします。

まずは、変数を一つだけ作ります。

…
let flipped = false;

let stop = false;
…

今回、「stop」という変数を作りました。

「stop」が「false」の時は、操作ができる状態にして、「true」の時に操作ができないようにしたいと思います。

なので次に、条件分岐を使って、「stop」が「false」の時だけ操作ができるようにしましょう。

…
if (stop == false) {

  if (e.key == "ArrowRight") {
    if (x <= 11) {
      x = x + 1;
    }
  }else if (e.key == "ArrowLeft") {
    if (x >= 1) {
      x = x - 1;
    }
  }else if (e.key == "ArrowDown") {
    if (y <= 2) {
      y = y + 1;
    }
  }else if (e.key == "ArrowUp") {
    if (y >= 1) {
      y = y - 1;
    }
  }else if (e.key == "Enter"){
    if (flip[y][x] == false) {
      flip[y][x] = true;
      if (flipped == false) {
        flipped = true;

        memory_x = x;
        memory_y = y
      }else if (flipped == true) {
        flipped = false;
        if (card[y][x][1] != card[memory_y][memory_x][1]) {
          stop = true;
          setTimeout("flipCards()", 1000);
        }
      }
    }
  }

}

少しややこしいですが、操作するための if文と else if文をすべて、

if (stop == false) {
  操作するための if文と else if文
}

のような、if文で囲いました。

「{」と「}」の位置がすごくややこしいので、エラーが出たらそこをチェックしましょう!

あとは最後に、2枚目のカードをひっくり返したときに「stop」を「true」に変えて、その2枚を元に戻す時に、「false」に戻すようにしましょう。

…
if (card[y][x][1] != card[memory_y][memory_x][1]) {
  stop = true;
  setTimeout("flipCards()", 1000);
}
…
…
function flipCards() {
  stop = false;
  flip[y][x] = false;
  flip[memory_y][memory_x] = false;

  CONTEXT.clearRect(0, 0, 1400, 500);
  drawCard();
}
…

これで、2枚目をめくってからひっくり返すまでの1秒間、どのキーを押しても動かなくなるはずです!

これで不具合の解消は完了ですね!


カードをシャッフルする

というわけで、本題です。

カードをシャッフルをランダムにシャッフルするには、乱数をうまく使います。

ですが、本題に入る前に一つだけ解説しておきたいことがあるのでそちらを先にします。


カードを入れ替える方法

プログラミングにおいて変数の中に入っている数字を入れ替えることって意外と難しいんです。

例えば次の例を見てみましょう。

let a = 12;
let b = 4;

このように、変数a, bがあったとしましょう。

そしてこれらの数字を入れ替えたい、つまり、「a を 4 に、b を 12」にしたいとしましょう。

すると、下のようなコードになりそうですね。

let a = 12;
let b = 4;

a = b;
b = a;

a を b の値に、b を a の値にしたいので、これでよさそうですが、これではだめです!

なぜだかわかるでしょうか?

「a = b;」となるので、その時点で「a = 12」「b = 12」となってしまい、4という数字が消えてしまいます。

そうこれが問題ですね。

数字の入れ替えをしようとしているのに、その数字が消えてしまったら元も子もありません。

なので、プログラミングにおいて、変数の入れ替えには下のようにします。

let a = 12;
let b = 4;

let c = a;

a = b;
b = c;

このように、新しい変数を作って、そこに消えないように数字を記憶させます。

最初は、少しややこしいかもしれませんが、意外と大事だったりしますので、しっかり覚えてみましょう!


「♤1」をランダムな場所に入れ替える

先ほどの入れ替えの説明はなんだったのかといわれそうですが、もう少しで使うのでお待ちください。

というわけで、いきなりすべてのカードをシャッフルするのは難しいので、まず初めに、「♤1」(=card[0][0]の場所)をランダムな場所と入れ替えてみましょう。

ランダムな場所と入れ替えるには、「0から3を出す乱数」と「0から12を出す乱数」が必要ですが、作れますか?

そして、なぜそれが必要になるかも考えてみましょう!

まず、「0から3を出す乱数」と「0から12を出す乱数」はこのように作りますね!

let a = Math.floor(Math.random() * 4);
let b = Math.floor(Math.random() * 13);

Math.floor(=切り捨て)をうまく使いこのように書けますね!

そして例えば、a が 3 になり、b が 2 になったときは、

「♤1」を「♡4」」と入れ替えるようにします!

先ほどの乱数をうまく使い、入れ替えるコードを書いて見ると…

let a = Math.floor(Math.random() * 4);
let b = Math.floor(Math.random() * 13);

let c = card[0][0];

card[0][0] = card[a][b];
card[a][b] = c;

のようになりますね!

これで、コードを実行するたびに、「♤1」がある場所(=card[0][0])がランダムで、別の場所と入れ替わります。

あとは、これを「♢K」(=card[3][12])まで、繰り返しをうまく使って書きます。

let card = [
  ["♤A", "♤2", "♤3", "♤4", "♤5", "♤6", "♤7", "♤8", "♤9", "♤10", "♤J", "♤Q", "♤K"],
  ["♧A", "♧2", "♧3", "♧4", "♧5", "♧6", "♧7", "♧8", "♧9", "♧10", "♧J", "♧Q", "♧K"],
  ["♡A", "♡2", "♡3", "♡4", "♡5", "♡6", "♡7", "♡8", "♡9", "♡10", "♡J", "♡Q", "♡K"],
  ["♢A", "♢2", "♢3", "♢4", "♢5", "♢6", "♢7", "♢8", "♢9", "♢10", "♢J", "♢Q", "♢K"]
];

for (let i = 0; i < 4; i++) {
  for (let j = 0; j < 13; j++) {
    let a = Math.floor(Math.random() * 4);
    let b = Math.floor(Math.random() * 13);

    let c = card[i][j];

    card[i][j] = card[a][b];
    card[a][b] = c;
  }
}

なぜこうなるかを少しだけ考えてから、多次元配列の「card」の下に書いて見ましょう!

これで、カードは完全にシャッフルされるはずです!

実際に実行してみて、神経衰弱で遊んでみましょう!


うまくいかなかった方向け

うまくいかなかった方は、まずエラーが出ていないか確認しましょう!

エラーの確認方法については、別の記事で詳しくまとめたので、ぜひそちらを参考にしてください!

それでもうまくいかなければ、下のサンプルコードをダウンロードして、自分のコードを比較してみましょう!

完成!

ということで、これで「神経衰弱」の完成です!

神経衰弱として、十分遊べるゲームができましたね!

お友達と交代しながら遊ぶこともできますが、1人でタイムアタックすることもできます!

是非、ゲームのスクリーンショットなどと共に感想を聞かせてください!

コメントやTwitterにどんなことでもいいので、ご感想いただけたらすごく喜びます!

ということで、長くなってしまいましたが、

最後まで読んでいただきありがとうございました!

このブログでは、ほかの方法でゲームを作ったり、様々なゲームの紹介をしています!

おすすめの記事:

また、ほかにもメモ帳を使ったプログラミングをお探しの方は、まとめたページがあるので、そちらもぜひ見てください!

クリックで飛べますメモ帳プログラミング一覧