【选作】Poker time 2 (enhanced version)

“我见青山多妩媚,料青山见我应如是”

嗨嗨嗨!有了Poker time基础版做铺垫,小橘相信解决这个enhanced版本也就不是很困难啦。

如果还没有了解过基础版的同学,可以先看看这篇文章(BOSS)Poker time! (20 xp)-CSDN博客

这样再看这题就会易懂得多。

话不多说,咱们进入正题!

题目描述

背景:两个人每人发3张牌(各从一副牌中),每张牌包括花色(红桃(Heart)>黑桃(Spade)>方块(Diamond)>梅花(Club))和大小(从小到大依次是:2-10、J、Q、K、A),胜负规则如下:同花顺(3张同花色的连牌,先比大小,再比花色后同)>炸弹(3张相同大小的牌)>连牌(3张不同花色的连牌)>对子(两张相同大小的牌)>单牌。例如,红桃QKA>黑桃QKA>梅花567>方块234>AAA(红桃、方块、梅花)>AAA(黑桃、方块、梅花)>JQK(红桃、红桃、方块)>JQK(黑桃、红桃、方块)>AA2(梅花黑桃梅花)>QQJ(红桃梅花方块)>JQA(红桃红桃红桃)。注:A23不算连牌。

输入:A的3张牌(未排序)和B的3张牌(未排序)。(参见用例)

输出:A的3张牌的排序后的输出和B的3张牌的排序后的输出,以及A和B谁获胜。(参见用例)

解题思路

和基础版一样,所谓升级版的题考的其实也是优先级排序问题,换汤不换药。

之前咱们总结说,基础版的难点有三个,那我们就将此题的难点总结为四个:一是对于输入输出时的细节处理,二是对花色和大小的权重赋值处理,三是对'10'的单独处理,四是对同花顺、炸弹、连牌和对子四个特殊情况的再次加权赋值。

整体思路是先对牌的花色和大小分别进行赋值,然后想办法将这两个属性整合到一个数中用于后续排序和比较,先完成A、B的降序排序,排序后针对四种特殊情况进行再次“加权”赋值,然后进行A、B的比较,最终输出结果。即:赋值——>整合——>特殊处理——>比较——>输出。

值得注意的是,与基础版不同,这里大小的权重是要高于花色的。

关键参数

A[3][3],B[3][3]:3×3的二维数组,用于储存输入的三张牌,列为3是由于10的存在,得多留一位。

A_score[3][2],B_score[3][2]:对于每个花色和大小进行重新赋值,方便后续整合比较。大小的优先级高,故将其设为十位数。

A_sum[3],B_sum[3]:是对花色和大小整合后的数值,是比较和排序的依据,也是在特殊情况处理时的关键指标。

难点分析

下面咱们对难点逐一进行分析:

1、输入输出时的细节处理

输入中只有10是特殊的,所以我们希望能将所有的输入都转变成两位的形式,这样方便后续的处理和比较。

注意:输入中无10,第三位为空格;若有10,则将第二位转变为'9'+1,第三位转变为0,并补上空格。

for(i=0;i<3;i++)
    {
        scanf("%c%c%c",&A[i][0],&A[i][1],&A[i][2]);
        if(A[i][1]=='1'&&A[i][2]=='0')
        {
            A[i][1]='9'+1;
            A[i][2]=0;
            if(i!=2)
                scanf(" ");
        }
    }
    scanf("\n");
    for(i=0;i<3;i++)
    {
        scanf("%c%c%c",&B[i][0],&B[i][1],&B[i][2]);
        if(B[i][1]=='1'&&B[i][2]=='0')
        {
            B[i][1]='9'+1;
            B[i][2]=0;
            if(i!=2)
                scanf(" ");
        }
    }

输出时要对第一步处理进行还原,将'9'+1还原为'10'

for(i=0;i<3;i++)
    {
        if(A[i][1]=='9'+1)
        {
            A[i][1]='1';
            A[i][2]='0';
        }
        if(B[i][1]=='9'+1)
        {
            B[i][1]='1';
            B[i][2]='0';
        }
    }
    
//输出结果
    printf("A:"); 
    for(i=0;i<3;i++)
    {
        if(A[i][2]=='0')
            printf(" %c%c%c",A[i][0],A[i][1],A[i][2]);
        else
            printf(" %c%c",A[i][0],A[i][1]);
    }
    printf("\n");
    printf("B:");
    for(i=0;i<3;i++)
    {
        if(B[i][2]=='0')
            printf(" %c%c%c",B[i][0],B[i][1],B[i][2]);
        else
            printf(" %c%c",B[i][0],B[i][1]);
    }
    printf("\n");

