【PHP】WPで動作可能なブラックジャックの作成

導入

WordPress 上で動作する ポイント制ブラックジャックを開発しました。
ユーザーは所持ポイントを使ってゲームをプレイし、勝敗に応じてポイントが増減します。

このプロジェクトでは以下の点を重視しています:

  • ✔️ WordPress AJAX による非同期処理
  • ✔️ myCRED を用いたポイント管理
  • ✔️ セキュアなセッション管理
  • ✔️ カードロジック

内容

ゲームロジック

  • デッキ生成
  • プレイヤー / ディーラーの処理
  • ヒット・スタンド・ブラックジャック判定
  • バースト処理
  • 結果判定とポイント精算

myCRED 連携

  • ベット額の引き落とし
  • 勝利・ブラックジャック時の払い戻し
  • 引き分け時の返金
  • 安全のため「銀行アカウント名は環境変数で管理」

セキュリティ対策

  • ログインユーザーでのみに制限
  • 入力データのサニタイズ

実際に動作している環境

※2025年11月22日現在はブラックジャックの公開は停止されています。
https://casino.project-sea.jp/

PHPコード例

以下は実際の開発で使用したコードの一部を、
安全化したうえでポートフォリオ向けに整形したものです。

add_action('init', function () {
    if (!session_id()) session_start();
});

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_script(
        'blackjack-js',
        get_template_directory_uri() . '/js/blackjack.js',
        ['jquery'],
        null,
        true
    );
    wp_localize_script('blackjack-js', 'blackjackAjax', [
        'ajaxurl' => admin_url('admin-ajax.php')
    ]);
});

add_action('wp_ajax_ps_blackjack_play', 'ps_blackjack_play');

function ps_blackjack_play()
{
    if (!is_user_logged_in()) {
        wp_send_json(['status' => 'error', 'message' => 'Authentication required.']);
    }

    $user_id = get_current_user_id();
    $mycred = mycred();

    $bank_user_login = getenv('BLACKJACK_BANK_USER') ?: 'bank_account_placeholder';
    $bank_user = get_user_by('login', $bank_user_login);

    if (!$bank_user) {
        wp_send_json(['status' => 'error', 'message' => 'Service unavailable.']);
    }

    $bank_user_id = $bank_user->ID;

    $player_stand  = sanitize_text_field($_POST['player_stand'] ?? '');
    $bet_amount    = intval($_POST['bet_amount'] ?? 0);
    $deck          = json_decode(stripslashes($_POST['deck'] ?? ''), true) ?? [];
    $player_cards  = json_decode(stripslashes($_POST['player_cards'] ?? ''), true) ?? [];
    $dealer_cards  = json_decode(stripslashes($_POST['dealer_cards'] ?? ''), true) ?? [];

    $current_balance  = $mycred->get_users_balance($user_id);
    $previous_balance = $_SESSION['blackjack_previous_balance'] ?? $current_balance;
    $initial_balance  = $_SESSION['blackjack_initial_balance'] ?? $current_balance;

    if ($player_stand === "start") {
        $deck = generate_blackjack_deck();
        shuffle($deck);

        $player_cards = [array_pop($deck), array_pop($deck)];
        $dealer_cards = [array_pop($deck), array_pop($deck)];

        if ($current_balance < $bet_amount) {
            wp_send_json(['status' => 'error', 'message' => 'Insufficient balance.']);
        }

        $mycred->add_creds('bj_bet', $user_id, -$bet_amount, 'Bet placed');
        $mycred->add_creds('bj_bank_in', $bank_user_id, $bet_amount, 'Bank receive');

        $_SESSION['blackjack_previous_balance'] = $mycred->get_users_balance($user_id);
        if (!isset($_SESSION['blackjack_initial_balance'])) {
            $_SESSION['blackjack_initial_balance'] = $previous_balance;
        }

        $player_blackjack = is_blackjack($player_cards);
        $dealer_blackjack = is_blackjack($dealer_cards);

        if ($player_blackjack || $dealer_blackjack) {
            if ($player_blackjack && $dealer_blackjack) {
                $mycred->add_creds('bj_push', $user_id, $bet_amount, 'Push refund');
                $mycred->add_creds('bj_bank_out', $bank_user_id, -$bet_amount, 'Push bank return');
                return finish_response("Push.", $mycred, $user_id, $player_cards, $dealer_cards);
            } elseif ($player_blackjack) {
                $payout = intval($bet_amount * 2.5);
                $mycred->add_creds('bj_blackjack_win', $user_id, $payout, 'Blackjack win');
                $mycred->add_creds('bj_bank_out', $bank_user_id, -$payout, 'Blackjack payout');
                return finish_response("Blackjack! You win.", $mycred, $user_id, $player_cards, $dealer_cards);
            } else {
                return finish_response("Dealer blackjack. You lose.", $mycred, $user_id, $player_cards, $dealer_cards);
            }
        }

        wp_send_json([
            'status' => 'success',
            'deck' => $deck,
            'player_cards' => $player_cards,
            'dealer_cards' => $dealer_cards,
            'balance' => $mycred->get_users_balance($user_id)
        ]);
    }

    if ($player_stand === "hit") {
        $player_cards[] = array_pop($deck);
        $score = blackjack_calc_score($player_cards);

        if ($score > 21) {
            if (empty($dealer_cards)) {
                $dealer_cards = [array_pop($deck), array_pop($deck)];
            }
            return finish_response("Bust. You lose.", $mycred, $user_id, $player_cards, $dealer_cards);
        }

        wp_send_json([
            'status' => 'continue',
            'deck' => $deck,
            'player_cards' => $player_cards
        ]);
    }

    if ($player_stand === "stand") {
        while (blackjack_calc_score($dealer_cards) < 17) {
            $dealer_cards[] = array_pop($deck);
        }

        $player_score = blackjack_calc_score($player_cards);
        $dealer_score = blackjack_calc_score($dealer_cards);
        $result = "";

        if ($player_score > 21) {
            $result = "Bust. You lose.";
        } elseif ($dealer_score > 21 || $player_score > $dealer_score) {
            $result = "You win!";
            $payout = $bet_amount * 2;
            $mycred->add_creds('bj_win', $user_id, $payout, 'Win payout');
            $mycred->add_creds('bj_bank_out', $bank_user_id, -$payout, 'Payout from bank');
        } elseif ($player_score < $dealer_score) {
            $result = "You lose.";
        } else {
            $result = "Push.";
            $mycred->add_creds('bj_push', $user_id, $bet_amount, 'Push refund');
            $mycred->add_creds('bj_bank_out', $bank_user_id, -$bet_amount, 'Push return');
        }

        return finish_response($result, $mycred, $user_id, $player_cards, $dealer_cards);
    }

    wp_send_json(['status' => 'error', 'message' => 'Invalid request.']);
}

