题目

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)若两个人的牌类型不同,则等级高者胜;若等级相同,则点数高者胜;若点数也相同,则为平局。
View Code

实现

//对它进行编码 方便逻辑实现 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\n\n", 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 \n");
    if (s < 0) printf("b win \n");
    if (s == 0) printf("pingju \n");
    return 0;
}