首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 實現「扎金花」撲克牌型判邏與大小比較算法詳解

     編輯:PHP 相關知識

遊戲規則回顧

扎金花(三張牌)比較規則由大到小:

  1. 豹子(筒子):三張點數相同(AAA 最大)
  2. 順金(同花順):同花色且點數連續
  3. 金花(同花):三張花色相同
  4. 順子:點數連續(A23 最大,其次 AKQ,最小 234)
  5. 對子:兩張點數相同
  6. 單張:無上述牌型,比較最大單張,依次類推

特殊規則:順子中 A-2-3 最大,A-K-Q 次之。

算法設計:分值量化法

將每手牌計算為一個整數分值,直接比較整數大小即可得出勝負。分值構成:

基礎分 (6位) + 牌型權重 (最高位)
  • 基礎分:三張牌點數按降序拼成 6 位數(不足補 0)。對子特殊處理:將對子點數前置(如 779 → 070709)。
  • 牌型權重(加在最高位,確保牌型優先級):
    • 單張:+0
    • 對子:+1000000 (106)
    • 順子:+2000000
    • 金花:+3000000
    • 順金:+5000000 (金花+順子)
    • 豹子:+6000000

完整 PHP 實現

<?php
class PlayCards {
    public $suits = ['Spade', 'Heart', 'Diamond', 'Club'];
    public $figures = ['2','3','4','5','6','7','8','9','10','J','Q','K','A'];
    private $cards = [];

    public function __construct() {
        foreach ($this->suits as $s) {
            foreach ($this->figures as $f) $this->cards[] = [$s, $f];
        }
    }

    // 洗牌發 3 張
    public function getCard() {
        shuffle($this->cards);
        return [array_pop($this->cards), array_pop($this->cards), array_pop($this->cards)];
    }

    // 比較兩手牌:返回 1/0/-1
    public function compareCards($c1, $c2) {
        $s1 = $this->calcScore($c1);
        $s2 = $this->calcScore($c2);
        return $s1 > $s2 ? 1 : ($s1 < $s2 ? -1 : 0);
    }

    private function calcScore($card) {
        $suits = []; $figs = [];
        foreach ($card as $c) {
            $suits[] = $c[0];
            $figs[] = array_search($c[1], $this->figures) + 2; // 2~14
        }
        // 補 0 並降序
        foreach ($figs as &$v) $v = str_pad($v, 2, '0', STR_PAD_LEFT);
        rsort($figs);

        // 對子特殊排序:將對子點數移至前兩位
        if ($figs[1] == $figs[2]) {
            $tmp = $figs[0]; $figs[0] = $figs[2]; $figs[2] = $tmp;
        }

        $score = (int)implode('', $figs); // 6位基礎分

        // 牌型判斷(按優先級由高到低)
        $isBaozi  = ($figs[0] == $figs[1] && $figs[1] == $figs[2]);
        $isJinhua = ($suits[0] == $suits[1] && $suits[1] == $suits[2]);
        $isShunzi = ($figs[0] == $figs[1] + 1 && $figs[1] == $figs[2] + 1) || implode($figs) === '140302'; // A23

        if ($isBaozi)      $score += 6000000;
        elseif ($isJinhua && $isShunzi) $score += 5000000; // 順金
        elseif ($isJinhua) $score += 3000000;
        elseif ($isShunzi) $score += 2000000;
        elseif ($figs[0] == $figs[1] && $figs[1] != $figs[2]) $score += 1000000; // 對子

        return $score;
    }
}

// --- 測試 ---
$game = new PlayCards();
$c1 = $game->getCard();
$c2 = $game->getCard();
$res = $game->compareCards($c1, $c2);

function printCard($c) {
    $s = '(';
    foreach ($c as $v) $s .= "{$v[0]}{$v[1]},";
    return rtrim($s, ',') . ')';
}

echo "手牌1: " . printCard($c1) . "<br>";
echo "手牌2: " . printCard($c2) . "<br>";
echo "結果: " . ($res==1?"手牌1大":($res==-1?"手牌2大":"平局"));
?>

關鍵點解析

  1. 點數映射:2~10,J,Q,K,A → 2~14,統一數值比較。
  2. 對子排序技巧:將對子點數前置(如 7,7,9 → 07,07,09),保證對子之間按對子點數大小比較,同對子再比單張。
  3. A23 順子特判:A(14),2,3 排序後為 14,03,02 不滿足連續遞減,需額外判斷 implode === '140302'。
  4. 權重設計:權重間隔足夠大(106),確保任意高牌型分值必大於低牌型最大基礎分(999999)。

擴展建議

  • 支持 5 張牌德州撲克牌型判斷(需引入更複雜的組合邏輯)。
  • 加入花色大小比較(如同牌型同點數時比花色:黑桃>紅桃>梅花>方塊)。
  • 性能優化:預計算所有 22100 種三張組合的分值建立查表,O(1) 比較。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved