题目
5.5下面将给出两个人玩的扑克牌游戏的一种玩法,试设计一个模拟程序,它的基本功能是: (1)发两手牌(利用随机数产生器)。 (2)确定赢者和赢牌的类型。 (3)模拟N次游戏,计算每种类型牌赢或平局的概率。要求用HIPO图描绘设计结果并且画出高层控制流程图。 扑克牌游戏规则如下: (1)有两个人玩分别为A和B。 (2)一副扑克牌有52张牌,4种花色(黑桃、红桃、梅花、方块),每种花色的牌的点数按升序排列有2,3,4,.........,10,J,Q,K,A等13种。 (3)给每个人发三张牌,牌面向上,赢者立即可以确定。 (4)最高等级的一手牌成为同花,即3张牌均为同一种花色,最大的同花是同一种花色的Q,K,A。 (6)第三等级的牌是同点,即点数相同的三张牌,最大的同点是AAA。 (7)第四等级的牌是对子,即3张牌中有两张点数相同,最大的对子是A,A,K。 (8)第五等级的牌是杂牌,即除去上列4等之外的任何一手牌,最大的杂牌是不同花色的A.K,J。 (9)若两个人的牌类型不同,则等级高者胜;若等级相同,则点数高者胜;若点数也相同,则为平局。
实现
//对它进行编码 方便逻辑实现 1到52进行编号
//按照1 2 3...J Q K 分
//1-13黑桃 14-26红心 27-39梅花 40-52方块
// 0 1 2 3
//设一张牌的随机数编号是 x 则(x - 1)/13是他的花色 即分别是0 1 2 3
//(x - 1) % 13 + 1是他的值
//inf 表示这种等级中最大的等级
再用题目要求 进行判断
对它的花色状态和值进行排序 判断起来比较方便
容易忽略的地方主要是不能有相同的牌 我使用了位运算来实现 用bool数组也可以
总结
位运算&写成了&&了= =
写出了点奇奇怪股的部分 调了一下 因为没有OJ 自己手动生成数据一个个看对不对 花了20分钟....
所有代码
#include <stdio.h> #include <iostream> #include <ctime> #include <algorithm> using namespace std; typedef long long ll; const int cardnum = 52; const int si = 3, inf = 1e7; int a[si], b[si]; void showcard(int x) { int cc = (x - 1 ) / 13; int vv = (x - 1 ) % 13 + 1; if (cc == 0) printf(" 黑桃"); else if (cc == 1) printf(" 红心"); else if (cc == 2) printf(" 梅花"); else printf(" 方块"); if (vv == 1) printf("A "); else if (vv == 11) printf("J "); else if (vv == 12) printf("Q "); else if (vv == 13) printf("K "); else printf("%d ", vv); } void generate() { //一副牌只有52张 且不能重复 用位运算 排除重复 速度很快 ll sta = 0;//int只有32位 装不下52个牌 要用ll srand( (unsigned)time( NULL)); for (int i = 0; i < si; i++) { do { a[i] = rand() % cardnum + 1; } while (sta >> a[i] & 1);//这里一开始错成了 && sta |= 1 << a[i]; } for (int i = 0; i < si; i++) { do { b[i] = rand() % cardnum + 1; } while (sta >> b[i] & 1); sta |= 1 << b[i]; } //这样6个牌都是不重复的 cout << endl << "a: " ; for (int i = 0; i < si; i++) showcard(a[i]); cout << endl << "b: " ; for (int i = 0; i < si; i++) showcard(b[i]); cout << endl; } void cal(int &g, int &v, int arr[]) { int color[si], val[si];//花色 值 int sum = 0; for (int i = 0; i < si; i++) { color[i] = (arr[i] - 1 ) / 13; //设一张牌的编号是 x 则(x - 1)/13是他的花色 即分别是0 1 2 3 val[i] = (arr[i] - 1 ) % 13 + 1; //(x - 1) % 13 + 1是他的值 sum += val[i]; } sort(val, val + si);//排序方便比较 sort(color, color + si); int fl = 1;//同花 for (int i = 0; i < si - 1; i++) if (color[i] != color[i + 1]) fl = 0; if (fl) { if (val[0] == 1 && val[1] == 12 && val[2] == 13) v = inf; else v = sum; g = 0; cout << "同花" << endl; return ; } fl = 1;//顺子 因为前面已经判断了 花色是不同的 所以不用判断了 for (int i = 0; i < si - 1; i++) if (val[i] + 1 != val[i + 1]) fl = 0; if (fl) { //这里 题目没说清楚 他说是花色不同的 A K Q 没说是全部都不同还是有一个和另外两个不同就行了 //我理解成是有一个和另外两个不同就行了 if (val[0] == 1 && val[1] == 12 && val[2] == 13) v = inf; else v = sum; g = 1; cout << "顺子" << endl; return ; } fl = 1;//同点 for (int i = 0; i < si - 1; i++) if (val[i] != val[i + 1]) fl = 0; if (fl) { if (sum == 3) v = inf;//小技巧 1 + 1 + 1 = 3; 3 必然是AAA else v = sum; g = 2; cout << "同点" << endl; return ; } fl = 0;//对子 for (int i = 0; i < si - 1; i++) if (val[i] == val[i + 1]) fl = 1; if (fl) { if (val[0] == 1 && val[1] == 1 && val[2] == 13) v = inf; else v = sum; g = 3; cout << "对子" << endl; return ; } //杂牌 cout << "杂牌" << endl; if (val[0] == 1 && val[1] == 11 && val[2] == 13) v = inf; else v = sum; g = 4; return ; } int comparee() {//比较 int ag, av, bg, bv;// a等级和点数 b的等级和点数 cal(ag, av, a);//计算a b的等级和点数 0是最高 同花 最弱是4 cal(bg, bv, b); printf("av %d, bv %d ", av, bv); if (ag < bg) return 1; if (ag > bg) return -1; if (av > bv) return 1; if (av < bv) return -1; return 0; } int main() { //对它进行编码 方便逻辑实现 //按照1 2 3...J Q K 分 //1-13黑桃 14-26红心 27-39梅花 40-52方块 // 0 1 2 3 //设一张牌的编号是 x 则(x - 1)/13是他的花色 即分别是0 1 2 3 //(x - 1) % 13 + 1是他的值 //inf 表示这种等级中最大的等级 generate();//生成随机数 int s = comparee();//比较 if (s > 0) printf("a win "); if (s < 0) printf("b win "); if (s == 0) printf("pingju "); return 0; }