PHPでじゃんけんゲームをつくる

PHPで簡単なじゃんけんゲームのプログラムを書いてみます。
グー、チョキ、パーの選択を1クリックで済ますためにbuttonを複数設置しました。

環境
PHP
5.6, 7.0

ifを使った判定

まずはifでの条件分岐によるコードです。

<?php
// 結果を代入する変数
$result = false;

// ポスト変数が存在するか
if (isset($_POST['select'])) {
    $janken = array(
        'グー',
        'チョキ',
        'パー'
    );

    // エスケープ
    $player = htmlspecialchars($_POST['select'], ENT_QUOTES, 'UTF-8');

    // 相手の手をランダムで決定
    $com = $janken[array_rand($janken)];

    // 勝敗判定
    if ($player === 'グー' && $com === 'チョキ') {
        $result = '勝ち';
    } elseif ($player === 'グー' && $com === 'グー') {
        $result = 'あいこ';
    } elseif ($player === 'グー' && $com === 'パー') {
        $result = '負け';
    } elseif ($player === 'チョキ' && $com === 'グー') {
        $result = '負け';
    }
    // 以下、チョキとパーのコード省略...
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPでじゃんけんゲーム</title>
</head>
<body>
<p>選んでください。</p>

<form action="" method="post">
    <button type="submit" name="select" value="グー">グー</button>
    <button type="submit" name="select" value="チョキ">チョキ</button>
    <button type="submit" name="select" value="パー">パー</button>
</form>

<?php if ($result) : ?>
    <p>結果</p>

    <p>
    あなた:<?php echo $player; ?><br>
    あいて:<?php echo $com; ?>
    </p>

    <p><?php echo $result; ?>です。</p>
<?php endif; ?>

</body>
</html>

意図した通りに動きましたが、何度も条件分岐を書くのが面倒です。

switchを使った判定

次はswitchを使用して勝敗を判定します。以下、勝敗判定部分のみです。

// 勝敗判定
if ($player === 'グー') {
    switch ($com) {
        case 'チョキ':
            $result = '勝ち';
            break;
        case 'グー':
            $result = 'あいこ';
            break;
        case 'パー':
            $result = '負け';
            break;
    }
} elseif ($player === 'チョキ') {
// 以下、チョキとパーのコード省略...
}

ifの判定コードに比べて見やすくなったかと思います。

コードを改善する

望む挙動のじゃんけんゲームは完成しました。続いて、コードに改善点が無いか見直してみます。

勝敗判定を見直す

「何度も条件分岐を書くのが面倒」と書いたifの勝敗判定を改善してみます。

じゃんけんでは手の組み合わせは「3x3の9通り」ですが、結果は「勝ち・負け・あいこの3通り」しかありません。結果から考えると違った書き方ができそうです。

// あいこ条件
if ($player === $com) {
    $result = 'あいこ';
// 勝ち条件
} elseif (
    $player === 'グー'   && $com === 'チョキ' ||
    $player === 'チョキ' && $com === 'パー' ||
    $player === 'パー'   && $com === 'グー'
    ) {
    $result = '勝ち';
// どの条件とも一致しない(負け)
} else {
    $result = '負け';
}

あいこを同じ手で判定し、勝利結果を条件でまとめ、さらに負け判定をelseで済ませることで、スッキリしたコードになりました。switchでも同様に改善できそうですが省略します。

PHP7でさらに改善

初めてのPHPで学んだ、Null合体演算子filter_inputを使って、コードを書いてみます。filter_inputを使うことで、$_POSTの存在確認とバリデーションを同時に行うことができます。このことによって、Formの改変が行われてもエラーが出ないようになりました。また、PHP7とは関係ありませんが、勝敗判定に簡潔なアルゴリズムを使っています。

<?php
// keyを1から
$janken = [1 => 'グー', 'チョキ', 'パー'];

// $POST_['select']が存在し、なおかつ「1から3」の数値であるか?
if ($player = filter_input(INPUT_POST, 'select', FILTER_VALIDATE_INT, [
    'options' => [
        'min_range' => 1,
        'max_range' => 3
    ]])) {

    // 相手の手をランダムで決定
    $com = array_rand($janken);

    // 勝敗判定
    $judge = ($player - $com + 3) % 3;
}

// Null合体演算子を使って、結果を代入
$result = ['あいこ', '負け', '勝ち', null][$judge ?? 3];
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPでじゃんけんゲーム</title>
</head>
<body>
<p>選んでください。</p>

<form action="<?= filter_input(INPUT_SERVER, 'SCRIPT_NAME'); ?>" method="post">
    <?php
    foreach ($janken as $value => $hand) {
        printf('<button type="submit" name="select" value="%s">%s</button>'. PHP_EOL, $value, $hand);
    }
    ?>
</form>

<?php
if ($result) {
echo <<<RESULT
<p>結果</p>

<p>
あなた:$janken[$player]<br>
あいて:$janken[$com]
</p>

<p>{$result}です。</p>
RESULT;
}
?>
</body>
</html>

HTTPリクエストメソッド判定も加える

HTTPリクエストメソッドがPOSTであるかを判定するには、if文の条件に以下のコードを追加します。

if (
    filter_input(INPUT_SERVER, 'REQUEST_METHOD') === 'POST' &&
    $player = ... // 以降省略
   )
}

まとめ

PHPで簡単にじゃんけんゲームを作ることができました。

今回書いた数通りのコードの結果はすべて同じです。どのコードを用いるかは、時間が経ってからの修正などを考慮し、ぱっと見て最も理解しやすいコードでいいかと思います。