【PHP入門 / 練習問題】Webじゃんけんゲームを作ろう!(対戦実装)

PHP

前回はじゃんけんゲームの開始時のバリデーションを行いました。
前回までに作成した、じゃんけんゲームに対して、コンピューターと対戦する機能を入れていきましょう。

前回の記事はこちらです。

この記事の目標(作るもの)について

ゲームを開始すると、このように表示されます。

手を選ぶと、コンピュータとの対戦結果が表示されるようにします。

コンピューター対戦を実装する

まずは、ユーザー名がセッションに入っている場合は、変数に戻すようにします。
$userNameは後続の処理で使いたいため、下記のように修正しました。

<?php
    session_start();

    // 入力されたユーザー名の取得
    $userName = isset($_POST['user_name']) ? $_POST['user_name'] : '';

// --- ここから追加する ---
    if (empty($userName) && isset($_SESSION['userName'])) {
        $userName = $_SESSION['userName'];
    }
// --- ここまで追加する ---

次に、コンピューター対戦のロジックを追加します。
下記のようにセッション($_SESSION['userName'])にユーザー名を格納している箇所の配下に追記してください。

    if (0 < count($errorMessages)) {
        $_SESSION["errors"] = $errorMessages;
        header("location: index.php");
        exit;
    }

    $_SESSION['userName'] = $userName;

// --- ここから追加する ---
    $userHand = null;
    $computerHand = null;
    if (isset($_POST['user_hand'])) {
        $userHand = $_POST['user_hand'];

        // コンピューターが出す手を決める
        $handTypes = ['rock', 'scissors', 'paper'];
        $handImages = ['rock' => 'images/janken_gu.png', 'scissors' => 'images/janken_choki.png', 'paper' => 'images/janken_pa.png'];

        $number = mt_rand(0, 2);
        $computerHand = $handTypes[$number];

        $computerHandImage = $handImages[$handTypes[$number]];
        $userHandImage = $handImages[$userHand];

        $winnerFlag = 0;
        if ($computerHand === $userHand) {
        } else if ($computerHand === 'rock' && $userHand === 'scissors') {
            $winnerFlag = 1;
        } else if ($computerHand === 'scissors' && $userHand === 'paper') {
            $winnerFlag = 1;
        }else if ($computerHand === 'paper' && $userHand === 'rock') {
            $winnerFlag = 1;
        } else {
            $winnerFlag = 2;
        }
    }
// --- ここまで追加する ---

解説

最初に下記のように処理を追加しました。

if (empty($userName) && isset($_SESSION['userName'])) {
    $userName = $_SESSION['userName'];
}

ユーザー名がゲーム開始画面から送られてなくて、セッションにユーザー名がある場合は$userNameに格納するようにしています。
画面リロードした場合などに$userNameにセッションに保持されている名前がセットされます。

まずは、対戦に使う変数の初期化です。
最初に$userHand$computerHandをnullで初期化します。

$userHand = null;
$computerHand = null;
if (isset($_POST['user_hand'])) {
    $userHand = $_POST['user_hand'];
// ---- 後続処理 ----
}

次に$_POST['user_hand']が入力されていたら、処理をするようにif文を書いています。
これは、ユーザーの手が選ばれたときに動く処理です。「ユーザーが出す手を選んだら、対戦の処理をする..」というイメージです。
$userHandという変数にユーザーの選んだ手(“rock”,”scissors”,”paper”のいずれか)を格納して、初期処理は完了です。

次にコンピューターの手を決めるところです。

$handTypes = ['rock', 'scissors', 'paper'];
$handImages = ['rock' => 'images/janken_gu.png', 'scissors' => 'images/janken_choki.png', 'paper' => 'images/janken_pa.png'];

$number = mt_rand(0, 2);
$computerHand = $handTypes[$number];

まず、2つの配列を用意しています。$handTypes$handImagesです。
$handTypeがそれぞれの手の文字列の配列です。$handImagesは連想配列で、出す手と画像のパスが紐づいています。

mt_rand関数を使っています。mt_rand(0, 2)0, 1 ,2のいずれかの値がランダムで返ってきます。
ランダムな値を$numberに格納します。

そして、$handTypes[$number]$computerHandに格納しています。
これでコンピューターの手が決まります。$handType配列の0, 1 ,2のいずれかを指定していますね。
“rock”,”scissors”,”paper”のどれかの文字列が格納されます。

その後に、選ばれた手からコンピューターの画像のパスを$computerHandImageに格納しています。
ユーザーの方も、選んだ手からコンピューターの画像のパスを$userHandImageに格納しています。
これは、画面の画像表示に使うためです。

$computerHandImage = $handImages[$handTypes[$number]];
$userHandImage = $handImages[$userHand];

最後に、勝敗判定です。
$winnerFlagを用意して、どちらが勝ったかわかるようにしています。
ユーザーが勝った場合は1を設定していて、コンピュータが勝った場合は2を設定しています。

$winnerFlag = 0;
if ($computerHand === $userHand) {
} else if ($computerHand === 'rock' && $userHand === 'scissors') {
    $winnerFlag = 1;
} else if ($computerHand === 'scissors' && $userHand === 'paper') {
    $winnerFlag = 1;
}else if ($computerHand === 'paper' && $userHand === 'rock') {
    $winnerFlag = 1;
} else {
    $winnerFlag = 2;
}

