Skip to content

PHP_10 「ポーカーをPHPで作ってみよう」

Last updated on 2019/7/11

どんなポーカー?

実現したい機能

  1. 掛け金を選択し決定する
  2. 5枚のカードを引く
  3. プレーヤーは交換できるか選択できる。交換しない場合は5へ。
  4. 交換するカードを選び、交換した分のカードを引く。
  5. カードが揃っているか判定 (役ができているか?)
  6. 役に応じた賞金を受け取る。
  7. 1へ戻る

実装

画像の用意

全体のコード

ポーカーのClass

<?php
class Poker
{
    public $hand;
    public $card_list;
    public $point;
    public $hand_name;
    static public $card_mark_list = array("c", "d", "h", "s");
    static public $hand_count = 5;

    public function __construct()
    {
        $this->reset();
        $this->judge();
    }
    function equal_hand($hand1, $hand2): bool
    {
        return intval($hand1 / 4) == intval($hand2 / 4) - 1;
    }

    function is_straight(): bool
    {
        $hand = $this->hand;
        return ($this->equal_hand($hand[0], $hand[1])
            && $this->equal_hand($hand[1], $hand[2])
            && $this->equal_hand($hand[2], $hand[3])
            && $this->equal_hand($hand[3], $hand[4]))
            || (intval($hand[0] / 4) == 0
                && $this->equal_hand($hand[1], $hand[2])
                && $this->equal_hand($hand[2], $hand[3])
                && $this->equal_hand($hand[3], $hand[4]));
    }

    function is_flash(): bool
    {
        $hand = $this->hand;
        $temp_card_mark = array();
        foreach ($hand as $value) {
            array_push($temp_card_mark, $value % 4);
        }
        return count(array_count_values($temp_card_mark)) == 1;
    }

    function duplicate_list()
    {
        $hand = $this->hand;
        $temp_card = array();
        foreach ($hand as $value) {
            array_push($temp_card, intval($value / 4));
        }
        return array_count_values($temp_card);
    }

    function is_equal_cards($count): bool
    {
        $array_count = $this->duplicate_list();
        $equal_flag = false;
        foreach ($array_count as $key => $value) {
            if ($value == $count) {
                $equal_flag = true;
            }
        }
        return $equal_flag;
    }

    function is_four(): bool
    {
        return $this->is_equal_cards(4);
    }

    function is_three(): bool
    {
        return $this->is_equal_cards(3);
    }

    function is_full_house(): bool
    {
        return $this->is_equal_cards(3) && $this->is_equal_cards(2);
    }

    function is_two_pear(): bool
    {
        return $this->is_equal_cards(2) && count($this->duplicate_list()) == 3;
    }

    function is_pear(): bool
    {
        return $this->is_equal_cards(2) && count($this->duplicate_list()) == 4;
    }

    function judge()
    {
        // 0: 役無し
        // 1: ロイヤルストレートフラッシュ
        // 2: ストレートフラッシュ
        // 3: フラッシュ
        // 4: ストレート
        // 5: フォーカード
        // 6: フルハウス
        // 7: スリーカード
        // 8: ツーペア
        // 9: ペア
        $code = 0;
        $hand = $this->hand;
        if ($this->is_flash($hand)) {
            if ($this->is_straight($hand)) {
                if (Poker::$card_mark_list[$hand[0] % 4] == "c") {
                    $code =  1;
                } else {
                    $code =  2;
                }
            } else {
                $code =  3;
            }
        } else if ($this->is_straight($hand)) {
            $code =  4;
        } elseif ($this->is_four($hand)) {
            $code =  5;
        } elseif ($this->is_full_house($hand)) {
            $code =  6;
        } elseif ($this->is_three($hand)) {
            $code =  7;
        } elseif ($this->is_two_pear($hand)) {
            $code =  8;
        } elseif ($this->is_pear($hand)) {
            $code =  9;
        } else {
            $code =  0;
        }
        $this->hand_name = $this->judge_name($code);
        $this->point = $this->judge_point($code);
    }

    function judge_point($code): int
    {
        $point_list = array(
            0, // 0: 役無し
            650000, // 1: ロイヤルストレートフラッシュ
            70000, // 2: ストレートフラッシュ
            500, // 3: フラッシュ
            250, // 4: ストレート
            4000, // 5: フォーカード
            700, // 6: フルハウス
            47, // 7: スリーカード
            21, // 8: ツーペア
            2, // 9: ペア
        );

        return $point_list[$code];
    }
    function judge_name($code): string
    {
        $name_list = array(
            "",
            "ロイヤルストレートフラッシュ",
            "ストレートフラッシュ",
            "フラッシュ",
            "ストレート",
            "フォーカード",
            "フルハウス",
            "スリーカード",
            "ツーペア",
            "ペア",
        );
        return $name_list[$code];
    }


    public function draw($count): void
    {
        for ($i = 0; $i < $count; $i++) {
            $rand_number = rand(0, count($this->card_list) - 1);
            array_push($this->hand, $this->card_list[$rand_number]);
            array_splice($this->card_list, $rand_number, 1);
        }
        sort($this->hand);
        $this->judge();
    }

    public function change($index_list): void
    {
        rsort($index_list);
        foreach ($index_list as $value) {
            array_splice($this->hand, intval($value), 1);
        }

        $this->draw(count($index_list));
    }

    public function reset(): void
    {
        // デフォルトの カードリスト を用意
        $this->card_list = array();
        // カードリストに 52枚 のカードを追加
        for ($i = 0; $i < 52; $i++) {
            // 配列 card_list に $iを追加
            array_push($this->card_list, $i);
        }
        $this->hand = array();
        $this->draw(Poker::$hand_count);
        $this->hand_name = "";
        $this->point = 0;
    }