2、花色和大小的权重赋值处理

以A为例,对于花色和大小进行赋值。由于大小的优先级更高,故我们将大小权重设置到十位,这样对花色的赋值不会影响到大小。这也是与基础版中要求不同的一点。

A_sum,B_sum即代表整体的分数,后面可以直接拿这个作比较。

switch(A[i][0])
        {
            case 'H':
                A_score[i][0]=4;
                break;
            case 'S':
                A_score[i][0]=3;
                break;
            case 'D':
                A_score[i][0]=2;
                break;
            case 'C':
                A_score[i][0]=1;
                break;
            default:
                printf("Input Error!\n");
                return 0;
        }
        switch(A[i][1])
        {
            case '2':
                A_score[i][1]=10;
                break;
            case '3':
                A_score[i][1]=20;
                break;
            case '4':
                A_score[i][1]=30;
                break;
            case '5':
                A_score[i][1]=40;
                break;
            case '6':
                A_score[i][1]=50;
                break;
            case '7':
                A_score[i][1]=60;
                break;
            case '8':
                A_score[i][1]=70;
                break;
            case '9':
                A_score[i][1]=80;
                break;
            case '9'+1:
                A_score[i][1]=90;
                break;
            case 'J':
                A_score[i][1]=100;
                break;
            case 'Q':
                A_score[i][1]=110;
                break;
            case 'K':
                A_score[i][1]=120;
                break;
            case 'A':
                A_score[i][1]=130;
                break;
            default:
                printf("Input Error!\n");
                return 0;
        }
        A_sum[i]=A_score[i][0]+A_score[i][1];

3、对'10'的单独处理

这个前面都已提到,一个是在输入时将数组由三位转换为两位,输出时在转变回来,另一个则是要注意运算时位数的统一。

4、四种特殊情况的再次加权赋值

按照优先级对四种特殊情况进行再次加权,这里前面设置A_sum[3]、B_sum[3]的好处就体现出来了,一方面经上面排序后数组数值已经是有序状态,便于更改和调用,另一方面后续比较的关键在于数组中的第一个值,故减少了计算量。

    //同花顺
    if(A_sum[0]%10==A_sum[1]%10&&A_sum[1]%10==A_sum[2]%10&&A_sum[0]/10==(A_sum[1]/10+1)&&A_sum[1]/10==(A_sum[2]/10+1))
        A_sum[0]*=10000;    
    //炸弹
    else if(A_sum[0]/10==A_sum[1]/10&&A_sum[1]/10==A_sum[2]/10)
        A_sum[0]*=1000;   
    //连牌
    else if(A_sum[0]/10==(A_sum[1]/10+1)&&A_sum[1]/10==(A_sum[2]/10+1)&&!(A_sum[0]%10==A_sum[1]%10&&A_sum[1]%10==A_sum[2]%10))
        A_sum[0]*=100;
    //对子
    else if(A_sum[0]/10==A_sum[1]/10||A_sum[1]/10==A_sum[2]/10||A_sum[0]/10==A_sum[2]/10)
        A_sum[0]*=10;

    //同花顺
    if(B_sum[0]%10==B_sum[1]%10&&B_sum[1]%10==B_sum[2]%10&&B_sum[0]/10==(B_sum[1]/10+1)&&B_sum[1]/10==(B_sum[2]/10+1))
        B_sum[0]*=10000;
    //炸弹
    else if(B_sum[0]/10==B_sum[1]/10&&B_sum[1]/10==B_sum[2]/10)
        B_sum[0]*=1000;
    //连牌
    else if(B_sum[0]/10==(B_sum[1]/10+1)&&B_sum[1]/10==(B_sum[2]/10+1)&&!(B_sum[0]%10==B_sum[1]%10&&B_sum[1]%10==B_sum[2]%10))
        B_sum[0]*=100;
    //对子
    else if(B_sum[0]/10==B_sum[1]/10||B_sum[1]/10==B_sum[2]/10||B_sum[0]/10==B_sum[2]/10)
        B_sum[0]*=10;

完整代码

#include<stdio.h>

