【PHP】確認問題3-☆3:モンスターとのバトルゲームを作ろう

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

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

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

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

確認問題:PHPでターン制バトルゲームを体験しよう

プレイヤーとモンスターが戦うターン制バトルゲームを作成しましょう。

プレイヤーは攻撃または防御を選択でき、モンスターは確率に基づいて攻撃を行います。

ゲームはプレイヤーまたはモンスターのHPが0以下になるまで続きます。

この問題の要件

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

  1. プレイヤーの名前は「勇者」、HPは100、攻撃力は20とする。
  2. モンスターの名前は「ドラゴン」、HPは100、攻撃力は40、攻撃成功率は初期値60%とする。
  3. プレイヤーの行動は攻撃(1)または防御(2)から選択する。
    • 攻撃時: モンスターに20ダメージを与える。
    • 防御時: 次のモンスターの攻撃を無効化する。
  4. モンスターは確率に基づいて攻撃を行う。
    • 攻撃成功率は初期値60%。攻撃失敗時には20%上昇する。
    • 成功時はプレイヤーに40ダメージを与える。
  5. ゲームの各ターンで、プレイヤーとモンスターのHPおよびモンスターの攻撃成功率を表示する。
  6. プレイヤーまたはモンスターのHPが0以下になった時点で勝敗を決定し、結果を表示する。

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

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

=== モンスターとのバトルゲーム ===
勇者のHP: 100, ドラゴンのHP: 100, ドラゴンの攻撃成功率: 60%
攻撃するか防御するかを選んでください (1: 攻撃, 2: 防御): 1
勇者はドラゴンに20のダメージを与えた!
ドラゴンの攻撃!
ドラゴンの攻撃が成功!
勇者に40のダメージ!
勇者のHP: 60, ドラゴンのHP: 80, ドラゴンの攻撃成功率: 60%

この問題を解くヒント

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

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

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

1:PHPコードの開始宣言
2:変数$playerNameに”勇者”を代入
3:変数$playerHpに100を代入
4:変数$playerAttackに20を代入
5:変数$playerDefendingにfalseを代入
6:変数$monsterNameに”ドラゴン”を代入
7:変数$monsterHpに100を代入
8:変数$monsterAttackに40を代入
9:変数$monsterSuccessRateに60を代入
10:関数displayStatusの定義(引数:プレイヤー名、プレイヤーHP、モンスター名、モンスターHP、モンスター成功率)
  □ 引数の情報を整形して出力
11:関数playerAttackの定義(引数:モンスターHP参照、プレイヤー攻撃力、プレイヤー名、モンスター名)
  □ モンスターHPからプレイヤー攻撃力を減算
  □ 攻撃結果のメッセージを出力
12:関数playerDefendの定義(引数:プレイヤー防御参照、プレイヤー名)
  □ プレイヤー防御フラグをtrueに設定
  □ 防御選択のメッセージを出力
13:関数monsterAttackの定義(引数:プレイヤーHP参照、モンスター成功率参照、モンスター攻撃力、モンスター名、プレイヤー名、プレイヤー防御フラグ)
  □ モンスターの攻撃開始メッセージを出力
  □ 乱数でモンスター攻撃の成功判定
  □ if文で攻撃成功時の処理
  □ □ プレイヤーが防御している場合、防御成功メッセージを出力
  □ □ 防御していない場合、プレイヤーHPからモンスター攻撃力を減算し、ダメージメッセージを出力
  □ □ モンスター成功率を60にリセット
  □ else文で攻撃失敗時の処理
  □ □ 攻撃失敗メッセージを出力
  □ □ モンスター成功率に20を加算
14:「モンスターとのバトルゲーム」のタイトルを出力
15:while文によるループ開始(プレイヤーHPとモンスターHPが0より大きい間繰り返す)
  □ 関数displayStatusを呼び出し、現在の状態を出力
  □ 「攻撃するか防御するかを選択してください」のメッセージを出力
  □ ユーザー入力を取得し、変数$choiceに代入
