【PHP】確認問題3-☆2:丁半賭博ゲームを作ろう

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

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

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

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

確認問題:PHPで丁半賭博ゲームを作ろう

サイコロを使った丁半賭博ゲームを作成します。

このゲームでは、プレイヤーは所持金を賭け、2つのサイコロの合計が偶数(丁)か奇数(半)かを予想します

予想が当たれば賭け金が増え、外れれば減ります。ゲームは所持金がなくなるか、プレイヤーが終了を選択するまで続きます。

この問題の要件

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

  • 初期所持金を1000円とする。
  • プレイヤーが賭け金を入力できるようにする。
  • 賭け金は現在の所持金以下で、かつ正の値でなければならない。
  • プレイヤーが「丁(0)」または「半(1)」を選択できるようにする。
  • 2つのサイコロの合計値をランダムに生成し、その偶奇を判定する。
  • 予想が当たれば賭け金を追加し、外れれば賭け金を差し引く。
  • 所持金がなくなるか、続行するかどうかの選択をできるようにする。
  • 入力が不正な場合は再入力を求める。
  • 最終所持金を表示し、ゲーム終了のメッセージを表示する。

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

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

丁半賭博ゲームを始めます!
プレイヤーの所持金:1000円
いくらかけますか? ⇒ 300
丁か半か?(丁:0,半:1) ⇒ 0
サイコロの目: 4, 2 ⇒ 丁
あなたの勝ち!賞金は300円

続けますか?(はい:0,いいえ:1) ⇒ 1
最終所持金は1300円でした。丁半賭博ゲームを終わります。

この問題を解くヒント

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

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

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

1:PHPスクリプトの開始宣言
2:関数getBetの定義
  □ whileループで無限ループを開始
  □ □ 「いくらかけますか?」と入力を促すメッセージを表示
  □ □ 標準入力から値を受け取り整数に変換し、変数$betに代入
  □ □ if文で$betが1以上かつ所持金以内であるかを判定
  □ □ □ 条件が真の場合、$betを返す
  □ □ 条件が偽の場合、「無効な入力です!」とエラーメッセージを表示
3:関数getChoiceの定義
  □ whileループで無限ループを開始
  □ □ 「丁か半か?」と入力を促すメッセージを表示
  □ □ 標準入力から値を受け取り整数に変換し、変数$choiceに代入
  □ □ if文で$choiceが0または1であるかを判定
  □ □ □ 条件が真の場合、$choiceを返す
  □ □ 条件が偽の場合、「無効な入力です!」とエラーメッセージを表示
4:関数rollSingleDieの定義
  □ rand関数を使い1から6までの乱数を生成して返す
5:関数askContinueの定義
  □ whileループで無限ループを開始
  □ □ 「続けますか?」と入力を促すメッセージを表示
  □ □ 標準入力から値を受け取り整数に変換し、変数$continueに代入
  □ □ if文で$continueが0または1であるかを判定
  □ □ □ 条件が真の場合、$continueを返す
  □ □ 条件が偽の場合、「無効な入力です!」とエラーメッセージを表示
6:関数choHanGameの定義
  □ 「丁半賭博ゲームを始めます!」と開始メッセージを表示
  □ 変数$moneyに1000を代入し初期所持金とする
  □ whileループで所持金が0より大きい間、ゲームを繰り返す
  □ □ 「プレイヤーの所持金」を表示
  □ □ getBet関数を呼び出し掛け金を設定
  □ □ getChoice関数を呼び出し丁か半かを選択
  □ □ サイコロを2回振って、それぞれの目を$dice1、$dice2に代入
  □ □ サイコロの目の合計を計算し変数$sumに代入
  □ □ 合計が偶数なら「丁」、奇数なら「半」を表示
  □ □ if文で選択と結果が一致するかを判定
  □ □ □ 真の場合、「あなたの勝ち!」を表示し、所持金を増やす
  □ □ □ 偽の場合、「あなたの負け!」を表示し、所持金を減らす
  □ □ 所持金が0より大きい場合はaskContinue関数で継続を確認
  □ □ □ 「いいえ」が選択されたらループを終了
  □ □ 所持金がなくなった場合、「ゲーム終了です。」と表示して終了
7:「最終所持金」とゲーム終了メッセージを表示
8:choHanGame関数を呼び出してゲームを開始

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

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

<?php

