【PHP】確認問題4-☆1:ナインゲームを作ろう

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

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

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

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

確認問題:PHPでナインゲームを作ろう

ナインゲームという対戦型ゲームを作成しましょう。

このゲームでは、プレイヤーとコンピュータが各自1から9までの牌を持ち、順番に牌を出して得点を競います。

プレイヤーは牌を選択し、コンピュータはランダムに牌を選択します。

各ラウンドで選んだ牌の数値が大きい方がその数値分の得点を獲得し、最終的に得点の高い方が勝利です。

この問題の要件

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

  1. 初期設定
    • プレイヤーとコンピュータの牌はそれぞれ1から9までの整数とする。
    • 得点は初期値0点で開始する。
  2. ゲームの進行
    • 9回のラウンドを行う。
    • 各ラウンドでプレイヤーは手持ちの牌から1つを選択すること。
    • コンピュータはランダムに牌を選択すること。
  3. 得点計算
    • プレイヤーとコンピュータが選んだ牌を比較し、数値の大きい方がその牌の数値分の得点を得る。
    • 同じ値の場合は引き分けとし、得点は発生しない。
  4. 使用済み牌の処理
    • 選択した牌は「使用済み」とし、無効化する(-1で表示)。
  5. 最終結果表示
    • 全ラウンド終了後、プレイヤーとコンピュータの得点を表示し、勝敗を決定すること。

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

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

ナインゲームを開始します!

【第1回戦】
プレイヤーの得点 : 0点
コンピュータの得点: 0点
☆プレイヤーの持ち牌⇒【1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9】
コンピュータの持ち牌⇒【1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9】
持ち牌の中から出す牌を選択してください > 9
プレイヤーの打牌:9 > 4:コンピュータの打牌
プレイヤーは9点獲得

【第2回戦】
プレイヤーの得点 : 9点
コンピュータの得点: 0点
☆プレイヤーの持ち牌⇒【1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,-】
コンピュータの持ち牌⇒【1 ,2 ,3 ,- ,5 ,6 ,7 ,8 ,9】
持ち牌の中から出す牌を選択してください > 5
プレイヤーの打牌:5 < 7:コンピュータの打牌
コンピュータは7点獲得

...(省略)...

ゲーム終了!
プレイヤーの得点 : 45点
コンピュータの得点: 40点
プレイヤーの勝利です!

この問題を解くヒント

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

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

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

<?php
function displayTiles($title, $tiles) {
    echo $title . "⇒【" . implode(" ,", array_map(fn($t) => $t === -1 ? '-' : $t, $tiles)) . "】" . PHP_EOL;
}

function displayScores($playerScore, $computerScore) {
    echo "プレイヤーの得点 : {$playerScore}点" . PHP_EOL;
    echo "コンピュータの得点: {$computerScore}点" . PHP_EOL;
}

function getPlayerChoice($tiles) {
    while (true) {
        echo "持ち牌の中から出す牌を選択してください > ";
        $choice = trim(fgets(STDIN));
        if (in_array($choice, $tiles)) {
            return (int)$choice;
        }
        echo "無効な選択です。再度選択してください。" . PHP_EOL;
    }
}

function getComputerChoice($tiles) {
    return $tiles[array_rand($tiles)];
}

echo "ナインゲームを開始します!" . PHP_EOL;

// 初期設定
/*【穴埋め問題1】
ここでプレイヤーとコンピュータの持ち牌、および得点の初期設定を行うコードを書いてください。
*/

// ラウンド処理
for ($round = 1; $round <= 9; $round++) {
    echo PHP_EOL . "【第{$round}回戦】" . PHP_EOL;

    // 得点と牌の表示
    displayScores($playerScore, $computerScore);
    displayTiles('☆プレイヤーの持ち牌', $playerTiles);
    displayTiles('コンピュータの持ち牌', $computerTiles);

    // 牌の選択
    /*【穴埋め問題2】
    プレイヤーとコンピュータの牌を選択する処理をここに記述してください。
    */

    // 結果表示
    echo "プレイヤーの打牌:{$playerChoice}";
    if ($playerChoice > $computerChoice) {
        echo " > {$computerChoice}:コンピュータの打牌" . PHP_EOL;
        $playerScore += $playerChoice;
        echo "プレイヤーは{$playerChoice}点獲得" . PHP_EOL;
    } elseif ($playerChoice < $computerChoice) {
        echo " < {$computerChoice}:コンピュータの打牌" . PHP_EOL;
        $computerScore += $computerChoice;
        echo "コンピュータは{$computerChoice}点獲得" . PHP_EOL;
    } else {
        echo " = {$computerChoice}:コンピュータの打牌" . PHP_EOL;
        echo "引き分けです。得点はなし" . PHP_EOL;
    }

    // 使用した牌を無効化
    /*【穴埋め問題3】
    使用済みの牌を無効化するコードをここに記述してください。
    */
}