16:if文によるプレイヤー選択処理
  □ 変数$choiceが1の場合、playerAttack関数を実行し防御フラグをfalseにリセット
  □ 変数$choiceが2の場合、playerDefend関数を実行
  □ それ以外の場合、無効な入力メッセージを出力しループ継続
17:if文でモンスターHPが0以下かを判定
  □ 倒されたメッセージと勝利メッセージを出力しループ終了
18:monsterAttack関数を呼び出し、モンスターの攻撃処理を実行
19:if文でプレイヤーHPが0以下かを判定
  □ 倒されたメッセージと敗北メッセージを出力

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

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

<?php

// プレイヤー設定
$playerName = "勇者";
$playerHp = 100;
$playerAttack = 20;
$playerDefending = false;

// モンスター設定
$monsterName = "ドラゴン";
$monsterHp = 100;
$monsterAttack = 40;
$monsterSuccessRate = 60;

// ステータス表示関数
function displayStatus($playerName, $playerHp, $monsterName, $monsterHp, $monsterSuccessRate) {
    /*【穴埋め問題1】
    ここでプレイヤーとモンスターのHPおよび攻撃成功率を表示するコードを書いてください。
    */
}

// プレイヤーの攻撃関数
function playerAttack(&$monsterHp, $playerAttack, $playerName, $monsterName) {
    /*【穴埋め問題2】
    ここでモンスターのHPを減らし、ダメージメッセージを出力するコードを書いてください。
    */
}

// プレイヤーの防御関数
function playerDefend(&$playerDefending, $playerName) {
    /*【穴埋め問題3】
    ここでプレイヤーの防御フラグを設定し、防御を選択したことを表示するコードを書いてください。
    */
}

// モンスターの攻撃関数
function monsterAttack(&$playerHp, &$monsterSuccessRate, $monsterAttack, $monsterName, $playerName, $playerDefending) {
    echo "$monsterNameの攻撃!" . PHP_EOL;
    /*【穴埋め問題4】
    ここでモンスターの攻撃成功率に基づく成功判定と、それに応じた処理を記述してください。
    */
}

// ゲーム開始
echo "=== モンスターとのバトルゲーム ===" . PHP_EOL;

while ($playerHp > 0 && $monsterHp > 0) {
    /*【穴埋め問題5】
    ここで現在のステータスを表示する関数を呼び出してください。
    */

    echo "攻撃するか防御するかを選んでください (1: 攻撃, 2: 防御): ";
    $choice = trim(fgets(STDIN));

    if ($choice == 1) {
        /*【穴埋め問題6】
        ここでプレイヤーの攻撃関数を呼び出し、防御フラグをリセットするコードを書いてください。
        */
    } elseif ($choice == 2) {
        /*【穴埋め問題7】
        ここでプレイヤーの防御関数を呼び出すコードを書いてください。
        */
    } else {
        echo "無効な入力です。再度入力してください。" . PHP_EOL;
        continue;
    }

    /*【穴埋め問題8】
    ここでモンスターの死亡判定を行い、勝利メッセージを表示してループを終了するコードを書いてください。
    */

    /*【穴埋め問題9】
    ここでモンスターの攻撃関数を呼び出すコードを書いてください。
    */

    /*【穴埋め問題10】
    ここでプレイヤーの死亡判定を行い、敗北メッセージを表示するコードを書いてください。
    */
}

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

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

ターン制バトルゲームの正解コードと解説

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

正解コードの例

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

<?php

// プレイヤー設定
$playerName = "勇者";
$playerHp = 100;
$playerAttack = 20;
$playerDefending = false;

// モンスター設定
$monsterName = "ドラゴン";
$monsterHp = 100;
$monsterAttack = 40;
$monsterSuccessRate = 60;

// ステータス表示関数
function displayStatus($playerName, $playerHp, $monsterName, $monsterHp, $monsterSuccessRate) {
    echo $playerName . "のHP: " . $playerHp . ", " . $monsterName . "のHP: " . $monsterHp . ", " . $monsterName . "の攻撃成功率: " . $monsterSuccessRate . "%" . PHP_EOL;
}

