背景:两个人每人发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,我们得用一个三元字符数组存储一张牌,同时得存储每一个人的三张牌。
考虑到每个人的牌都是从一副完整牌组中取得,因此不存在两张完全相同的牌。据此,我们可以写出两个函数检验输入是否合理。check1检验花色,check2检验点数。
用一个循环处理输入,每次输入三个字符,除10以外的牌都包含了空格。单独考虑10的情况,需要额外取出一个空格。同时考虑到之后要对点数进行比较,可以先把10转化为‘9’后一个。
我们设置一个标志error记录输入情况。
b的输入类似。
如果输入错误,直接输出结果。接下来考虑有效输入。
由于需要判断顺子等牌型,我们对点数进行调整使满足连贯性。
同时我们要比较每张牌的大小,根据点数优先写出比较函数。
注意,此处对红桃进行升格处理,是利用花色ASCII码的特性(要求H>S>D>C),可以根据个人喜好合理调整。
利用cmp2函数写出如下的冒泡排序函数。
考虑到比较大小时牌型优先级最高,由大到小排序后我们写出判断牌型的函数。
由于以上函数调用传递的都是指针变量,并且对其指向的值做了一定修改,我们在输出时应提前复原。
最后比较大小按要求输出即可。
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
int check1(char);
int check2(char);
int cmp(char a[2],char b[2]);
int cmp2(char a[],char b[]);
void sort2(char a[3][3]);
void restore(char a[2]);
void change(char a[3][3]);
int card_type(char a[3][3]);
enum kind {straight_flush,three,straight,pair,single};
int main()
{
char a[3][3]={0},b[3][3]={0};
int i=0,j=0,error=0,flag;
for(i=0;i<3;i++)//input and check
{
scanf("%c%c%c",&a[i][0],&a[i][1],&a[i][2]);
if(a[i][2]=='0'){a[i][1]='9'+1;a[i][2]=0;if(i!=2)scanf(" ");}//输入有10,化为两位
if(check1(a[i][0])&&check2(a[i][1]))continue;
else
{
error=1;
break;
}
}
scanf("\n");
for(i=0;i<3;i++)
{
scanf("%c%c%c",&b[i][0],&b[i][1],&b[i][2]);
if(b[i][2]=='0'){b[i][1]='9'+1;b[i][2]=0;if(i!=2)scanf(" ");}
if(check1(b[i][0])&&check2(b[i][1]))continue;
else
{
error=1;
break;
}
}
for(i=0;i<2;i++)//检查重复
{
for(j=i+1;j<3;j++)
{
if((a[i][0]==a[j][0]&&a[i][1]==a[j][1])
||(b[i][0]==b[j][0]&&b[i][1]==b[j][1]))error=1;
}
}
if(error)printf("Input Error!\n");
else//valid input
{
change(a);change(b);//adjust the point
sort2(a);sort2(b);//sort
if(card_type(a)<card_type(b))flag=1;//a牌型大
else if(card_type(a)>card_type(b))flag=3;//a牌型小
else//同种牌型
{
for(i=0;i<3;i++)
{
if(cmp2(a[i],b[i])==1){flag=1;break;}
else if(cmp2(a[i],b[i])==3){flag=3;break;}
else {flag=2;continue;}
}
}
if(flag==1)
{
printf("Winner is A!\nA:");
}
else if(flag==2)
{
//printf("Winner is X!\nA:");
printf("Draw!\nA:");
}
else if(flag==3)
{
printf("Winner is B!\nA:");
}
for(i=0;i<3;i++)//恢复
{restore(a[i]);restore(b[i]);}
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("\nB:");
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]);
}
putchar(10);
}
system("pause");
return 0;
}
int check1(char card)//check the suits
{
if(card!='H'&&card!='S'&&card!='D'&&card!='C')return 0;//ERROR
else return 1;
}
int check2(char card)//check the points
{
if(('2'<=card&&card<='9'+1)||card=='J'||card=='Q'||card=='K'||card=='A')return 1;
else return 0;
}
int cmp(char a[2],char b[2])//花色优先//if the first is bigger,return 1;else if equal,return 2;else return 3
{
if(a[0]=='H')a[0]='T';if(b[0]=='H')b[0]='T';//给红桃升格
if(a[0]>b[0])return 1;
else if(a[0]==b[0])//the suit is the same
{
if(a[1]>b[1])return 1;
else if(a[1]==b[1])return 2;
else return 3;
}
else return 3;
}
int cmp2(char a[],char b[])//点数优先
{
if(a[0]=='H')a[0]='T';if(b[0]=='H')b[0]='T';//给红桃升格
if(a[1]>b[1])return 1;
else if(a[1]<b[1])return 3;
else
{
if(a[0]>b[0])return 1;
else if(a[0]<b[0])return 3;
else return 2;
}
}
void change(char a[3][3])//adjust the point
{
int i,j;
for(i=0;i<3;i++)
{
//if(a[i][1]=='1'&&a[i][2]=='0'){a[i][1]='9'+1;a[i][2]=0;}
if(a[i][1]=='J')a[i][1]='9'+2;
else if(a[i][1]=='Q')a[i][1]='9'+3;
else if(a[i][1]=='K')a[i][1]='9'+4;
else if(a[i][1]=='A')a[i][1]='9'+5;
}
}
void sort2(char a[3][3])
{
int i,j;char t1,t2;
for(i=0;i<2;i++)
{
for(j=0;j<2-i;j++)
{
if(cmp2(a[j],a[j+1])==3)
{
t1=a[j][0];t2=a[j][1];
a[j][0]=a[j+1][0];a[j][1]=a[j+1][1];
a[j+1][0]=t1;a[j+1][1]=t2;
}
}
}
}
void restore(char a[])//由于传递指针改变原值应恢复
{
if(a[0]=='T')a[0]='H';//给红桃升格
if(a[1]=='9'+1){a[1]='1';a[2]='0';}
else if(a[1]=='9'+2)a[1]='J';
else if(a[1]=='9'+3)a[1]='Q';
else if(a[1]=='9'+4)a[1]='K';
else if(a[1]=='9'+5)a[1]='A';
}
int card_type(char a[3][3])//排序后判断牌型
{
if(a[0][0]==a[1][0]&&a[1][0]==a[2][0]&&//同花
a[0][1]==a[1][1]+1&&a[1][1]==a[2][1]+1)//顺
return 0;
else if(a[0][1]==a[1][1]&&a[1][1]==a[2][1])return 1;//three of a kind
else if(a[0][1]==a[1][1]+1&&a[1][1]==a[2][1]+1)return 2;//straight
else if(a[0][1]==a[1][1]||a[0][1]==a[2][1]||a[1][1]==a[2][1])return 3;//pair
else return 4;//single
}