PHPで作る間違い探しゲーム

PHPで間違い探しゲームを作成してみましょう。多くのマス目を作成し、その中に同一の文字やをアイコンを配置して1箇所だけ類似の文字を配置します。その中から探し出すというゲームです。

完成イメージ

間違い探しゲームの考え方

1. ゲームの基本ルール

  • 複数のマス目を作る(例:10×10で100マス)
  • ほとんどのマスには同じ文字(例:森)を入れる
  • 1つだけ違う文字(例:林)を入れる
  • ユーザーがどのマスかクリックして、正解かどうか判定する

2. 乱数(ランダム配置)の仕組み

  • まず「全マス分の配列」を作り、全てに同じ文字を入れる
  • そのうち1個だけ違う文字に変えておく
  • shuffle() で配列全体をシャッフル(ランダムに並べ替え)
  • 順番が毎回変わるので、どこに「林」が出るかわからなくなる

3. 正解判定

  • マス目にはリンクを付ける(?choice=番号 のようにGETで番号を送る)
  • クリックされた番号の配列要素が「林」だったら正解!それ以外はハズレ!

フォルダ構成とファイル名

  • 作成フォルダ:php-practice-onlygame
  • 作成ファイル:only01.php
  • 使用CSSファイル(任意):style.cssは任意で作成
only01.php基本コード
<?php
// 文字の設定
$target = "森";
$odd    = "林";
$cols = 10;
$total = $cols * $cols;

//乱数の種(「シャッフルのやり方」をメモ)
if (isset($_GET['seed'])) {
    $seed = $_GET['seed'];
} else {
    $seed = random_int(1, 99999);
}

// 同じseedでシャッフルを再現
mt_srand($seed);

//0 番から $total - 1 個ぶん、すべて '森' の配列を作る」
$cells = array_fill(0, $total - 1, $target);
$cells[] = $odd;
shuffle($cells);

// クリックされた番号を取得
$choice = $_GET['choice'] ?? null;
$message = '';

if ($choice !== null) {
    if ($cells[$choice] === $odd) {
        $message = "正解!";
    } else {
        $message = "ハズレ...";
    }
}
?>
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>間違い探しゲーム</title>
    <style>
        table {
            border-collapse: collapse;
            margin: 1em auto;
        }

        td {
            border: 1px solid #ccc;
            width: 50px;
            height: 50px;
            text-align: center;
            font-size: 2rem;
        }

        .msg {
            text-align: center;
            font-size: 1.2rem;
            margin-bottom: 1em;
        }
    </style>
</head>

<body>
    <?php if ($message): ?>
        <p class="msg"><?= htmlspecialchars($message, ENT_QUOTES, 'UTF-8') ?></p>
    <?php endif; ?>

    <table>
        <?php foreach ($cells as $i => $char): ?>
            <?php if ($i % $cols === 0) echo "<tr>"; ?>
            <td><a href="?choice=<?= $i ?>&seed=<?= $seed ?>"><?= $char ?></a></td>
            <?php if ($i % $cols === $cols - 1) echo "</tr>"; ?>
        <?php endforeach; ?>
    </table>

    <p style="text-align:center;">
        <a href="only01.php">新しい問題</a>
    </p>
</body>

</html>

プログラムの構成と解説

初期設定

$target = "森";
$odd    = "林";
$cols = 10;
$total = $cols * $cols;
  • $target … 通常マスに入れる文字(ここでは「森」)
  • $odd … 間違いの文字(ここでは「林」)
  • $cols … 列数(10列×10行=100マスに設定)
  • $total … マス目の総数($cols × $cols)

乱数の種(シード)を作る

if (isset($_GET['seed'])) {
    $seed = $_GET['seed'];
} else {
    $seed = random_int(1, 99999);
}
  • 最初のアクセス時は random_int() で新しい seed を作る
  • クリック後は GETパラメータの seed を再利用して
  • 同じ並びを再現する

乱数の初期化

mt_srand($seed);

  • PHP の乱数生成器を $seed を使って初期化
  • mt_srand()乱数生成器を初期化する関数 $seed を渡すことで、乱数列のスタート位置を決定
  • 同じ seed で初期化すると、後に呼ばれる mt_rand() 系の乱数を作成する関数が同じ順番の乱数になります
  • これにより、同じ seed なら shuffle() の結果も同じになる

マス目を作る

