【PHP】確認問題4-☆2:宝探しゲーム

記事内に商品プロモーションを含む場合があります

この記事の練習問題で使用する知識:
基礎文法(レッスン1)、制御構造(レッスン2)、関数(レッスン3)、データ構造(レッスン4)、クラス(レッスン5)

PHPのゲームコード一覧はこちら

<<前のページ PHP記事一覧 次のページ>>

確認問題:PHPで宝探しゲームを作ろう

宝探しゲームを作成しましょう。

このゲームでは5×5のグリッドに隠された宝物を探します。ユーザーは数字を入力して宝の位置を指定し、ヒントをもとに宝を見つけ出します。

ヒントとグリッドの更新情報を表示しながら、宝を見つけるまでゲームを続けます。

この問題の要件

以下の要件に従ってコードを完成させてください。

  • 定数 GRID_SIZE を 5 として定義すること。
  • 5×5 のグリッドを初期化し、各セルに1から25までの番号を割り当てること。
  • グリッドを表示する関数 displayGrid() を作成し、各セルの状態を出力すること。
  • 宝の位置をランダムに決定すること。
  • ユーザーの入力を受け取り、1から25までの数字として処理すること。
  • 入力された数字を x, y 座標に変換すること。
  • 宝の位置に応じて、方向(上、下、左、右)をヒントとして表示する関数 giveHint() を作成すること。
  • ユーザーに3回の試行を許可し、試行ごとにヒントを提供すること。
  • 宝が発見された場合は「おめでとうございます!」を表示し、グリッドを更新して終了すること。
  • すべての試行で宝を発見できなかった場合は「チャンスを使い切りました。」を表示して終了すること。

ただし、以下のような実行結果となるコードを書くこと。

*****↓↓正解コードの実行結果の例↓↓*****

宝探しゲームへようこそ!1から25までの数字で宝を探し当ててください。
宝を探すチャンスは3回です。
現在のグリッド:
01 02 03 04 05
06 07 08 09 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

1から25のマス番号を入力してください: 7
右 下 に宝があります。
残りのチャンス: 2回
現在のグリッド:
01 02 03 04 05
06 * 08 09 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

1から25のマス番号を入力してください: 18
おめでとうございます!宝を見つけました!
現在のグリッド:
01 02 03 04 05
06 * 08 09 10
11 12 13 14 15
16 17 ☆ 19 20
21 22 23 24 25

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

<?php
define('GRID_SIZE', 5);

// グリッドを初期化
function initializeGrid() {
    /* 【穴埋め問題1】
    ここで5x5のグリッドを初期化し、各セルに1から25までの番号を格納するコードを書いてください。
    */
}

// グリッドを表示
function displayGrid($grid) {
    echo "現在のグリッド:" . PHP_EOL;
    /* 【穴埋め問題2】
    ここで各行をスペース区切りで表示するコードを書いてください。
    */
}

// ヒントを提供
function giveHint($px, $py, $tx, $ty) {
    /* 【穴埋め問題3】
    ここでプレイヤーの位置と宝の位置を比較し、方向のヒントを生成するコードを書いてください。
    */
}

// プレイヤーの入力処理
function getPlayerInput($used) {
    while (true) {
        echo "1から25のマス番号を入力してください: ";
        $input = trim(fgets(STDIN));
        /* 【穴埋め問題4】
        ここでユーザーの入力が1から25の範囲で未使用のものかを判定するコードを書いてください。
        */
    }
}

// ゲーム開始
echo "宝探しゲームへようこそ!1から25までの数字で宝を探し当ててください。" . PHP_EOL;
echo "宝を探すチャンスは3回です。" . PHP_EOL;

// 初期化
/* 【穴埋め問題5】
ここでグリッドを初期化し、宝の位置をランダムに設定するコードを書いてください。
*/
$attempts = 3;
$used = [];
$found = false;

// ゲームループ
/* 【穴埋め問題6】
ここでグリッドを表示し、ゲームのループ処理を実装するコードを書いてください。
*/