// プレイヤーの攻撃関数
function playerAttack(&$monsterHp, $playerAttack, $playerName, $monsterName) {
    $monsterHp -= $playerAttack;
    echo $playerName . "は" . $monsterName . "に" . $playerAttack . "のダメージを与えた!" . PHP_EOL;
}

// プレイヤーの防御関数
function playerDefend(&$playerDefending, $playerName) {
    $playerDefending = true;
    echo $playerName . "は防御を選択した!" . PHP_EOL;
}

// モンスターの攻撃関数
function monsterAttack(&$playerHp, &$monsterSuccessRate, $monsterAttack, $monsterName, $playerName, $playerDefending) {
    echo $monsterName . "の攻撃!" . PHP_EOL;
    if (rand(1, 100) <= $monsterSuccessRate) { // 成功
        if ($playerDefending) {
            echo $playerName . "は防御して攻撃を無効化した!" . PHP_EOL;
        } else {
            $playerHp -= $monsterAttack;
            echo $playerName . "に" . $monsterAttack . "のダメージ!" . PHP_EOL;
        }
        $monsterSuccessRate = 60; // 成功率リセット
    } else { // 失敗
        echo $monsterName . "の攻撃がミス!" . PHP_EOL;
        $monsterSuccessRate += 20; // 成功率アップ
    }
}

// ゲーム開始
echo "=== モンスターとのバトルゲーム ===" . PHP_EOL;

while ($playerHp > 0 && $monsterHp > 0) {
    // ステータス表示
    displayStatus($playerName, $playerHp, $monsterName, $monsterHp, $monsterSuccessRate);

    // プレイヤー行動
    echo "攻撃するか防御するかを選んでください (1: 攻撃, 2: 防御): ";
    $choice = trim(fgets(STDIN));

    if ($choice == 1) {
        playerAttack($monsterHp, $playerAttack, $playerName, $monsterName);
        $playerDefending = false; // 防御リセット
    } elseif ($choice == 2) {
        playerDefend($playerDefending, $playerName);
    } else {
        echo "無効な入力です。再度入力してください。" . PHP_EOL;
        continue;
    }

    // モンスター死亡判定
    if ($monsterHp <= 0) {
        echo $monsterName . "は倒された!" . $playerName . "の勝利!" . PHP_EOL;
        break;
    }

    // モンスター行動
    monsterAttack($playerHp, $monsterSuccessRate, $monsterAttack, $monsterName, $playerName, $playerDefending);

    // プレイヤー死亡判定
    if ($playerHp <= 0) {
        echo $playerName . "は倒された…" . $monsterName . "の勝利!" . PHP_EOL;
    }
}

 

正解コードの解説

今回のコードはPHPでターン制のバトルゲームを作成するプログラムです。

プレイヤーは攻撃または防御を選択し、モンスターは確率に基づいて攻撃を行います。

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

初期設定

// プレイヤー設定
$playerName = "勇者";
$playerHp = 100;
$playerAttack = 20;
$playerDefending = false;

// モンスター設定
$monsterName = "ドラゴン";
$monsterHp = 100;
$monsterAttack = 40;
$monsterSuccessRate = 60;
  • 変数宣言: $playerName$playerHp などを使ってプレイヤーとモンスターの初期ステータスを設定します。
  • PHPの変数: $ 記号で変数を定義し、値を代入します。たとえば $playerHp = 100; では $playerHp に100を代入します。
  • 防御フラグ: $playerDefending はプレイヤーが防御状態かどうかを管理します。初期値は false(防御していない)。

ステータス表示関数

function displayStatus($playerName, $playerHp, $monsterName, $monsterHp, $monsterSuccessRate) {
    echo "$playerNameのHP: $playerHp, $monsterNameのHP: $monsterHp, $monsterNameの攻撃成功率: $monsterSuccessRate%" . PHP_EOL;
}
  • 関数の定義: function キーワードで関数を定義します。ここでは displayStatus() という関数を作成。
  • 引数: 関数のカッコ内に $playerName などの引数を指定し、関数内で使用します。
  • 出力: echo 文を使い、プレイヤーとモンスターのステータスを表示します。文字列の結合には . を使用します。