int main()
{
//先比大小,再比花色
    char A[3][3],B[3][3];
    int A_score[3][2],B_score[3][2],A_sum[3],B_sum[3];
    int i,j,temp;
    char ctemp1,ctemp2;

//输入中只有10是特殊的,所以我们希望能将所有的输入都转变成两位的形式,这样方便后续的处理和比较
//注意:输入中无10,第三位为空格;若有10,则将第二位转变为'9'+1,第三位转变为0,并补上空格
    for(i=0;i<3;i++)
    {
        scanf("%c%c%c",&A[i][0],&A[i][1],&A[i][2]);
        if(A[i][1]=='1'&&A[i][2]=='0')
        {
            A[i][1]='9'+1;
            A[i][2]=0;
            if(i!=2)
                scanf(" ");
        }
    }
    scanf("\n");
    for(i=0;i<3;i++)
    {
        scanf("%c%c%c",&B[i][0],&B[i][1],&B[i][2]);
        if(B[i][1]=='1'&&B[i][2]=='0')
        {
            B[i][1]='9'+1;
            B[i][2]=0;
            if(i!=2)
                scanf(" ");
        }
    }


//A_sum,B_sum即代表整体的分数,后面可以直接拿这个作比较
    for(i=0;i<3;i++)
    {
        switch(A[i][0])
        {
            case 'H':
                A_score[i][0]=4;
                break;
            case 'S':
                A_score[i][0]=3;
                break;
            case 'D':
                A_score[i][0]=2;
                break;
            case 'C':
                A_score[i][0]=1;
                break;
            default:
                printf("Input Error!\n");
                return 0;
        }
        switch(A[i][1])
        {
            case '2':
                A_score[i][1]=10;
                break;
            case '3':
                A_score[i][1]=20;
                break;
            case '4':
                A_score[i][1]=30;
                break;
            case '5':
                A_score[i][1]=40;
                break;
            case '6':
                A_score[i][1]=50;
                break;
            case '7':
                A_score[i][1]=60;
                break;
            case '8':
                A_score[i][1]=70;
                break;
            case '9':
                A_score[i][1]=80;
                break;
            case '9'+1:
                A_score[i][1]=90;
                break;
            case 'J':
                A_score[i][1]=100;
                break;
            case 'Q':
                A_score[i][1]=110;
                break;
            case 'K':
                A_score[i][1]=120;
                break;
            case 'A':
                A_score[i][1]=130;
                break;
            default:
                printf("Input Error!\n");
                return 0;
        }
        A_sum[i]=A_score[i][0]+A_score[i][1];

        switch(B[i][0])
        {
            case 'H':
                B_score[i][0]=4;
                break;
            case 'S':
                B_score[i][0]=3;
                break;
            case 'D':
                B_score[i][0]=2;
                break;
            case 'C':
                B_score[i][0]=1;
                break;
            default:
                printf("Input Error!\n");
                return 0;
        }
        switch(B[i][1])
        {
            case '2':
                B_score[i][1]=10;
                break;
            case '3':
                B_score[i][1]=20;
                break;
            case '4':
                B_score[i][1]=30;
                break;
            case '5':
                B_score[i][1]=40;
                break;
            case '6':
                B_score[i][1]=50;
                break;
            case '7':
                B_score[i][1]=60;
                break;
            case '8':
                B_score[i][1]=70;
                break;
            case '9':
                B_score[i][1]=80;
                break;
            case '9'+1:
                B_score[i][1]=90;
                break;
            case 'J':
                B_score[i][1]=100;
                break;
            case 'Q':
                B_score[i][1]=110;
                break;
            case 'K':
                B_score[i][1]=120;
                break;
            case 'A':
                B_score[i][1]=130;
                break;
            default:
                printf("Input Error!\n");
                return 0;
        }
        B_sum[i]=B_score[i][0]+B_score[i][1];
    }

//有了前面的铺垫,这里就是一个简单的冒泡排序,需要关注的就是对于数字和字符的分离但同步的处理
    for(i=0;i<2;i++)
    {
        if(A_sum[i]==A_sum[i+1]||B_sum[i]==B_sum[i+1])
        {
            printf("Input Error!\n");
            return 0;
        }
        for(j=0;j<2-i;j++)
        {
            if(A_sum[j]<A_sum[j+1])
            {
                temp=A_sum[j];
                A_sum[j]=A_sum[j+1];
                A_sum[j+1]=temp;
                
                ctemp1=A[j][0];
                ctemp2=A[j][1];
                A[j][0]=A[j+1][0];
                A[j][1]=A[j+1][1];
                A[j+1][0]=ctemp1;
                A[j+1][1]=ctemp2;
            }
            if(B_sum[j]<B_sum[j+1])
            {
                temp=B_sum[j];
                B_sum[j]=B_sum[j+1];
                B_sum[j+1]=temp;
                
                ctemp1=B[j][0];
                ctemp2=B[j][1];
                B[j][0]=B[j+1][0];
                B[j][1]=B[j+1][1];
                B[j+1][0]=ctemp1;
                B[j+1][1]=ctemp2;
            }
        }      
    }

    //同花顺
    if(A_sum[0]%10==A_sum[1]%10&&A_sum[1]%10==A_sum[2]%10&&A_sum[0]/10==(A_sum[1]/10+1)&&A_sum[1]/10==(A_sum[2]/10+1))
        A_sum[0]*=10000;    
    //炸弹
    else if(A_sum[0]/10==A_sum[1]/10&&A_sum[1]/10==A_sum[2]/10)
        A_sum[0]*=1000;   
    //连牌
    else if(A_sum[0]/10==(A_sum[1]/10+1)&&A_sum[1]/10==(A_sum[2]/10+1)&&!(A_sum[0]%10==A_sum[1]%10&&A_sum[1]%10==A_sum[2]%10))
        A_sum[0]*=100;
    //对子
    else if(A_sum[0]/10==A_sum[1]/10||A_sum[1]/10==A_sum[2]/10||A_sum[0]/10==A_sum[2]/10)
        A_sum[0]*=10;

    //同花顺
    if(B_sum[0]%10==B_sum[1]%10&&B_sum[1]%10==B_sum[2]%10&&B_sum[0]/10==(B_sum[1]/10+1)&&B_sum[1]/10==(B_sum[2]/10+1))
        B_sum[0]*=10000;
    //炸弹
    else if(B_sum[0]/10==B_sum[1]/10&&B_sum[1]/10==B_sum[2]/10)
        B_sum[0]*=1000;
    //连牌
    else if(B_sum[0]/10==(B_sum[1]/10+1)&&B_sum[1]/10==(B_sum[2]/10+1)&&!(B_sum[0]%10==B_sum[1]%10&&B_sum[1]%10==B_sum[2]%10))
        B_sum[0]*=100;
    //对子
    else if(B_sum[0]/10==B_sum[1]/10||B_sum[1]/10==B_sum[2]/10||B_sum[0]/10==B_sum[2]/10)
        B_sum[0]*=10;


    if(A_sum[0]==B_sum[0])
    {
        if(A_sum[1]==B_sum[1])
        {
            if(A_sum[2]==B_sum[2])
            {
                printf("Draw!\n");
            }
            else if(A_sum[2]>B_sum[2])
            {
                printf("Winner is A!\n");
            }
            else
            {
                printf("Winner is B!\n");
            }
        }
        else if(A_sum[1]>B_sum[1])
        {
            printf("Winner is A!\n");
        }
        else
        {
            printf("Winner is B!\n");
        }
    }
    else if(A_sum[0]>B_sum[0])
    {
        printf("Winner is A!\n");
    }
    else if(A_sum[0]<B_sum[0])
    {
        printf("Winner is B!\n");
    }

//这一步也至关重要,是对第一步处理的还原,将'9'+1还原为'10'
    for(i=0;i<3;i++)
    {
        if(A[i][1]=='9'+1)
        {
            A[i][1]='1';
            A[i][2]='0';
        }
        if(B[i][1]=='9'+1)
        {
            B[i][1]='1';
            B[i][2]='0';
        }
    }
    
//输出结果
    printf("A:"); 
    for(i=0;i<3;i++)
    {
        if(A[i][2]=='0')
            printf(" %c%c%c",A[i][0],A[i][1],A[i][2]);
        else
            printf(" %c%c",A[i][0],A[i][1]);
    }
    printf("\n");
    printf("B:");
    for(i=0;i<3;i++)
    {
        if(B[i][2]=='0')
            printf(" %c%c%c",B[i][0],B[i][1],B[i][2]);
        else
            printf(" %c%c",B[i][0],B[i][1]);
    }
    printf("\n");
    return 0;
}

以上就是本次分享的全部内容啦,此题当然还有很多种解法,小橘也还在学习中,水平有限,如有考虑不周之处烦请各位不吝赐教:)

如果各位客官觉得小橘写得还算用心,可以动动发财的小手点赞关注,大家的支持也是我更新的动力,在此谢过各位嘿嘿:>

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值