function finish_response($message, $mycred, $user_id, $player_cards, $dealer_cards)
{
    $current_balance  = $mycred->get_users_balance($user_id);
    $_SESSION['blackjack_previous_balance'] = $current_balance;

    wp_send_json([
        'status' => 'finish',
        'message' => $message,
        'balance' => $current_balance,
        'player_cards' => $player_cards,
        'dealer_cards' => $dealer_cards
    ]);
}

function generate_blackjack_deck()
{
    $suits = ['♠', '♥', '♦', '♣'];
    $deck = [];
    foreach ($suits as $suit) {
        for ($i = 1; $i <= 13; $i++) {
            $value = ($i > 10) ? 10 : ($i === 1 ? 1 : $i);
            $rank = ($i === 1) ? 'A' : (($i > 10) ? ['J', 'Q', 'K'][$i - 11] : strval($i));
            $deck[] = ['card' => "{$suit}{$rank}", 'value' => $value];
        }
    }
    return $deck;
}

function blackjack_calc_score($cards)
{
    $total = 0;
    $aces = 0;
    foreach ($cards as $c) {
        $total += $c['value'];
        if ($c['value'] == 1) $aces++;
    }
    while ($total <= 11 && $aces > 0) {
        $total += 10;
        $aces--;
    }
    return $total;
}

function is_blackjack($cards)
{
    if (count($cards) != 2) return false;
    $ranks = array_column($cards, 'value');
    return (in_array(1, $ranks) && in_array(10, $ranks));
}

技術構成

技術内容
WordPressベースシステム
PHPサーバーサイドゲームロジック
myCREDポイント管理システム
JavaScript / jQueryゲームUI処理
Sessionユーザーゲーム状態管理
JSON / AJAXフロント ↔ バック間の通信

もし実際のコードを確認したい場合

本ポートフォリオでは、安全のため以下の情報は非公開にしています。

  • システム内部ログ名
  • 金融処理ロジックの実際のキー
  • 管理ユーザー情報
  • セキュリティ設定の詳細
  • リコーティング前のベースコード

必要であれば、個別に相談受付可能です。


お問い合わせ

このブラックジャックゲームの実装詳細や、システムの開発についてお問い合わせがあればいつでもご連絡ください。

PAGE TOP