C++扑克牌游戏算法:寻找最小点数牌型
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;
}
代码说明
- 使用
checkCard函数将牌面字符转换为对应点数,方便后续比较大小。 - 使用
judgeCards函数判断是否存在符合条件的牌型,并根据不同牌型编写判断逻辑。 - 在
main函数中输入数据,调用judgeCards函数判断结果,并输出结果。
优化建议
- 可以使用哈希表或数组统计每种点数出现的次数,简化部分牌型的判断逻辑。
- 可以将部分重复代码封装成函数,提高代码复用性。
- 可以添加输入数据合法性校验,增强程序健壮性。
总结
本文实现了一个简单的C++扑克牌游戏算法,可以帮助玩家找到满足条件的最小点数牌型。通过学习该算法,可以锻炼编程思维和代码实现能力。同时,也可以根据实际需求对算法进行改进和优化。
原文地址: https://www.cveoy.top/t/topic/2xV 著作权归作者所有。请勿转载和采集!