// 最終結果
echo PHP_EOL . "ゲーム終了!" . PHP_EOL;
displayScores($playerScore, $computerScore);

if ($playerScore > $computerScore) {
    echo "プレイヤーの勝利です!" . PHP_EOL;
} elseif ($playerScore < $computerScore) {
    echo "コンピュータの勝利です!" . PHP_EOL;
} else {
    echo "引き分けです!" . PHP_EOL;
}

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

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

【コードの例】ナインゲーム

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

正解コードの例

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

<?php
function displayTiles($title, $tiles) {
    echo $title . "⇒【" . implode(" ,", array_map(fn($t) => $t === -1 ? '-' : $t, $tiles)) . "】" . PHP_EOL;
}

function displayScores($playerScore, $computerScore) {
    echo "プレイヤーの得点 : {$playerScore}点" . PHP_EOL;
    echo "コンピュータの得点: {$computerScore}点" . PHP_EOL;
}

function getPlayerChoice($tiles) {
    while (true) {
        echo "持ち牌の中から出す牌を選択してください > ";
        $choice = trim(fgets(STDIN));
        if (in_array($choice, $tiles)) {
            return (int)$choice;
        }
        echo "無効な選択です。再度選択してください。" . PHP_EOL;
    }
}

function getComputerChoice($tiles) {
    return $tiles[array_rand($tiles)];
}

echo "ナインゲームを開始します!" . PHP_EOL;

// 初期設定
$playerTiles = range(1, 9);
$computerTiles = range(1, 9);
$playerScore = 0;
$computerScore = 0;

for ($round = 1; $round <= 9; $round++) {
    echo PHP_EOL . "【第{$round}回戦】" . PHP_EOL;

    // 得点と牌の表示
    displayScores($playerScore, $computerScore);
    displayTiles('☆プレイヤーの持ち牌', $playerTiles);
    displayTiles('コンピュータの持ち牌', $computerTiles);

    // 牌の選択
    $playerChoice = getPlayerChoice(array_diff($playerTiles, [-1]));
    $computerChoice = getComputerChoice(array_diff($computerTiles, [-1]));

    // 結果表示
    echo "プレイヤーの打牌:{$playerChoice}";
    if ($playerChoice > $computerChoice) {
        echo " > {$computerChoice}:コンピュータの打牌" . PHP_EOL;
        $playerScore += $playerChoice;
        echo "プレイヤーは{$playerChoice}点獲得" . PHP_EOL;
    } elseif ($playerChoice < $computerChoice) {
        echo " < {$computerChoice}:コンピュータの打牌" . PHP_EOL;
        $computerScore += $computerChoice;
        echo "コンピュータは{$computerChoice}点獲得" . PHP_EOL;
    } else {
        echo " = {$computerChoice}:コンピュータの打牌" . PHP_EOL;
        echo "引き分けです。得点はなし" . PHP_EOL;
    }

    // 使用した牌を無効化
    $playerTiles[array_search($playerChoice, $playerTiles)] = -1;
    $computerTiles[array_search($computerChoice, $computerTiles)] = -1;
}

// 最終結果
echo PHP_EOL . "ゲーム終了!" . PHP_EOL;
displayScores($playerScore, $computerScore);

if ($playerScore > $computerScore) {
    echo "プレイヤーの勝利です!" . PHP_EOL;
} elseif ($playerScore < $computerScore) {
    echo "コンピュータの勝利です!" . PHP_EOL;
} else {
    echo "引き分けです!" . PHP_EOL;
}

正解コードの解説

今回作成したPHPコードは、ナインゲームという対戦型ゲームをシミュレートするものです。

この解説ではコードをブロックごとに分け、初心者向けに分かりやすく説明します。

初期設定と関数の定義

function displayTiles($title, $tiles) {
    echo $title . "⇒【" . implode(" ,", array_map(fn($t) => $t === -1 ? '-' : $t, $tiles)) . "】" . PHP_EOL;
}

この関数は、プレイヤーやコンピュータの持ち牌を表示する役割を持ちます。

  • implode()関数: 配列の要素を文字列に変換して連結します。
  • array_map()関数: 配列内の各要素に処理を施します。
  • 三項演算子 (? :): 条件式で「-1」の場合は「-」を表示し、それ以外はその数値を表示します。
function displayScores($playerScore, $computerScore) {
    echo "プレイヤーの得点 : {$playerScore}点" . PHP_EOL;
    echo "コンピュータの得点: {$computerScore}点" . PHP_EOL;
}

この関数はプレイヤーとコンピュータの得点を表示します。

  • 文字列内で変数を埋め込む: {$変数名} と記述することで変数の値を文字列内に挿入できます。
  • PHP_EOL: プラットフォームに依存しない改行コードを出力します。

プレイヤーとコンピュータの選択処理

function getPlayerChoice($tiles) {
    while (true) {
        echo "持ち牌の中から出す牌を選択してください > ";
        $choice = trim(fgets(STDIN));
        if (in_array($choice, $tiles)) {
            return (int)$choice;
        }
        echo "無効な選択です。再度選択してください。" . PHP_EOL;
    }
}

この関数は、プレイヤーが牌を選択する処理を担当します。

  • fgets(STDIN): 標準入力から1行分のデータを取得します。
  • trim(): 入力された文字列の前後の空白や改行を取り除きます。
  • in_array(): 配列内に指定した値が存在するかをチェックします。
  • 無限ループ (while(true)): 条件が常に真のため、正しい入力が行われるまで繰り返します。
function getComputerChoice($tiles) {
    return $tiles[array_rand($tiles)];
}

コンピュータはランダムに牌を選択します。

  • array_rand(): 配列からランダムにキーを取得します。

メイン処理の開始

$playerTiles = range(1, 9);
$computerTiles = range(1, 9);
$playerScore = 0;
$computerScore = 0;
  • range(1, 9): 1から9までの整数を含む配列を生成します。
  • 初期得点は0点に設定します。

ラウンドごとの処理

for ($round = 1; $round <= 9; $round++) {
    echo PHP_EOL . "【第{$round}回戦】" . PHP_EOL;
  • forループ: 1から9までループを繰り返し、9回戦行うように設定します。
  • 各ラウンドの開始時にラウンド数を表示します。

牌の選択と得点処理

$playerChoice = getPlayerChoice(array_diff($playerTiles, [-1]));
$computerChoice = getComputerChoice(array_diff($computerTiles, [-1]));

array_diff(): 配列の要素から「-1」を除外します。これにより未使用の牌だけが選択可能になります。

if ($playerChoice > $computerChoice) {
    echo " > {$computerChoice}:コンピュータの打牌" . PHP_EOL;
    $playerScore += $playerChoice;
    echo "プレイヤーは{$playerChoice}点獲得" . PHP_EOL;
} elseif ($playerChoice < $computerChoice) {
    echo " < {$computerChoice}:コンピュータの打牌" . PHP_EOL;
    $computerScore += $computerChoice;
    echo "コンピュータは{$computerChoice}点獲得" . PHP_EOL;
} else {
    echo " = {$computerChoice}:コンピュータの打牌" . PHP_EOL;
    echo "引き分けです。得点はなし" . PHP_EOL;
}
  • 条件分岐 (if-elseif-else) によって、得点を計算します。
  • +=: 得点を加算します。

使用済み牌の処理

$playerTiles[array_search($playerChoice, $playerTiles)] = -1;
$computerTiles[array_search($computerChoice, $computerTiles)] = -1;
  • array_search(): 指定した値のインデックスを検索します。
  • 使用済みの牌は「-1」に置き換えて無効化します。

最終結果の表示

if ($playerScore > $computerScore) {
    echo "プレイヤーの勝利です!" . PHP_EOL;
} elseif ($playerScore < $computerScore) {
    echo "コンピュータの勝利です!" . PHP_EOL;
} else {
    echo "引き分けです!" . PHP_EOL;
}

最終的な得点を比較し、勝敗または引き分けを判定します。

まとめ

このコードでは、PHPの配列操作、条件分岐、ユーザー入力処理、ループ処理などを組み合わせてゲームを実現しました。

このコードはゲーム要素を通じてPHPの基本文法を学べる良い練習問題です。

ぜひこのコードをアレンジして、さらに理解を深めてください!

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

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

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

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

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






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