题目描述
最近,阿夸迷于德州扑克。所以她找到了很多人和她一起玩。由于人数众多,阿夸必须更改游戏规则:

  1. 所有扑克牌均只看数字,不计花色。
  2. 每张卡的值为1、2、3、4、5、6、7、8、9、10、11、12、13 中的一种(对应A,2、3、4、5、6、7, 8、9、10,J,Q,K)
  3. 每位玩家从一副完整的扑克牌(没有大小王)中抽出五张扑克牌,可能出现的手牌的值从低到高排列如下:
  • 高牌:不包含以下牌的牌。对于都是高牌的牌,按照五张牌的值的和进行从大到小排序。
  • 对子:手中的5张牌中有2张相同值的牌。对于都拥有对子的牌,按构成该对子的牌的值进行从大到小地排序。如果这些都相同,则按手牌中余下3张牌的值的和进行从大到小排序。**
  • 两对:手中拥有两对不同的对子。对于都包含两对的手牌,按其最高对子的值进行从大到小排序。如果最高对子相同,则按另一个对子的值从大到小地进行排序。如果这些值相同,则按剩余牌的值从大到小地进行排序。
  • 三条:手中拥有3张相同值的牌。对于都包含三条的手牌按构成三条的牌的值进行从大到小地排序。如果这些值相同,则按剩余牌的值从大到小地进行排序。
  • 满堂红:手中拥有一个三条和一个对子。同理,先按三条大小排序,如果三条大小相同,则按对子大小进行排序。
  • 四条:手中拥有4张相同值的牌。对于都包含四条的手牌按构成四条的牌的值进行从大到小地排序。如果这些值相同,则按剩余牌的值从大到小地进行排序。
  • 顺子:手中拥有5张连续值的卡。对于都包含顺子的手牌按顺子最大的牌进行排序。
  • 皇家同花顺:手中拥有10到A(10、J、Q、K、A)。是最大的手牌!

现在,阿夸已经知道了每个人的手牌,她想要知道所有人的排名列表。如果玩家的手牌大小相等,则按玩家名字的字典序输出。保证没有重复的名字。你能帮帮她吗?

输入格式:
第一行包含一个正整数 N (1<=N<=100000) ,表示玩家的人数。
接下来 N 行,每行包含两个字符串:m (1<=|m|<=10 ) ,表示玩家的名字;s (1<=|s|<=10),表示玩家的手牌。

输出格式:
输出 N个玩家的排名列表。

解题思路

1.转换牌面:将字符数组转换为数字数组
2.对每一副牌的牌面排序,分类判断各种牌型,并计算对应的分值: (关键步骤)

  • 将牌型由小到大划分为等级level 1-8
  • 在同一level下,利用每张牌不同的优先级计算分值
  • 例如,两对22335的分值为310000+2100+5=30205

3.按牌型、分值、姓名排序:采用结构体数组快速排序的方法

完整代码

#include<stdio.h>
#include<string.h>
#include <algorithm>
using namespace std;

char num[15] = "0A234567891JQK";
struct member {
    char name[15];
    char card1[15];
    int card2[15];
    int level,score,two1,two2,three,four;
}man[120000];

void convert(char str[], int x[]) {
    int i, j, k;
    for (i = 0, j = 0; str[i] != ''; i++, j++) {
        for (k = 1;; k++) {
            if (num[k] == str[i]) {
                x[j] = k;
                break;
            }
        }
        if (x[j] == 10) {
            i++;
        }
    }
}/*功能:转换牌面 
 参数:str 为字符牌面,x 为数字牌面*/

void judge(member a,int x) {
    int i;
    for (i = 0; i < 5; i++) {
        a.score+= a.card2[i];
    }

    for (i = 0; i<4; i++) {
        if (a.card2[i] == a.card2[i + 1]) {
            a.two1= a.card2[i];
        }
        if (a.card2[i] == a.card2[i + 2]) {
            a.three = a.card2[i];
        }
        if (a.card2[i] == a.card2[i + 3]) {
            a.four = a.card2[i];
        }
    }
    for (i = 0; i < 4; i++) {
        if (a.card2[i] == a.card2[i + 1]) {
            a.two2 = a.card2[i];
            break;
        }
    }
    if (a.four != 0) {
        a.level = 6;
        a.score += a.four * 100 - 4 * a.four;
    }
    else if (a.three != 0 && a.two1 != a.two2) {
        a.level = 5;
        a.score += a.three * 100 - 3*a.three;
    }
    else if (a.three != 0&&a.two1==a.two2) {
        a.level = 4;
        a.score += a.three * 100 - 3 * a.three;
    }
    else if (a.two1 != a.two2) {
        a.level = 3;
        a.score += a.two1 * 10000 + a.two2 * 100 - 2 * a.two1 - 2 * a.two2;
    }
    else if (a.two1 != 0) {
        a.level = 2;
        a.score += a.two1 * 100 - a.two1 * 2;
    }
    else if (a.card2[0] == 1 && a.card2[1] == 10 && a.card2[2] == 11 && a.card2[3] == 12 && a.card2[4] == 13) {
        a.level = 8;
    }
    else if (a.card2[1]==a.card2[0]+1&& a.card2[2] == a.card2[1] + 1 && a.card2[3] == a.card2[2] + 1 && a.card2[4] == a.card2[3] + 1 ) {
        a.level = 7;
    }
    man[x].level = a.level;
    man[x].score = a.score;
}/*分类判断各种牌型,并计算对应的分值*/

bool cmp(member x, member y)
{
    if (x.level != y.level) return x.level > y.level;
    if (x.score != y.score) return x.score > y.score;
    return strcmp(x.name, y.name)<0;
}/*功能:按牌型、分值、姓名非升序排序*/

int main()
{
    int N, i, j = 0;
    scanf("%d", &N);
    for (i = 0; i < N; i++) {
        scanf("%s%s", man[i].name, man[i].card1);
        convert(man[i].card1, man[i].card2);/*转换牌面*/
        sort(man[i].card2, man[i].card2+5);/*对每一副牌的牌面非升序排序*/
        judge(man[i],i);/*分类判断各种牌型,并计算对应的分值*/
    }
    sort(man, man+N, cmp);/*按牌型、分值、姓名非升序排序*/
    for (i = 0; i < N; i++) {
        puts(man[i].name);
    }
    return 0;
}

心得

本题的关键在于分类判断各种牌型,而分类的前提是“读懂规则”。在我看来,运用纸笔或者记事本将题目规则理解透彻,应该是第一步。
复杂的规则下,本题需要的代码量较多,对各种牌型的判断容易出现交叉错误。可以尝试对程序进行分块化处理,分成不相关的几个模块,进而对各个模块逐一突破。
在测试数据的方面,可以考虑自己写测试数据。以不同等级下不同牌面为例,测试时输出对应的等级与分值,就可以直观地看出问题所在,返回该模块进行修改。

附:
粘贴代码到 word 的在线工具:PlanetB
使用教程->如何优雅的在 Microsoft word 中插入代码

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/dump16/p/12397008.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!

相关课程

3764 8.82元 9.8元 9折