zoukankan      html  css  js  c++  java
  • 软工作业第五章第五题

    题目

    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
    
    ", 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;
    }
  • 相关阅读:
    datasnap的监督功能【3】-TCP链接监督功能
    实体服务规则或值更新设置字段锁定性
    设置指定的单据视图
    启动或停止IIS
    SSMS2014清除登录记录
    未授予用户在此计算机上的请求登录类型
    采购合同手动下推采购订单提示没有NAME属性
    审批流消息中无法获取明细字段
    费用申请单反写费用合同提示第2行总金额超出,但是实际未超出
    调试手机端
  • 原文地址:https://www.cnblogs.com/smatrchen/p/10785159.html
Copyright © 2011-2022 走看看