最初のif文は「if ($computerHand === $userHand)」となっていますね。
同じなので「あいこ」です。この場合は何も設定していません。なので「あいこ」は0ですね。

その後のelse ifでコンピューターが勝つパターンを羅列しています。
その場合は1を設定しているので、コンピューターの勝ちです。

「あいこ」でもコンピューターの勝ちでもない場合は2を設定していますので、ユーザーの勝ちになります。

対戦結果の表示箇所を実装する

勝敗と回数の表示の修正を行います。
コンピューターの手と、プレイヤーの選んだ手を表示させるようにします。

勝敗と回数の表示箇所を実装

下記のように、どちらかが勝ったかの勝敗を記載している箇所と、回数表示の箇所を表示します。

<div class="container">
      <div>
        <div class="fs-2 blue text-danger">xxxさんの勝ち</div>
        <div class="fs-4">n回のうち、n回勝ちました。</div>
      </div

下記のように、一部を削除して、削除箇所に追記してみてください。

<div class="container">
// ---- ここから追加する ----
       <?php if ($userHand && $computerHand): ?>
// ---- ここまで追加する ----
       <div>
// ---- ここから削除する ----
         <div class="fs-2 blue text-danger">xxxさんの勝ち</div>
// ---- ここまで削除する ----
// ---- ここから追加する ----
         <?php if ($winnerFlag === 0): ?>
             <div class="fs-2 blue text-danger">あいこです</div>
         <?php elseif ($winnerFlag === 1): ?>
             <div class="fs-2 blue text-danger">コンピューターの勝ち</div>
         <?php elseif ($winnerFlag === 2): ?>
             <div class="fs-2 blue text-danger"><?php echo $userName; ?>さんの勝ち</div>
         <?php endif; ?>
// ---- ここまで追加する ----
         <div class="fs-4">n回のうち、n回勝ちました。</div>
       </div>

最初にif ($userHand && $computerHand)の箇所ですが、ユーザーとコンピューターの手が決まっていたら、勝敗を表示します。
初回は表示されず、elseの分岐に入ります。elseでの分岐箇所は、後述しています。

「xxxさんの勝ち」と固定で書いていたところを、$winnerFlagを参照して出す内容を変えるようにしています。
HTMLの中に書いているので、コンマでif文を書くようにしました。

この書き方については下記を参照してください。

とりあえず、ここまでで、誰が勝ったかを表示できます。

コンピューターの手とプレーヤーの手の表示を実装

下記のように、コンピューターとプレイヤーが出した手を、チョキとグーで固定表示している箇所を修正します。

<div class="d-flex justify-content-center align-items-center flex-column mt-2">
  <div class="border rounded p-3 mt-2">
      <img src="images/janken_choki.png" width="100" class="rounded" />
  </div>
  <div class="d-flex justify-content-center fs-2 mt-1 mb-1">
      VS
  </div>
  <div class="border rounded p-3">
      <img src="images/janken_gu.png" width="100" class="rounded" />
  </div>
</div>

上記の箇所を、下記のように修正します。

       <div class="d-flex justify-content-center align-items-center flex-column mt-2">
         <div class="border rounded p-3 mt-2">
// ---- ここから削除する ----
            <img src="images/janken_choki.png" width="100" class="rounded" />
// ---- ここまで削除する ----
// ---- ここから追加する ----
            <img src="<?php echo $computerHandImage; ?>" width="100" class="rounded" />
// ---- ここまで追加する ----
         </div>
         <div class="d-flex justify-content-center fs-2 mt-1 mb-1">
             VS
         </div>
         <div class="border rounded p-3">
// ---- ここから削除する ----
             <img src="images/janken_gu.png" width="100" class="rounded" />
// ---- ここまで削除する ----
// ---- ここから追加する ----
             <img src="<?php echo $userHandImage; ?>" width="100" class="rounded" />
// ---- ここまで追加する ----
         </div>
       </div>
// ---- ここから追加する ----
       <?php else: ?>
         <div class="fs-2 blue text-danger">手を選んでください。</div>
       <?php endif; ?>
// ---- ここまで追加する ----
       <form method="post" action="game.php" id="select_hand_form">

それぞれ固定で画像を出していたところを、それぞれの選ばれた手が出るようにしています。
対戦ロジックのところで作成した変数($computerHandImage, $userHandImage)をそれぞれ表示しています。

次に手が選ばれていなかった場合の分岐を書いています。(ここに入るのは初回画面を表示したとき)
$userHand$computerHandが決まっていなかった場合に「手を選んでください。」と出しています。

動作確認する

`http://localhost:8080/php-rock-paper-scissors/index.php` にアクセスして、名前を入力します。
名前を入力したら、始めるボタンを押してゲームを開始します。

このようにコンピュータと対戦できることが確認できました。
PHPじゃんけんゲーム対戦実装の確認

参考

今回は修正箇所が複雑になってしまいました。😅
うまくいかなかった場合や編集箇所などがわからなくなった場合は、完成版のこちらのリポジトリをご確認ください。
[TODO]

終わりに

今回はコンピュータ対戦まで実装しました。
意外と簡単なコードの実装で、処理がかけましたね。

次回はじゃんけんをした回数の実装をしてみたいと思います。

コメント

タイトルとURLをコピーしました