    public static function image_url($card): string
    {
        $mark = Poker::$card_mark_list[$card % 4];
        $number = sprintf('%02d', intval($card / 4 + 1));
        return "./trump/" . $mark . $number . ".png";
    }
}

画面表示の部分

<?php
// オリジナルポーカーゲームの仕様
// ① 掛け金を選択し決定する
// ② 5枚のカードを引く
// ③ プレーヤーは交換できるか選択できる。
// 交換しない場合は⑤へ。
// ④ 交換するカードを選び、交換した分のカードを引く。
// ⑤ カードが揃っているか判定 (役ができているか?)
// ⑥ 役に応じた賞金を受け取る。
// ⑦ ①へ戻る

// 掛け金
// 持ち金
// カード (手札 & 山札)

require "./pocker_class.php";
session_start();

$poker = new Poker();
$user_point = 0;
$draw_flag = false;
$result_flag = false;

if (isset($_POST["change"])) {
    if (empty($_SESSION["poker"])) {
        // Sessionに情報がない場合 エラーにする。
    } else {
        $poker = $_SESSION["poker"];
        if (isset($_POST["index_list"])) {
            $poker->change($_POST["index_list"]);
        }
        $_SESSION["poker"] = $poker;
        $draw_flag = true;
    }
} else if (isset($_POST["result"])) {
    $draw_flag = true;
    $result_flag = true;
    $poker = $_SESSION["poker"];
    unset($_SESSION["poker"]);
} else {
    // 新規ゲームの場合
    $_SESSION["poker"] = $poker;
}

if (isset($_COOKIE["point"])) {
    $user_point = $_COOKIE["point"];
} else {
    $user_point = 0;
}

?>

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ポーカーゲーム</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css">
    <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
    <style>
        /* figure {
            padding: 2px;
            border-radius: 20px;
            background-color: white;
        }

        input[type="checkbox"]:checked + figure.image {
            background-color: red;
        }

        .trump-check {
            display: none;
        } */
    </style>
</head>

<body>

    <section class="section">
        <div class="container is-fullhd">
            <div class="modal <?= $result_flag ? "is-active" : "" ?>">
                <div class="modal-background"></div>
                <div class="modal-content">
                    <p class="image is-4by3">
                        <img src="./image/bingo/<?= $poker->point ?>.png" alt="">
                    </p>
                </div>
                <button class="modal-close is-large" aria-label="close"></button>
            </div>
            <h1 class="title">ポーカースロット</h1>
            <h2 class="subtitle">人生逆転ゲーム</h2>
            <!-- Main container -->
            <nav class="level">
                <!-- Left side -->
                <div class="level-left">
                    <div class="level-item">
                        <p class="subtitle is-5">
                            <strong><?= $user_point ?></strong> ポイントのうち掛け金:
                        </p>
                    </div>
                    <div class="level-item">
                        <div class="field has-addons">
                            <div class="select">
                                <select>
                                    <option>10 pt</option>
                                    <option>20 pt</option>
                                    <option>30 pt</option>
                                </select>
                            </div>
                        </div>
                    </div>
                    <!-- <div class="level-item">
                        <a class="button is-success">BET</a>
                    </div>
                    <div class="level-item">
                        <a class="button is-success">MAX BET</a>
                    </div> -->
                </div>

                <!-- Right side -->
                <div class="level-right">
                    <!-- <p class="level-item"><button type="submit" form="start" class="button is-success">Start</button>
                    </p> -->
                    <p class="level-item"><button type="submit" form="new" class="button is-success">New Game</button>
                    </p>
                </div>
            </nav>
            <div class="columns is-centered">
                <?php foreach ($poker->hand as $key => $card) { ?>
                    <div class="column has-text-centered">
                        <label class="trump checkbox" for="card<?= $key ?>">
                            <figure class="image is-200x300">
                                <img src="<?= Poker::image_url($card) ?>" alt="trump">
                            </figure>
                            <input id="card<?= $key ?>" class="checkbox trump-check" type="checkbox" name="index_list[]" form="change" value="<?= $key ?>" <?= $result_flag ? "disabled" : "" ?> />
                        </label>
                    </div>
                <?php } ?>
            </div>
            <div class="columns is-centered">
                <div class="column has-text-centered">
                    <?php if ($draw_flag) { ?>
                        <button id="modal-button" class="button is-success">結果を見る</button>
                        <button type="submit" form="new" class="button is-success">ゲームを始める</button>
                    <?php } elseif ($result_flag) { ?>
                        <button type="submit" form="new" class="button is-success">ゲームを始める</button>
                    <?php } else { ?>
                        <button type="submit" form="change" class="button is-success">交換する</button>
                        <button type="submit" form="result" class="button is-success">役確定</button>
                        <button type="submit" form="new" class="button is-success">降りる</button>
                    <?php } ?>
                </div>
            </div>
        </div>
    </section>
    <form action="./poker.php" method="post" id="change">
        <input type="hidden" name="change">
    </form>
    <form action="./poker.php" method="post" id="new">
        <input type="hidden" name="new">
    </form>
    <form action="./poker.php" method="post" id="start">
        <input type="hidden" name="start">
    </form>
    <form action="./poker.php" method="post" id="result">
        <input type="hidden" name="result">
    </form>
    <script>
        window.onload = function() {
            document.querySelector("#modal-button").onclick = function() {
                document.querySelector(".modal").classList.add("is-active")
            }
            document.querySelector(".modal-background").onclick = function() {
                document.querySelector(".modal").classList.remove("is-active")
            }
            document.querySelector(".modal-close").onclick = function() {
                document.querySelector(".modal").classList.remove("is-active")
            }

        }
    </script>
</body>

</html>