【板子】德州扑克模拟

复制代码
#include <bits/stdc++.h>
using namespace std;

int t;
string a;
int x[5], y[5];

int kk(char s) {
    if (s >= '2' && s <= '9') return s - '0';
    else {
        if (s == 'T') return 10;
        else if (s == 'J') return 11;
        else if (s == 'Q') return 12;
        else if (s == 'K') return 13;
        else if (s == 'A') return 14;
        return 0;
    }
}//数值
int hs(char s) {
    if (s == 'C') return 0;
    else if (s == 'D') return 1;
    else if (s == 'H') return 2;
    else if (s == 'S') return 3;
    return 0;
}//百位花色

enum HandRank {
    HIGH_CARD = 1, ONE_PAIR, TWO_PAIR, THREE_OF_A_KIND,
    STRAIGHT, FLUSH, FULL_HOUSE, FOUR_OF_A_KIND, STRAIGHT_FLUSH
};//牌型

int wt(int a1, int a2, int a3, int a4, int a5) {
    int cards[5] = {a1, a2, a3, a4, a5};
    int ranks[5], suits[5];
    for (int i = 0; i < 5; i++) {
        ranks[i] = cards[i] % 100;
        suits[i] = cards[i] / 100;
    }
    sort(ranks, ranks + 5, greater<int>());

    bool is_flush = true;
    for (int i = 1; i < 5; i++)
        if (suits[i] != suits[0]) { is_flush = false; break; }

    bool is_straight = true;
    for (int i = 1; i < 5; i++)
        if (ranks[i - 1] - ranks[i] != 1) { is_straight = false; break; }

    bool is_wheel = (ranks[0] == 14 && ranks[1] == 5 && ranks[2] == 4 && ranks[3] == 3 && ranks[4] == 2);
    if (is_wheel) {
        is_straight = true;
        ranks[0] = 5; ranks[1] = 4; ranks[2] = 3; ranks[3] = 2; ranks[4] = 1;
    }

    int cnt[15] = {0};
    for (int i = 0; i < 5; i++) cnt[ranks[i]]++;

    int freq[5] = {0}, f_idx = 0;
    for (int i = 14; i >= 2; i--)
        if (cnt[i] > 0) freq[f_idx++] = cnt[i];
    sort(freq, freq + f_idx, greater<int>());

    int rank_val, tie_break = 0;
    if (is_straight && is_flush) {
        rank_val = STRAIGHT_FLUSH;
        tie_break = ranks[0];
    } else if (freq[0] == 4) {
        rank_val = FOUR_OF_A_KIND;
        int quad_rank = 0, kicker = 0;
        for (int i = 14; i >= 2; i--) {
            if (cnt[i] == 4) quad_rank = i;
            if (cnt[i] == 1) kicker = i;
        }
        tie_break = quad_rank * 100 + kicker;
    } else if (freq[0] == 3 && freq[1] == 2) {
        rank_val = FULL_HOUSE;
        int tri_rank = 0, pair_rank = 0;
        for (int i = 14; i >= 2; i--) {
            if (cnt[i] == 3) tri_rank = i;
            if (cnt[i] == 2) pair_rank = i;
        }
        tie_break = tri_rank * 100 + pair_rank;
    } else if (is_flush) {
        rank_val = FLUSH;
        for (int i = 0; i < 5; i++) tie_break = tie_break * 20 + ranks[i];
    } else if (is_straight) {
        rank_val = STRAIGHT;
        tie_break = ranks[0];
    } else if (freq[0] == 3) {
        rank_val = THREE_OF_A_KIND;
        int tri_rank = 0, kickers[2], k = 0;
        for (int i = 14; i >= 2; i--) {
            if (cnt[i] == 3) tri_rank = i;
            if (cnt[i] == 1) kickers[k++] = i;
        }
        tie_break = tri_rank * 10000 + kickers[0] * 100 + kickers[1];
    } else if (freq[0] == 2 && freq[1] == 2) {
        rank_val = TWO_PAIR;
        int pairs[2], p = 0, kicker = 0;
        for (int i = 14; i >= 2; i--) {
            if (cnt[i] == 2) pairs[p++] = i;
            if (cnt[i] == 1) kicker = i;
        }
        if (pairs[0] < pairs[1]) swap(pairs[0], pairs[1]);
        tie_break = pairs[0] * 10000 + pairs[1] * 100 + kicker;
    } else if (freq[0] == 2) {
        rank_val = ONE_PAIR;
        int pair_rank = 0, kickers[3], k = 0;
        for (int i = 14; i >= 2; i--) {
            if (cnt[i] == 2) pair_rank = i;
            if (cnt[i] == 1) kickers[k++] = i;
        }
        tie_break = pair_rank * 1000000 + kickers[0] * 10000 + kickers[1] * 100 + kickers[2];
    } else {
        rank_val = HIGH_CARD;
        for (int i = 0; i < 5; i++) tie_break = tie_break * 20 + ranks[i];
    }
    return rank_val * 100000000 + tie_break;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> t;
    while (t--) {
        for (int i = 0; i < 4; i++) {
            cin >> a;
            x[i] = kk(a[0]) + 100 * hs(a[1]);
        }
        for (int i = 0; i < 4; i++) {
            cin >> a;
            y[i] = kk(a[0]) + 100 * hs(a[1]);
        }

        // 构建44张剩余牌堆(排除8张明牌)
        vector<int> deck;
        for (int i = 0; i < 4; i++) {
            for (int j = 2; j <= 14; j++) {
                int card = i * 100 + j;
                bool ok = true;
                for (int k = 0; k < 4; k++)
                    if (card == x[k] || card == y[k]) { ok = false; break; }
                if (ok) deck.push_back(card);
            }
        }

        // 计算 c1, c2:我方牌力最大的两张暗牌
        int c1 = -1, c2 = -1, max1 = -1, max2 = -1;
        for (int card : deck) {
            int val = wt(x[0], x[1], x[2], x[3], card);
            if (val > max1) {
                max2 = max1; c2 = c1;
                max1 = val; c1 = card;
            } else if (val > max2) {
                max2 = val; c2 = card;
            }
        }

        // 计算 p1:对方牌力最大的一张暗牌
        int p1 = -1, max_opp = -1;
        for (int card : deck) {
            int val = wt(y[0], y[1], y[2], y[3], card);
            if (val > max_opp) {
                max_opp = val; p1 = card;
            }
        }

        // 博弈关键:我方在对方选定 p1 后的最优响应
        int q1 = (p1 == c1) ? c2 : c1;

        // 四种核心情景
        int case1_opp = wt(y[0], y[1], y[2], y[3], p1);
        int case1_me  = wt(x[0], x[1], x[2], x[3], q1);
        int case2_opp = wt(y[0], y[1], y[2], y[3], c1);
        int case2_me  = wt(x[0], x[1], x[2], x[3], c2);

        bool opp_win_case1 = (case1_opp > case1_me);
        bool opp_win_case2 = (case2_opp > case2_me);
        bool me_win_case1  = (case1_me > case1_opp);
        bool me_win_case2  = (case2_me > case2_opp);

        // 分类讨论
        if (opp_win_case1 || opp_win_case2) {
            cout << "GeiWoCaPiXie\n";
        } else if (me_win_case1 && me_win_case2) {
            cout << "WoYaoYanPai\n";
        } else {
            cout << "PaiMeiYouWenTi\n";
        }
    }
    return 0;
}

你是今晚打老虎,正在与法国赌神皮尔克松进行一场梭哈对决。游戏使用一副标准的 52 张扑克牌。

当前,每位玩家都有四张明牌和一张暗牌。由于法国赌神拥有超强的特异功能,他可以先把自己的

暗牌变成除桌面上已经出现的八张明牌之外的任意一张牌。法国赌神变牌之后,你完全知晓他的选择,然后你可以把自己的暗牌变成除桌面上已经出现的八张明牌以及法国赌神变牌后的暗牌之外的

任意一张牌。也就是说,除去已知的九张不同牌,总共有 43 张牌可选。如果你有必胜策略,输出

"WoYaoYanPai";如果法国赌神有必胜策略,输出 "GeiWoCaPiXie";如果双方都没有必胜策略,最终平

局,输出 "PaiMeiYouWenTi"。

在梭哈游戏中,每位玩家最终手里有五张牌,并且所有玩家的牌都互不相同。所有牌都来自一副标准

的 52 张扑克牌。标准扑克牌包含四种花色,每种花色各有 13 个点数:梅花(♣)、方块(♢)、红桃

(♡)和黑桃(♠)。每种花色都包含 A、K、Q、J,以及从 2 到 10 的数字牌;每张牌上会印有对应花

色的符号。同一张牌不能被抽取超过一次。

相关推荐
·醉挽清风·1 小时前
学习笔记—八股—操作系统
笔记·学习
慧都小项1 小时前
C/C++ 静态分析为什么要前移?Parasoft C/C++test 在 IDE 与 CI/CD 中的应用
c语言·c++·ide·功能测试·ai
qq_33776320192 小时前
国际期货资管系统开发方案|内外盘交易平台源码授权与二次开发支持
java·c语言·开发语言·c++·c#
zmzb010313 小时前
C++课后习题训练记录Day157
开发语言·c++
fanchenxinok15 小时前
学习笔记:LabVIEW调用DLL解析S19文件教程
笔记·学习·labview·dll解析
疯狂打码的少年15 小时前
【软件工程】结构化设计:模块独立性与耦合内聚
java·开发语言·笔记·软件工程
从零开始的代码生活_16 小时前
C++ 多态详解:虚函数、动态绑定、抽象类与虚表原理
开发语言·c++·后端·学习·算法
大彼方..17 小时前
C++ STL Vector 深度剖析:从内存管理到性能优化
开发语言·c++
炸薯条!17 小时前
从零开始学C++ (内存管理)
java·jvm·c++