function getBet($money) {
    while (true) {
        echo "いくらかけますか? ⇒ ";
        /* 【穴埋め問題1】
        標準入力から値を取得し、整数型に変換して変数$betに代入し、$betが1以上かつ所持金以内であればその値を返すコードを書いてください。
        条件に合わない場合はエラーメッセージを表示します。
        */
    }
}

function getChoice() {
    while (true) {
        echo "丁か半か?(丁:0,半:1) ⇒ ";
        /* 【穴埋め問題2】
        標準入力から値を取得し、整数型に変換して変数$choiceに代入し、$choiceが0または1であればその値を返すコードを書いてください。
        条件に合わない場合はエラーメッセージを表示します。
        */
    }
}

function rollSingleDie() {
    /* 【穴埋め問題3】
    1から6までの乱数を生成し、その結果を返すコードを書いてください。
    */
}

function askContinue() {
    while (true) {
        echo "続けますか?(はい:0,いいえ:1) ⇒ ";
        /* 【穴埋め問題4】
        標準入力から値を取得し、整数型に変換して変数$continueに代入し、$continueが0または1であればその値を返すコードを書いてください。
        条件に合わない場合はエラーメッセージを表示します。
        */
    }
}

function choHanGame() {
    echo "丁半賭博ゲームを始めます!" . PHP_EOL;

    /* 【穴埋め問題5】
    初期所持金を1000円に設定し、ゲームを開始します。
    所持金がある間はループを継続し、ゲームの流れ(掛け金入力、選択入力、サイコロ結果表示、勝敗判定、資金の増減、継続確認)を実行してください。
    所持金がなくなった場合、ゲーム終了メッセージを表示します。
    */
}

choHanGame();

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

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

丁半賭博ゲームの正解コードと解説

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

正解コードの例

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

<?php

function getBet($money) {
    while (true) {
        echo "いくらかけますか? ⇒ ";
        $bet = (int)trim(fgets(STDIN));
        if ($bet > 0 && $bet <= $money) {
            return $bet;
        }
        echo "無効な入力です!所持金以内の正しい金額を入力してください。" . PHP_EOL;
    }
}

function getChoice() {
    while (true) {
        echo "丁か半か?(丁:0,半:1) ⇒ ";
        $choice = (int)trim(fgets(STDIN));
        if ($choice === 0 || $choice === 1) {
            return $choice;
        }
        echo "無効な入力です!0か1を入力してください。" . PHP_EOL;
    }
}

function rollSingleDie() {
    return rand(1, 6); // サイコロを1つ振る
}

function askContinue() {
    while (true) {
        echo "続けますか?(はい:0,いいえ:1) ⇒ ";
        $continue = (int)trim(fgets(STDIN));
        if ($continue === 0 || $continue === 1) {
            return $continue;
        }
        echo "無効な入力です!0か1を入力してください。" . PHP_EOL;
    }
}

function choHanGame() {
    echo "丁半賭博ゲームを始めます!" . PHP_EOL;

    $money = 1000; // 初期所持金

    while ($money > 0) {
        echo "プレイヤーの所持金:" . $money . "円" . PHP_EOL;

        // 掛け金を入力
        $bet = getBet($money);

        // 丁か半かの選択
        $choice = getChoice();

        // サイコロを2回振る
        $dice1 = rollSingleDie();
        $dice2 = rollSingleDie();
        $sum = $dice1 + $dice2;

        echo "サイコロの目: " . $dice1 . ", " . $dice2 . " ⇒ " . ($sum % 2 === 0 ? "丁" : "半") . PHP_EOL;

        // 勝敗判定
        if (($sum % 2 === 0 && $choice === 0) || ($sum % 2 !== 0 && $choice === 1)) {
            echo "あなたの勝ち!賞金は" . $bet . "円" . PHP_EOL;
            $money += $bet;
        } else {
            echo "あなたの負け!" . $bet . "円没収!" . PHP_EOL;
            $money -= $bet;
        }

        // ゲームを続けるか確認
        if ($money > 0) {
            $continue = askContinue();
            if ($continue === 1) {
                break;
            }
        } else {
            echo "所持金がなくなりました。ゲーム終了です。" . PHP_EOL;
            break;
        }
    }

    echo "最終所持金は" . $money . "円でした。丁半賭博ゲームを終わります。" . PHP_EOL;
}

choHanGame();

正解コードの解説

今回のPHPコードは「丁半賭博ゲーム」を実装したものです。

このゲームではユーザーがサイコロの偶数・奇数を予測し、賭けを行います。

正解すれば賞金が増え、外れれば減ります。ここでは、コードをブロックごとに分けて説明します。

