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

C# 網路版鬥地主:出牌演算法與規則引擎實作 (第二部分) - 牌型判斷與大小比較

     編輯:關於C語言

出牌規則引擎核心:牌型識別與比較邏輯

本文深入解析鬥地主最複雜的核心邏輯:根據出牌張數識別牌型、處理複雜組合 (順子、連對、飛機)、牌組標準化排序、以及大小比較運算子重載。

牌型識別策略:按張數分派

IsRule(PokerGroup pg) 方法根據 pg.Count 分派判斷邏輯:

  • 1 張 → 單張
  • 2 張 → 對子 / 雙王
  • 3 張 → 三張
  • 4 張 → 三帶一 / 炸彈
  • 5 張 → 三帶一對 / 順子
  • 6+ 張 → 順子 / 連對 / 飛機 / 飛機帶翅膀 / 四帶二 等

複雜牌型判斷難點與解法

順子 / 連對判斷

排序後檢查點數連續性且無 2、大小王:

bool IsStraight(List cards) {
    if (cards.Any(c => c.Point >= 15)) return false; // 2(15)、小王(16)、大王(17) 不能進順子
    for (int i = 1; i < cards.Count; i++)
        if (cards[i].Point != cards[i-1].Point + 1) return false;
    return true;
}

飛機判斷 (最複雜)

飛機 = 連續三張 + 同數量附帶牌 (單張或對子)。難點在於「帶牌點數可能大於飛機主體」,導致排序後主體不連續。

解法:牌組標準化排序

  1. 先按點數分組統計張數。
  2. 識別「三張以上」的連續點數序列作為飛機主體。
  3. 將剩餘牌按規則歸類為「翅膀」。
  4. 重新組裝牌組:主體在前,翅膀在後,並按點數排序。

牌組大小比較:運算子重載

public static bool operator >(PokerGroup L, PokerGroup R) {
    // 類型不同且非炸彈/雙王 → 不可比較
    if (L.Type != R.Type && L.Type != PokerGroupType.Bomb && L.Type != PokerGroupType.JokerBomb)
        return false;

    // 同為炸彈:比較點數
    if (L.Type == PokerGroupType.Bomb && R.Type == PokerGroupType.Bomb)
        return L[0] > R[0];

    // 炸彈大於一切 (除雙王)
    if (L.Type == PokerGroupType.Bomb) return true;
    if (R.Type == PokerGroupType.Bomb) return false;

    // 雙王最大
    if (L.Type == PokerGroupType.JokerBomb) return true;
    if (R.Type == PokerGroupType.JokerBomb) return false;

    // 普通牌型:比較首張牌點數 (已標準化排序)
    return L[0] > R[0];
}

設計優化建議

  1. 策略模式封裝判斷邏輯:每種牌型一個 IHandValidator,便於擴充 (如加入「四帶二」)。
  2. 不可變牌組:PokerGroup 實例化後不可修改,比較運算回傳新實例。
  3. 單元測試覆蓋:建立完整測試案例表 (含邊界:A-2-3 不連續、飛機帶大牌、雙王等)。
  4. 效能優化:預先計算點數直方圖 int[18],避免重複 LINQ 查詢。

原始碼下載提醒

原文提供下載連結已失效,建議參考上述邏輯自行實作或搜尋開源專案 (如 DouDizhuRuleEngine)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved