【PHP】確認問題3-☆1:石取りゲームを作ろう

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

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

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

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

確認問題:PHPで石取りゲームを作ろう

PHPで石取りゲームを作成しましょう。

このゲームでは20個の石をプレイヤーとコンピュータが交互に取り合います。1回のターンで取れる石の最大数は3個です。

最終的に石を取らなければならないプレイヤーが負けとなります。

プログラムは以下の機能を備えます:

  • 現在の石の数を表示する。
  • プレイヤーが取る石の数を入力できる。
  • コンピュータがランダムに石を取る。
  • 勝敗判定を行う。

この問題の要件

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

  1. 初期設定
    • 石の総数を $totalStones = 20 とする。
    • 1度に取れる最大数を $maxPick = 3 とする。
  2. 関数の定義
    • 残りの石の数を表示する関数 displayStones($totalStones) を作成する。
    • プレイヤーの入力を取得し、条件を満たす値のみ受け付ける関数 getPlayerPick($maxPick, $totalStones) を作成する。
    • コンピュータがランダムで石を取る関数 getComputerPick($maxPick, $totalStones) を作成する。
  3. ゲームの進行
    • プレイヤーとコンピュータが交互に石を取る処理を実装する。
    • 取った石の数と残りの石の数を表示する。
    • 石を取った後に勝敗判定を行う。
  4. 終了条件
    • 残りの石が0になった場合、そのターンのプレイヤーが負けと表示する。

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

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

石取りゲームを開始します!
残りの石の数: 20
何個の石を取りますか? (1〜3個): 3
プレイヤーは3個の石を取りました。
残りの石の数: 17
コンピュータは2個の石を取りました。
残りの石の数: 15
何個の石を取りますか? (1〜3個): 3
プレイヤーは3個の石を取りました。
残りの石の数: 12
コンピュータは3個の石を取りました。
残りの石の数: 9
何個の石を取りますか? (1〜3個): 2
プレイヤーは2個の石を取りました。
残りの石の数: 7
コンピュータは3個の石を取りました。
残りの石の数: 4
何個の石を取りますか? (1〜3個): 3
プレイヤーは3個の石を取りました。
残りの石の数: 1
コンピュータは1個の石を取りました。
コンピュータの負けです!
ゲーム終了!

この問題を解くヒント

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

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:「石取りゲームを開始します!」を出力
2:変数$totalStonesに20を代入(石の総数)
3:変数$maxPickに3を代入(一度に取れる最大数)
4:関数displayStonesの定義(引数$totalStonesを受け取る)
  □ 「残りの石の数: {$totalStones}」を出力
5:関数getPlayerPickの定義(引数$maxPick, $totalStonesを受け取る)
  □ whileループを開始(無効入力を繰り返しチェック)
  □ □ 「何個の石を取りますか? (1〜{$maxPick}個): 」を出力
  □ □ 標準入力から値を取得し、整数に変換して変数$pickに代入
  □ □ if文で$pickが条件(1〜$maxPickかつ$totalStones以下)を満たすか判定
  □ □ □ 条件を満たした場合、$pickを返す
  □ □ 条件を満たさない場合、「無効な入力です。再入力してください。」を出力
6:関数getComputerPickの定義(引数$maxPick, $totalStonesを受け取る)
  □ 変数$pickにmin($maxPick, $totalStones)の値を代入
  □ 変数$pickを1〜$pickの範囲でランダムに取得し返す
7:whileループを開始($totalStonesが0より大きい間繰り返す)
  □ displayStones関数を呼び出し、石の状態を表示
  □ プレイヤーのターン開始
  □ □ getPlayerPick関数を呼び出し、プレイヤーの取る石の数を取得
  □ □ $totalStonesから取得した数を減算
  □ □ 「プレイヤーは{$playerPick}個の石を取りました。」を出力
  □ □ if文で$totalStonesが0になったか判定
  □ □ □ 0の場合、「プレイヤーの負けです!」を出力しbreakで終了
  □ displayStones関数を再度呼び出し、石の状態を表示
  □ コンピュータのターン開始
  □ □ getComputerPick関数を呼び出し、コンピュータの取る石の数を取得
  □ □ $totalStonesから取得した数を減算
  □ □ 「コンピュータは{$computerPick}個の石を取りました。」を出力
  □ □ if文で$totalStonesが0になったか判定
  □ □ □ 0の場合、「コンピュータの負けです!」を出力しbreakで終了
8:「ゲーム終了!」を出力

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

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

<?php
echo "石取りゲームを開始します!" . PHP_EOL;

// 初期設定
$totalStones = 20; // 石の総数
$maxPick = 3;      // 一度に取れる最大数

// 現在の石の数を表示する関数
function displayStones($totalStones) {
    echo "残りの石の数: {$totalStones}" . PHP_EOL;
}

// プレイヤーの入力を取得する関数
function getPlayerPick($maxPick, $totalStones) {
    while (true) {
        /*
        【穴埋め問題1】ここでプレイヤーから入力を取得し、整数に変換して返すコードを書いてください。
        */
    }
}

// コンピュータの選択を決定する関数
function getComputerPick($maxPick, $totalStones) {
    /*
    【穴埋め問題2】ここでコンピュータがランダムに石を取る数を決定するコードを書いてください。
    */
}

// ゲーム開始
while ($totalStones > 0) {
    // 石の状態を表示
    displayStones($totalStones);

    // プレイヤーのターン
    $playerPick = getPlayerPick($maxPick, $totalStones);
    $totalStones -= $playerPick;
    echo "プレイヤーは{$playerPick}個の石を取りました。" . PHP_EOL;

    // 勝敗判定
    if ($totalStones == 0) {
        /*
        【穴埋め問題3】ここでプレイヤーの負けを表示するコードを書いてください。
        */
        break;
    }

    // 石の状態を表示
    displayStones($totalStones);

    // コンピュータのターン
    $computerPick = getComputerPick($maxPick, $totalStones);
    $totalStones -= $computerPick;
    echo "コンピュータは{$computerPick}個の石を取りました。" . PHP_EOL;

    // 勝敗判定
    if ($totalStones == 0) {
        /*
        【穴埋め問題4】ここでコンピュータの負けを表示するコードを書いてください。
        */
        break;
    }
}

echo "ゲーム終了!" . PHP_EOL;

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

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

石取りゲームの正解コードと解説

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

正解コードの例

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

<?php
echo "石取りゲームを開始します!" . PHP_EOL;

// 初期設定
$totalStones = 20; // 石の総数
$maxPick = 3;      // 一度に取れる最大数

// 現在の石の数を表示する関数
function displayStones($totalStones) {
    echo "残りの石の数: {$totalStones}" . PHP_EOL;
}

// プレイヤーの入力を取得する関数
function getPlayerPick($maxPick, $totalStones) {
    while (true) {
        echo "何個の石を取りますか? (1〜{$maxPick}個): ";
        $pick = intval(trim(fgets(STDIN)));
        if ($pick >= 1 && $pick <= $maxPick && $pick <= $totalStones) {
            return $pick;
        }
        echo "無効な入力です。再入力してください。" . PHP_EOL;
    }
}

// コンピュータの選択を決定する関数
function getComputerPick($maxPick, $totalStones) {
    $pick = min($maxPick, $totalStones); // 残りの石が少ない場合は調整
    return rand(1, $pick); // ランダムに石を取る
}

// ゲーム開始
while ($totalStones > 0) {
    // 石の状態を表示
    displayStones($totalStones);

    // プレイヤーのターン
    $playerPick = getPlayerPick($maxPick, $totalStones);
    $totalStones -= $playerPick;
    echo "プレイヤーは{$playerPick}個の石を取りました。" . PHP_EOL;

    // 勝敗判定
    if ($totalStones == 0) {
        echo "プレイヤーの負けです!" . PHP_EOL;
        break;
    }

    // 石の状態を表示
    displayStones($totalStones);

    // コンピュータのターン
    $computerPick = getComputerPick($maxPick, $totalStones);
    $totalStones -= $computerPick;
    echo "コンピュータは{$computerPick}個の石を取りました。" . PHP_EOL;

    // 勝敗判定
    if ($totalStones == 0) {
        echo "コンピュータの負けです!" . PHP_EOL;
        break;
    }
}