賭け金入力処理 (getBet 関数)

function getBet($money) {
    while (true) {
        echo "いくらかけますか? ⇒ ";
        $bet = (int)trim(fgets(STDIN));
        if ($bet > 0 && $bet <= $money) {
            return $bet;
        }
        echo "無効な入力です!所持金以内の正しい金額を入力してください。" . PHP_EOL;
    }
}
  • while (true): 無限ループを作り、ユーザーが正しい入力をするまで繰り返します。
  • fgets(STDIN): 標準入力からユーザーの入力を受け取ります。
  • trim(): 入力の前後の空白や改行を除去します。
  • (int): 入力された文字列を整数に変換します。
  • 条件分岐 (if): 賭け金が0より大きく所持金以内であればその値を返し、そうでない場合は再入力を促します。

丁半選択処理 (getChoice 関数)

function getChoice() {
    while (true) {
        echo "丁か半か?(丁:0,半:1) ⇒ ";
        $choice = (int)trim(fgets(STDIN));
        if ($choice === 0 || $choice === 1) {
            return $choice;
        }
        echo "無効な入力です!0か1を入力してください。" . PHP_EOL;
    }
}
  • 入力ループ (while): ユーザーが0または1を入力するまで繰り返します。
  • === 演算子: 厳密比較を行い、型と値が完全に一致しているかを確認します。
  • 正しい入力があれば選択を返し、不正入力の場合は再度促します。

サイコロを振る処理 (rollSingleDie 関数)

function rollSingleDie() {
    return rand(1, 6);
}
  • rand(1, 6): 1から6までのランダムな整数を返します。サイコロの目を模倣しています。
  • この関数は呼び出されるたびに1つのサイコロの出目を返します。

ゲーム継続確認処理 (askContinue 関数)

function askContinue() {
    while (true) {
        echo "続けますか?(はい:0,いいえ:1) ⇒ ";
        $continue = (int)trim(fgets(STDIN));
        if ($continue === 0 || $continue === 1) {
            return $continue;
        }
        echo "無効な入力です!0か1を入力してください。" . PHP_EOL;
    }
}
  • プレイヤーがゲームを続けるか終了するかを選択します。
  • 正しい入力のみ受け付けるようにし、不正な値は再入力させます。

ゲーム本体 (choHanGame 関数)

function choHanGame() {
    echo "丁半賭博ゲームを始めます!" . PHP_EOL;
    $money = 1000; // 初期所持金

初期値設定: 所持金を1000円にセットします。

掛け金・選択・サイコロ結果の処理

$bet = getBet($money);
$choice = getChoice();
$dice1 = rollSingleDie();
$dice2 = rollSingleDie();
$sum = $dice1 + $dice2;
  • 掛け金入力と選択: 先ほど作成した関数を使って、掛け金と丁半の選択を受け取ります。
  • サイコロ振り: 2つのサイコロを振って合計値を計算します。

結果判定と金額更新

if (($sum % 2 === 0 && $choice === 0) || ($sum % 2 !== 0 && $choice === 1)) {
    echo "あなたの勝ち!賞金は" . $bet . "円" . PHP_EOL;
    $money += $bet;
} else {
    echo "あなたの負け!" . $bet . "円没収!" . PHP_EOL;
    $money -= $bet;
}
  • 偶数か奇数か判定: $sum % 2 === 0 で偶数(丁)、そうでなければ奇数(半)を判定します。
  • 条件分岐: プレイヤーの選択とサイコロ結果を比較して、勝敗を決定します。
  • 勝てば所持金が増え、負ければ減るように更新します。

ゲーム終了判定と最終出力

if ($money > 0) {
    $continue = askContinue();
    if ($continue === 1) {
        break;
    }
} else {
    echo "所持金がなくなりました。ゲーム終了です。" . PHP_EOL;
    break;
}
  • 続行確認: 所持金があれば続行確認、なければゲーム終了です。
  • 終了時の表示: 最終所持金を表示してプログラム終了します。

まとめ

このプログラムではPHPの基本機能である標準入力の受け取りランダム値の生成条件分岐ループ処理などが組み合わさっています。

特にユーザー入力やエラーハンドリングを適切に行う方法、そしてゲームの流れを管理する論理的な構成を学べます。

このコードを理解したら掛け金や勝利条件を変更したり、サイコロを増やすなどして応用してみましょう!

ゲームを作ることで、PHPの基礎力を楽しく身につけることができます。

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

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

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

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

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






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