跳转至

游戏

德州扑克

德州扑克 (Texas hold'em,有时也简称为Hold'em或Holdem),简称德扑,是世界上最流行的公牌扑克衍生游戏,也是国际扑克比赛的正式竞赛项目之一。世界扑克大赛(World Series of Poker, WSOP)和世界扑克巡回赛(World Poker Tour,WPT)的主赛事(Main Event)项目即是“无限注德州扑克”。德州扑克是位置顺序影响最大的扑克衍生游戏之一,每一轮的下注顺序维持不变,它也是美国多数赌场内最受欢迎的扑克牌类游戏,在美国以外的地区也十分流行,与桥牌的流行程度相当。理论上一桌同时最多可容纳22位(若不销牌则为23位)牌手,但一般是二至十人一桌。

namespace holdem {
enum Suit {
    HighCard,           // 高牌
    Pair,               // 对子
    TwoPair,            // 两对
    ThreeOfAKind,       // 三条
    Straight,           // 顺子
    Flush,              // 同花
    FullHouse,          // 葫芦
    FourOfAKind,        // 铁支
    StraightFlush,      // 同花顺
    RoyalStraightFlush  // 同花大顺
};

enum CardType {
    Two = 0,
    Three = 1,
    Four = 2,
    Five = 3,
    Six = 4,
    Seven = 5,
    Eight = 6,
    Nine = 7,
    Ten = 8,
    Jack = 9,
    Queen = 10,
    King = 11,
    Ace = 12
};

enum Color {
    Heart = 0,    // ♥
    Spade = 1,    // ♠
    Club = 2,     // ♣
    Diamond = 3   // ♦
};

// 一张卡牌,用类型和颜色表示
using Card = std::pair<CardType, Color>;

bool operator<(const Card &lhs, const Card &rhs) {
    return lhs.first < rhs.first;
}

// 手牌分数,用牌型和分数判断,分数只对相同牌型有效
using Score = std::pair<Suit, int>;

bool operator<(const Score &lhs, const Score &rhs) {
    return lhs.first < rhs.first or (lhs.first == rhs.first and lhs.second < rhs.second);
}

// 手牌
struct Hand {
    // 颜色,用位表示每张手牌是否存在
    std::array<short, 4> color{};
    // 数目,存放每种卡牌的数目
    std::array<short, 13> type{};
    void clear(){
        std::fill(color.begin(), color.end(), 0);
        std::fill(type.begin(), type.end(), 0);
    }
    void addCard(const Card& c){
        color[c.second] += (1 << c.first);
        type[c.first]++;
    }
    void removeCard(const Card& c){
        color[c.second] -= (1 << c.first);
        type[c.first]--;
    }
};

Score getType(const Hand &hand) {

    auto& colors = hand.color;
    auto& types = hand.type;
    // is RoyalStraightFlush
    for (short i = 0; i < 4; ++i) {
        if ((colors[i] & 0b111110000000000) == 0b111110000000000) {
            return {RoyalStraightFlush, 0};
        }
    }
    // is StraightFlush
    {
        int tv = 0b111110000000000;
        for (short i = Ace; i >= Five; --i) {
            for(int j = 0; j < 4; ++j){
                if((colors[j] & tv) == tv){
                    return {StraightFlush, i};
                }
            }
            tv >>= 1;
            if(__builtin_popcount(tv) < 5) tv |= (1 << 12);
        }
    }
    // is FourOfAKind
    {
        for (short i = Ace; i >= Two; --i) {
            if (types[i] >= 4) {
                for (short j = Ace; j >= Two; --j) {
                    if (j == i) continue;
                    if (types[j] > 0) {
                        return {FourOfAKind, i * 13 + j};
                    }
                }
            }
        }
    }
    // is FullHouse
    {
        for (short i = Ace; i >= Two; --i) {
            if (types[i] >= 3) {
                for (short j = Ace; j >= Two; --j) {
                    if (j == i) continue;
                    if (types[j] >= 2) {
                        return {FullHouse, i * 13 + j};
                    }
                }
            }
        }
    }
    // is Flush
    {
        int score = 0;
        for (short c = 0; c < 4; ++c) {
            if (__builtin_popcount(colors[c]) >= 5) {
                int tScore = 0;
                for (int j = Ace; j >= Two and __builtin_popcount(tScore) < 5; --j) {
                    tScore |= (colors[c] & (1 << j));
                }
                score = std::max(score, tScore);
            }
        }
        if (score) return {Flush, score};
    }
    // is Straight
    {
        for (int i = Ace; i >= Five; --i) {
            bool ok = true;
            for (int j = 0; j < 5 and ok; ++j) {
                int p = (i + 13 - j) % 13;
                if (types[p] == 0) {
                    ok = false;
                }
            }
            if (ok) {
                return {Straight, i};
            }
        }
    }
    // is ThreeOfAKind
    {
        for (int i = Ace; i >= Two; --i) {
            if (types[i] >= 3) {
                std::vector<int> others;
                for (int j = Ace; j >= Two and others.size() < 2; --j) {
                    if (types[j] > 0) {
                        others.push_back(j);
                    }
                }
                return {ThreeOfAKind, i * 169 + others[0] * 13 + others[1]};
            }
        }
    }
    // is TwoPair
    {
        std::vector<int> pairs;
        for (int i = Ace; i >= Two and pairs.size() < 2; --i) {
            if (types[i] >= 2) {
                pairs.push_back(i);
            }
        }
        if (pairs.size() >= 2) {
            for (int i = Ace; i >= Two; --i) {
                if (types[i] > 0) {
                    return {TwoPair, pairs[0] * 169 + pairs[1] * 13 + i};
                }
            }
        }
    }
    // is Pair
    {
        for (int i = Ace; i >= Two; --i) {
            if (types[i] >= 2) {
                int score = i;
                for (int j = Ace, cnt = 0; j >= Two and cnt < 3; --j) {
                    if (j == i) continue;
                    if (types[j] > 0) {
                        ++cnt;
                        score = score * 13 + j;
                    }
                }
                return {Pair, score};
            }
        }
    }
    // HighCard
    int highScore = 0;
    for (int i = Ace, cnt = 0; i >= Two and cnt < 5; --i) {
        if (types[i]) {
            highScore = highScore * 13 + i;
            ++cnt;
        }
    }
    return {HighCard, highScore};
}

char cardType2char(CardType ct) {
    return "23456789TJQKA"[ct];
}

CardType char2cardType(char c) {
    switch (c) {
        case '2':
            return Two;
        case '3':
            return Three;
        case '4':
            return Four;
        case '5':
            return Five;
        case '6':
            return Six;
        case '7':
            return Seven;
        case '8':
            return Eight;
        case '9':
            return Nine;
        case 'T':
            return Ten;
        case 'J':
            return Jack;
        case 'Q':
            return Queen;
        case 'K':
            return King;
        default:
            return Ace;
    }
}
}

评论