$cells = array_fill(0, $total - 1, $target);
$cells[] = $odd;
shuffle($cells);
  • array_fill(0, $total - 1, $target)
    • → 「森」を $total-1 個ぶん作って配列に入れる
  • $cells[] = $odd;
    • → 最後に1個だけ「林」を追加
  • shuffle($cells);アルゴリズム込みで安全にシャッフルしてくれる便利関数
    • → 内部的に「乱数」を使って配列をシャッフル 各要素をランダムに入れ替えるときにmt_rand() を呼んでいます。
    • shuffle() 自体に「seed を渡す引数」はありませんが、すでにグローバルな乱数生成器が mt_srand($seed) で初期化されているため、同じ配列を同じ環境で shuffle() すれば、同じ結果になります。

クリックされた場所を判定

$choice = $_GET['choice'] ?? null;
$message = '';

if ($choice !== null) {
    if ($cells[$choice] === $odd) {
        $message = "正解!";
    } else {
        $message = "ハズレ...";
    }
}
  • $_GET['choice'] … クリックされたマスの番号
  • $cells[$choice] … そのマスの文字
  • 「林」だったら「正解!」、それ以外なら「ハズレ…」を表示

盤面の表示

<table>
<?php foreach ($cells as $i => $char): ?>
    <?php if ($i % $cols === 0) echo "<tr>"; ?>
    <td><a href="?choice=<?= $i ?>&seed=<?= $seed ?>"><?= $char ?></a></td>
    <?php if ($i % $cols === $cols - 1) echo "</tr>"; ?>
<?php endforeach; ?>
</table>
  • $cells の中身を1つずつ表示
  • $i % $cols === 0 は、「今表示しているセルが1行の先頭かどうか」を調べています。
    $i は0から始まるインデックスなので、$cols で割り切れるとき(0, $cols, $cols×2…)は新しい行が始まるタイミングです。そのときに <tr> タグを出力して、次のセルから新しい行に配置されるようにしています。
  • <a href="?choice=番号&seed=シード"> でクリックできるリンクを作る
  • これにより、どのマスがクリックされたか番号で分かる

$i % $cols === 0の挙動

具体例($cols = 5 のとき、最初の5行)

$i$i % $cols余り意味出力するタグ
00 % 5 余り 01行目の先頭<tr>
11 % 5 余り 11行目の2列目なし
22 % 5 余り 21行目の3列目なし
33 % 5 余り 31行目の4列目なし
44 % 5 余り 41行目の最後</tr>(次の if 文で出力)
50 % 5 余り 02行目の先頭<tr>
61 % 5 余り 12行目の2列目なし
72 % 5 余り 22行目の3列目なし
83 % 5 余り 32行目の4列目なし
94 % 5 余り 42行目の最後</tr>

ステップアップ:マス目が変更できるようにしよう!

only02.phpに出来上がった01ファイルの内容をコピーし、form要素を追加。マス目を自由に変更できるように追加してみましょう。

only02.phpの解答例はこちら

PHPに下記を追加





マス目を変更するところを追加

    <div class="make_cell">
        <form action="" method="get">
            <p>マス目を変更する</p>
            <input type="hidden" name="seed" value="<?= $seed ?>">
            <input type="number" name="make_cell" value="<?= $cols ?>">
            <button type="submit">作成</button>
        </form>
    </div>

最小値と最大値を設定できるように変更してみましょう。
HTML 属性: minlengthとmaxlength

ステップアップ:文字と答えが変更できるようにしよう

only03.phpに出来上がった02ファイルの内容をコピーし、さらに文字列が変更できるように追加してみましょう!

only03.phpの解答例はこちら
<?php
// 文字の設定
$target = "森";
$odd    = "林";

if (isset($_GET['make_target'])) {
    $target = $_GET['make_target'];
} else {
    $target = "森";
}

if (isset($_GET['make_odd'])) {
    $odd = $_GET['make_odd'];
} else {
    $odd = "林";
}




    <div class="make_cell">
        <form action="" method="get">
            <p>マス目の変更と文字の変更</p>
            <input type="hidden" name="seed" value="<?= $seed ?>">
            <p>
                <label>マス目
                    <input type="number" name="make_cell" value="<?= h($cols) ?>">
                </label>
            </p>
            <p>
                <label>文字
                    <input type="text" name="make_target" value="<?= h($target) ?>">
                </label>
                の中の
                <label>隠れた文字
                    <input type="text" name="make_odd" value="<?= h($odd) ?>">
                </label>

            </p>
            <button type="submit">作成</button>
        </form>
    </div>

</body>

</html>