C++扑克牌游戏算法:寻找最小点数牌型

问题背景

中秋国庆假期,小F和小C玩起了扑克牌游戏。游戏规则如下:

  • 一副牌除去大小王,共52张。
  • 牌型分为单张、对子、同花顺、普通顺子、三带一五种。
  • 每种牌型有对应的点数计算规则。

现在已知小C打出了一套牌,以及小F手上的牌,需要编写一个程序帮助小F找到满足以下条件的最小点数牌型:

  • 牌型、张数与小C打出的牌相同。
  • 点数大于小C打出的牌。

代码实现

#include<iostream>
#include<stdio.h>
#include<string.h>

using namespace std;

// 定义常量和变量
const int MAXN = 25;
int n, m;
char WordsFromF[MAXN], CardsNumsFromF[MAXN], WordsFromC[MAXN], CardsNumsFromC[MAXN];
int NumsFromF[MAXN], NumsFromC[MAXN];
bool IsSameColor = true, IsSameNum = true;

// 将牌面字符转换为对应点数
inline void checkCard(char Num, int i, int Nums[]) {
    if (Num > '2' && Num <= '9') {
        Nums[i] = Num - '0';
    } else {
        switch (Num) {
            case 'X': Nums[i] = 10; break;
            case 'J': Nums[i] = 11; break;
            case 'Q': Nums[i] = 12; break;
            case 'K': Nums[i] = 13; break;
            case 'A': Nums[i] = 14; break;
            case '2': Nums[i] = 15; break;
        }
    }
}

// 判断是否存在符合条件的牌型
inline bool judgeCards() {
    // 单张情况
    if (m == 1) {
        for (int i = 1; i <= n; ++i) {
            if (NumsFromF[i] > NumsFromC[1]) {
                printf('%c%c', WordsFromF[i], CardsNumsFromF[i]);
                return true;
            }
        }
        return false;
    }
    // 对子情况
    else if (m == 2 && IsSameNum) {
        for (int i = 1; i <= n - 1; ++i) {
            if (NumsFromF[i] > NumsFromC[1] && NumsFromF[i + 1] == NumsFromF[i]) {
                printf('%c%c %c%c', WordsFromF[i], CardsNumsFromF[i], WordsFromF[i + 1], CardsNumsFromF[i + 1]);
                return true;
            }
        }
        return false;
    }
    // 同花顺情况
    else if (m >= 3 && IsSameColor && !IsSameNum && CardsNumsFromC[1] != CardsNumsFromC[2]) {
        for (int i = 1; i <= n - m + 1; ++i) {
            if (CardsNumsFromF[i + m - 1] == '2' || i + m - 1 > n) {
                break; // 无法完成同花顺
            }
            for (int j = i + 1; j <= i + m - 1; ++j) {
                if (NumsFromF[j - 1] + 1 != NumsFromF[j] || WordsFromF[j - 1] != WordsFromF[j]) {
                    break; // 不是顺子或花色不同
                }
                if (j == i + m - 1 && NumsFromF[j - m + 1] > NumsFromC[1]) {
                    for (int k = i; k <= i + m - 1; ++k) {
                        printf('%c%c ', WordsFromF[k], CardsNumsFromF[k]);
                    }
                    return true;
                }
            }
        }
        return false;
    }
    // 普通顺子情况
    else if (m >= 5 && !IsSameColor && !IsSameNum) {
        for (int i = 1; i <= n - m + 1; ++i) {
            if (CardsNumsFromF[i + m - 1] == '2' || i + m - 1 > n) {
                break; // 无法完成顺子
            }
            for (int j = i + 1; j <= i + m - 1; ++j) {
                if (NumsFromF[j - 1] + 1 != NumsFromF[j]) {
                    break; // 不是顺子
                }
                if (j == i + m - 1 && NumsFromF[j - m + 1] > NumsFromC[1]) {
                    for (int k = i; k <= i + m - 1; ++k) {
                        printf('%c%c ', WordsFromF[k], CardsNumsFromF[k]);
                    }
                    return true;
                }
            }
        }
        return false;
    }
    // 三带一情况
    else if (m == 4 && !IsSameNum && CardsNumsFromC[1] == CardsNumsFromC[2] && CardsNumsFromC[3] != CardsNumsFromC[4]) {
        if (n < 4) {
            return false; // 手牌不足
        }
        for (int i = 1; i <= n - 2; ++i) {
            for (int j = i + 1; j <= i + 2; ++j) {
                if (NumsFromF[j - 1] != NumsFromF[j]) {
                    break; // 不是三张相同点数
                }
                if (j == i + 2 && NumsFromF[j] > NumsFromC[2]) {
                    for (int k = i; k <= i + 2; ++k) {
                        printf('%c%c ', WordsFromF[k], CardsNumsFromF[k]);
                    }
                    printf('%c%c', WordsFromF[i + 3], CardsNumsFromF[i + 3]); // 带一张其他牌
                    return true;
                }
            }
        }
        return false;
    }
    return false; // 其他情况均无解
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // 输入数据
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> WordsFromF[i] >> CardsNumsFromF[i];
        checkCard(CardsNumsFromF[i], i, NumsFromF);
    }
    cin >> m;
    for (int i = 1; i <= m; ++i) {
        cin >> WordsFromC[i] >> CardsNumsFromC[i];
        checkCard(CardsNumsFromC[i], i, NumsFromC);
        if (i > 1) {
            if (WordsFromC[i] != WordsFromC[i - 1]) IsSameColor = false;
            if (CardsNumsFromC[i] != CardsNumsFromC[i - 1]) IsSameNum = false;
        }
    }

    // 判断并输出结果
    if (!judgeCards()) {
        printf('-1
');
    }

    return 0;
}

代码说明

  1. 使用 checkCard 函数将牌面字符转换为对应点数,方便后续比较大小。
  2. 使用 judgeCards 函数判断是否存在符合条件的牌型,并根据不同牌型编写判断逻辑。
  3. main 函数中输入数据,调用 judgeCards 函数判断结果,并输出结果。

优化建议

  1. 可以使用哈希表或数组统计每种点数出现的次数,简化部分牌型的判断逻辑。
  2. 可以将部分重复代码封装成函数,提高代码复用性。
  3. 可以添加输入数据合法性校验,增强程序健壮性。

总结

本文实现了一个简单的C++扑克牌游戏算法,可以帮助玩家找到满足条件的最小点数牌型。通过学习该算法,可以锻炼编程思维和代码实现能力。同时,也可以根据实际需求对算法进行改进和优化。

C++扑克牌游戏算法:寻找最小点数牌型

原文地址: https://www.cveoy.top/t/topic/2xV 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录