プレイヤーの攻撃と防御関数

function playerAttack(&$monsterHp, $playerAttack, $playerName, $monsterName) {
    $monsterHp -= $playerAttack;
    echo "$playerNameは$monsterNameに$playerAttackのダメージを与えた!" . PHP_EOL;
}
  • 参照渡し: & を付けることで変数の値を直接変更できるようにします。ここでは $monsterHp の値を直接減少させます。
  • 計算と更新: $monsterHp -= $playerAttack; はモンスターのHPを攻撃力分減らします。
function playerDefend(&$playerDefending, $playerName) {
    $playerDefending = true;
    echo "$playerNameは防御を選択した!" . PHP_EOL;
}

防御設定: $playerDefendingtrue に変更して防御状態にします。

モンスターの攻撃関数

function monsterAttack(&$playerHp, &$monsterSuccessRate, $monsterAttack, $monsterName, $playerName, $playerDefending) {
    echo "$monsterNameの攻撃!" . PHP_EOL;
    if (rand(1, 100) <= $monsterSuccessRate) {
        if ($playerDefending) {
            echo "$playerNameは防御して攻撃を無効化した!" . PHP_EOL;
        } else {
            $playerHp -= $monsterAttack;
            echo "$playerNameに$monsterAttackのダメージ!" . PHP_EOL;
        }
        $monsterSuccessRate = 60;
    } else {
        echo "$monsterNameの攻撃がミス!" . PHP_EOL;
        $monsterSuccessRate += 20;
    }
}
  • 乱数の使用: rand(1, 100) で1から100までの乱数を生成します。攻撃成功率と比較して、攻撃が成功するかどうかを決めます。
  • 条件分岐: if 文を使って攻撃の成否を判断します。攻撃成功時はダメージを与え、失敗時は攻撃成功率を増加させます。
  • 防御判定: 防御中ならダメージを無効化します。

ゲームループ

while ($playerHp > 0 && $monsterHp > 0) {
    displayStatus($playerName, $playerHp, $monsterName, $monsterHp, $monsterSuccessRate);
    echo "攻撃するか防御するかを選んでください (1: 攻撃, 2: 防御): ";
    $choice = trim(fgets(STDIN));

    if ($choice == 1) {
        playerAttack($monsterHp, $playerAttack, $playerName, $monsterName);
        $playerDefending = false;
    } elseif ($choice == 2) {
        playerDefend($playerDefending, $playerName);
    } else {
        echo "無効な入力です。再度入力してください。" . PHP_EOL;
        continue;
    }

    if ($monsterHp <= 0) {
        echo "$monsterNameは倒された!$playerNameの勝利!" . PHP_EOL;
        break;
    }

    monsterAttack($playerHp, $monsterSuccessRate, $monsterAttack, $monsterName, $playerName, $playerDefending);

    if ($playerHp <= 0) {
        echo "$playerNameは倒された…$monsterNameの勝利!" . PHP_EOL;
    }
}
  • ループ処理: while 文を使い、プレイヤーとモンスターのHPが0になるまでゲームを繰り返します。
  • ユーザー入力: fgets(STDIN) でプレイヤーの選択を受け取ります。trim() で余分な空白や改行を除去します。
  • 条件分岐: プレイヤーの行動やモンスターの行動によって処理を分岐します。

まとめ

このプログラムでは、PHPの基本的な文法(変数、関数、条件分岐、ループ)を学べます。

また、ゲームを作りながら乱数や参照渡しの使い方も体験できるため、実践的なスキルを磨けます。

初心者はコードを自分で実行し、さまざまなパターンを試しながら動作を確認すると理解が深まります。

ぜひこのコードを土台に、新しい機能を追加してさらに面白いゲームに改良してみてください!

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

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

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

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

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






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