この問題の穴埋めコードは以上です。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

【コードの例】宝探しゲーム

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

<?php
define('GRID_SIZE', 5);

// グリッドを初期化
function initializeGrid() {
    $grid = [];
    for ($i = 0; $i < GRID_SIZE; $i++) {
        for ($j = 0; $j < GRID_SIZE; $j++) {
            $grid[$i][$j] = str_pad($i * GRID_SIZE + $j + 1, 2, '0', STR_PAD_LEFT);
        }
    }
    return $grid;
}

// グリッドを表示
function displayGrid($grid) {
    echo "現在のグリッド:" . PHP_EOL;
    foreach ($grid as $row) {
        echo implode(' ', $row) . PHP_EOL;
    }
}

// ヒントを提供
function giveHint($px, $py, $tx, $ty) {
    $hint = [];
    if ($px < $tx) $hint[] = "右";
    if ($px > $tx) $hint[] = "左";
    if ($py < $ty) $hint[] = "下";
    if ($py > $ty) $hint[] = "上";
    return implode(' ', $hint) . " に宝があります。";
}

// プレイヤーの入力処理
function getPlayerInput($used) {
    while (true) {
        echo "1から25のマス番号を入力してください: ";
        $input = trim(fgets(STDIN));
        if (is_numeric($input) && $input >= 1 && $input <= 25 && !in_array($input, $used)) {
            return $input - 1;
        }
        echo "無効な入力です。もう一度入力してください。" . PHP_EOL;
    }
}

// ゲーム開始
echo "宝探しゲームへようこそ!1から25までの数字で宝を探し当ててください。" . PHP_EOL;
echo "宝を探すチャンスは3回です。" . PHP_EOL;

// 初期化
$grid = initializeGrid();
$treasureX = rand(0, GRID_SIZE - 1);
$treasureY = rand(0, GRID_SIZE - 1);
$attempts = 3;
$used = [];
$found = false;

// ゲームループ
displayGrid($grid);
while ($attempts > 0 && !$found) {
    // 入力処理
    $input = getPlayerInput($used);
    $used[] = $input;

    $playerX = $input % GRID_SIZE;
    $playerY = intdiv($input, GRID_SIZE);

    // 宝の判定
    if ($playerX == $treasureX && $playerY == $treasureY) {
        echo "おめでとうございます!宝を見つけました!" . PHP_EOL;
        $grid[$playerY][$playerX] = "☆";
        $found = true;
    } else {
        echo giveHint($playerX, $playerY, $treasureX, $treasureY) . PHP_EOL;
        $grid[$playerY][$playerX] = "*";
        $attempts--;
        echo "残りのチャンス: {$attempts}回" . PHP_EOL;
    }

    displayGrid($grid);
}

// 終了メッセージ
if (!$found) {
    echo "残念ながら、チャンスを使い切りました。宝は見つかりませんでした。" . PHP_EOL;
}

正解コードの解説

今回のコードは「宝探しゲーム」を作成するプログラムです。

以下でコードの詳細をブロックごとに分けて解説します。

定数の定義

define('GRID_SIZE', 5);
  • define() 関数は定数を定義します。
  • GRID_SIZE はグリッドのサイズ(5×5)を定義しています。
  • 定数は変更できない値なので、コード内で固定されたサイズを表すときに便利です。

グリッドの初期化

function initializeGrid() {
    $grid = [];
    for ($i = 0; $i < GRID_SIZE; $i++) {
        for ($j = 0; $j < GRID_SIZE; $j++) {
            $grid[$i][$j] = str_pad($i * GRID_SIZE + $j + 1, 2, '0', STR_PAD_LEFT);
        }
    }
    return $grid;
}
  • 多次元配列の作成: $grid は5×5の二次元配列を表します。
  • ループ: 2重ループで各行と列のデータを埋めます。
  • 数値のフォーマット: str_pad() 関数を使用して、1桁の数字を2桁にします(例: 1 → “01”)。

グリッドの表示

function displayGrid($grid) {
    echo "現在のグリッド:" . PHP_EOL;
    foreach ($grid as $row) {
        echo implode(' ', $row) . PHP_EOL;
    }
}
  • グリッドを行ごとに表示します。
  • implode() 関数は配列を文字列に変換し、スペース区切りで表示します。
  • PHP_EOL は改行コードです。環境依存なく改行できます。

ヒントを提供する関数

function giveHint($px, $py, $tx, $ty) {
    $hint = [];
    if ($px < $tx) $hint[] = "右";
    if ($px > $tx) $hint[] = "左";
    if ($py < $ty) $hint[] = "下";
    if ($py > $ty) $hint[] = "上";
    return implode(' ', $hint) . " に宝があります。";
}
  • ヒントの計算: プレイヤーの現在位置と宝の位置を比較し、方向を判定します。
  • ヒントの出力: implode() 関数で複数のヒントを結合して出力します。

ユーザー入力の処理

function getPlayerInput($used) {
    while (true) {
        echo "1から25のマス番号を入力してください: ";
        $input = trim(fgets(STDIN));
        if (is_numeric($input) && $input >= 1 && $input <= 25 && !in_array($input, $used)) {
            return $input - 1;
        }
        echo "無効な入力です。もう一度入力してください。" . PHP_EOL;
    }
}
  • 入力取得: fgets(STDIN) で標準入力を受け取ります。
  • 検証処理:
    1. 入力が数値か?
    2. 範囲内か?
    3. すでに使われていないか?
  • 入力が条件を満たした場合のみ次に進みます。

ゲームの開始設定

$grid = initializeGrid();
$treasureX = rand(0, GRID_SIZE - 1);
$treasureY = rand(0, GRID_SIZE - 1);
$attempts = 3;
$used = [];
$found = false;
  • グリッドを初期化します。
  • 宝の座標を rand() 関数でランダムに設定します。
  • 試行回数や既に選んだ場所を記録する変数を初期化します。

ゲームループ

while ($attempts > 0 && !$found) {
    // 入力取得と処理
    $input = getPlayerInput($used);
    $used[] = $input;

    $playerX = $input % GRID_SIZE;
    $playerY = intdiv($input, GRID_SIZE);
  • ループ条件: 試行回数が残っている間、宝を探します。
  • 座標変換: 入力された番号をx, y座標に変換します。

宝の判定とヒント表示

    if ($playerX == $treasureX && $playerY == $treasureY) {
        echo "おめでとうございます!宝を見つけました!" . PHP_EOL;
        $grid[$playerY][$playerX] = "☆";
        $found = true;
    } else {
        echo giveHint($playerX, $playerY, $treasureX, $treasureY) . PHP_EOL;
        $grid[$playerY][$playerX] = "*";
        $attempts--;
        echo "残りのチャンス: {$attempts}回" . PHP_EOL;
    }
  • 宝の発見: 座標が一致する場合、宝を見つけたと表示します。
  • ヒント表示: 一致しない場合は方向をヒントとして表示します。
  • 試行回数の減少: 1回失敗するたびに試行回数を減らします。

終了メッセージ

if (!$found) {
    echo "残念ながら、チャンスを使い切りました。宝は見つかりませんでした。" . PHP_EOL;
}

宝を見つけられなかった場合は、ゲーム終了のメッセージを表示します。

まとめ

このコードは、PHPの基本的な文法を活用し、配列やループ、条件分岐、関数の使い方を学べる内容になっています。

  1. 定数とループで配列を作成する方法。
  2. 入力処理と検証の基本。
  3. 条件分岐とヒントの提供を使ったゲームロジックの構築。

このプログラムを応用してさらに複雑なゲームや機能を追加することで、PHPのスキルを磨いていきましょう!

PHPのゲームコード一覧はこちら

<<前のページ PHP記事一覧 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    PHPテキスト&問題集へ戻る
    トップページへ戻る