echo "ゲーム終了!" . PHP_EOL;

正解コードの解説

このコードは「石取りゲーム」を作るプログラムです。

プレイヤーとコンピュータが交互に石を取り合い、最後に石を取った方が負けとなります。

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

初期設定

echo "石取りゲームを開始します!" . PHP_EOL;
$totalStones = 20; // 石の総数
$maxPick = 3;      // 一度に取れる最大数
  • echo:文字列を表示する命令です。この場合「石取りゲームを開始します!」と画面に表示されます。
  • PHP_EOL:改行コードです。環境に応じた改行を追加します。
  • 変数 $totalStones:ゲームで使用する石の総数を設定します。
  • 変数 $maxPick:1回のターンで取れる最大の石の数を設定します。

残りの石を表示する関数

function displayStones($totalStones) {
    echo "残りの石の数: {$totalStones}" . PHP_EOL;
}
  • 関数 displayStones:引数 $totalStones を受け取り、残りの石の数を表示します。
  • {$totalStones}:波括弧 {} を使うことで文字列の中に変数を埋め込むことができます。

プレイヤーの入力処理

function getPlayerPick($maxPick, $totalStones) {
    while (true) {
        echo "何個の石を取りますか? (1〜{$maxPick}個): ";
        $pick = intval(trim(fgets(STDIN)));
        if ($pick >= 1 && $pick <= $maxPick && $pick <= $totalStones) {
            return $pick;
        }
        echo "無効な入力です。再入力してください。" . PHP_EOL;
    }
}
  • while (true):無限ループを作ります。正しい入力があるまで繰り返します。
  • fgets(STDIN):ユーザーからの入力を受け取ります。
  • trim:余分な空白や改行を削除します。
  • intval:文字列を整数に変換します。
  • 条件判定:入力が1〜3の範囲内かつ残りの石以下であるかをチェックします。

コンピュータの選択処理

function getComputerPick($maxPick, $totalStones) {
    $pick = min($maxPick, $totalStones); 
    return rand(1, $pick);
}
  • min:指定した値のうち最小値を返します。ここでは残りの石が最大で取れる数より少ない場合に対応します。
  • rand(1, $pick):1から $pick の間でランダムな数を生成します。

ゲームの進行処理

プレイヤーのターン
$playerPick = getPlayerPick($maxPick, $totalStones);
$totalStones -= $playerPick;
echo "プレイヤーは{$playerPick}個の石を取りました。" . PHP_EOL;
  • getPlayerPick:プレイヤーの入力を受け取ります。
  • $totalStones -= $playerPick:取った石の数だけ残りの石を減らします。
  • 結果の表示:プレイヤーが何個の石を取ったのか表示します。

勝敗判定

if ($totalStones == 0) {
    echo "プレイヤーの負けです!" . PHP_EOL;
    break;
}

if:残りの石が0ならばプレイヤーの負けと表示してループを終了します。

コンピュータのターン

$computerPick = getComputerPick($maxPick, $totalStones);
$totalStones -= $computerPick;
echo "コンピュータは{$computerPick}個の石を取りました。" . PHP_EOL;
  • getComputerPick:コンピュータがランダムに石を取ります。
  • $totalStones -= $computerPick:取った石の分だけ減らします。
  • 結果の表示:コンピュータが取った石の数を表示します。

ゲーム終了条件

if ($totalStones == 0) {
    echo "コンピュータの負けです!" . PHP_EOL;
    break;
}

コンピュータが最後の石を取った場合は負けと判定されます。

ゲーム終了メッセージ

echo "ゲーム終了!" . PHP_EOL;

最後にゲーム終了メッセージを表示します。

まとめ

このプログラムではPHPでの関数、ループ、条件分岐の使い方を学ぶことができます。
ポイントは以下の通りです:

  1. 関数の活用:繰り返し使う処理は関数化することでコードを整理できる。
  2. ユーザー入力の検証:不正な入力を防ぐチェックを入れる。
  3. ランダム処理:コンピュータの動作をランダム化してリアリティを増す。

このコードを通して、プログラムの流れやデータ処理の基礎を学べます。

ぜひ、他のゲームや機能追加に挑戦して理解を深めてください!

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

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

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

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

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






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