思路在代码注释内pwp
PS:个人做题记录,不是最优解,如有错误欢迎指正喵!
背景:两个人每人发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谁获胜。(参见用例)
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 3 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 4 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 5 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 8 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 11 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 12 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 13 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
#include<stdio.h>
#include<string.h>
int flower_key(char arr[]) //该函数与下个函数分别获取花色和数字(J Q K A当作数字)对应的值,便于计算
{ //该函数传入的是player[]的形式 即二维数组内部的一维数组
char flower[4]={'C','D','S','H'};
for(int i=0;i<4;i++) if(arr[0]==flower[i]) return i+1;
return 0; //此时代表获取不到花色 证明花色输入错误
}
int num_key(char arr[])
{ //该函数传入的是player[]的形式 即二维数组内部的一维数组
char num[13][3]={"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
for(int i=0;i<13;i++) if(strcmp(&arr[1],num[i])==0) return i+1;
return 0; //此时代表获取不到数字 证明数字输入错误
}
int check_input(char player[][4])
{
for(int i=0;i<3;i++)//扫描输入的三张卡
{
for(int m=i+1;m<3;m++) if(strcmp(player[i],player[m])==0) return 1; //判断有无相同的两张 若有则输入错误
if(flower_key(player[i])==0 || num_key(player[i])==0) return 1; //是否能获取到花色和数字的对应的值,不能则输入错误
}
return 0; //若输入错误返回1,无误返回0
}
int player_sort(char arr[][4]) //排序玩家的卡牌,采用冒泡排序法
{
char temp[4];
for(int i=0;i<2;i++)
{
for(int m=0;m<2;m++)
{
if(num_key(arr[m])<num_key(arr[m+1])) //若数字小与后面一张 交换顺序
{
strcpy(temp,arr[m+1]);
strcpy(arr[m+1],arr[m]);
strcpy(arr[m],temp);
}
else if(num_key(arr[m])==num_key(arr[m+1]))
{
if(flower_key(arr[m])<flower_key(arr[m+1])) //数字相同比较花色
{
strcpy(temp,arr[m+1]);
strcpy(arr[m+1],arr[m]);
strcpy(arr[m],temp);
}
}
}
}
}
int get_key(char arr[][4])
{
for(int i=0;i<2;i++)//判断是否为同花顺 循环比较元素
{
if(flower_key(arr[i])!=flower_key(arr[i+1])) break; //若某一张花色与后面一张不同就跳出
//若比到倒数第二张与最后一张发现仍相同,看数字是否满足顺子
if(i==1 && num_key(arr[0])-1==num_key(arr[1]) && num_key(arr[0])-2==num_key(arr[2]) && num_key(arr[0])>=3) return 5;
}
for(int i=0;i<2;i++)//判断是否为炸弹 循环比较元素
{
if(num_key(arr[i])!=num_key(arr[i+1])) break; //若某一张与后面那张数字不同就跳出
if(i==1) return 4; //比完倒数第二张与倒数第一张仍未跳出则是炸弹
}
//判断是否为顺子
if(num_key(arr[0])-1==num_key(arr[1]) && num_key(arr[0])-2==num_key(arr[2]) && num_key(arr[0])>=3) return 3;
//判断是否为对子
if(num_key(arr[0])==num_key(arr[1]) || num_key(arr[1])==num_key(arr[2])) return 2;
return 1;//上面的情形都不是那就是单牌了
}
int double_place(char arr[][4])//此函数在传入的玩家牌有对子时返回对子两张牌中排序后位于前面的那张的角标
{
if(num_key(arr[0])==num_key(arr[1])) return 0;
else return 1;
}
int who_win(char player1[][4],char player2[][4])
{
int count=0;
for(int i=0;i<3;i++) if(strcmp(player1[i],player2[i])==0) count++;//先判断俩人三张是否一样 过滤平局情况
if(count==3) return 2;//平局 返回2
int key1=get_key(player1),key2=get_key(player2);//key代表大小,同花顺、炸弹、连牌、对子、单牌分别为 5,4,3,2,1
if(key1>key2) return 0; //key大的就是赢家,key相同在下面分情况比较
if(key1<key2) return 1;
if(key1==key2 && key1==5)//都是同花顺 判断一下大小
{
if(num_key(player1[0])>num_key(player2[0])) return 0; //数字大的是赢家
if(num_key(player1[0])<num_key(player2[0])) return 1;
if(flower_key(player1[0])>flower_key(player2[0])) return 0; //数字相同比花色
if(flower_key(player1[0])<flower_key(player2[0])) return 1;
}
if(key1==key2 && key1==4)//都是炸弹 判断一下大小
{
if(num_key(player1[0])>num_key(player2[0])) return 0; //数字大的是赢家
if(num_key(player1[0])<num_key(player2[0])) return 1;
for(int i=0;i<3;i++)//数字相同从前到后逐个比花色
{
if(flower_key(player1[i])>flower_key(player2[i])) return 0;
if(flower_key(player1[i])<flower_key(player2[i])) return 1;
}
}
if(key1==key2 && key1==3)//都是顺子 判断一下大小
{
if(num_key(player1[0])>num_key(player2[0])) return 0; //数字大的是赢家
if(num_key(player1[0])<num_key(player2[0])) return 1;
for(int i=0;i<3;i++)//数字相同从前到后逐个比花色
{
if(flower_key(player1[i])>flower_key(player2[i])) return 0;
if(flower_key(player1[i])<flower_key(player2[i])) return 1;
}
}
if(key1==key2 && key1==2)//都是对子 判断一下大小
{
int place1=double_place(player1),place2=double_place(player2);
if(num_key(player1[place1])>num_key(player2[place2])) return 0; //数字大的是赢家
if(num_key(player1[place1])<num_key(player2[place2])) return 1;
for(int i=0;i<2;i++)//数字相同从前到后逐个比花色
{
if(flower_key(player1[place1+i])>flower_key(player2[place2+i])) return 0;
if(flower_key(player1[place1+i])<flower_key(player2[place2+i])) return 1;
}
}
for(int i=0;i<3;i++) //下面判断单牌情形的大小 第一张比第一张 若相同 往后进行
{
if(num_key(player1[i])>num_key(player2[i+1])) return 0; //数字大的赢
if(num_key(player1[i])<num_key(player2[i+1])) return 1;
if(flower_key(player1[i])>flower_key(player2[i])) return 0;//数字相同看花色
if(flower_key(player1[i])<flower_key(player2[i])) return 1;
}
}
int main()
{
char player1[3][4],player2[3][4]; //采取二维数组的形式存储卡牌 第n行代表第几张 每一行代表的卡牌以字符串储存
scanf("%s %s %s",player1[0],player1[1],player1[2]);
scanf("%s %s %s",player2[0],player2[1],player2[2]);
if(check_input(player1) || check_input(player2)) //如果输入错误直接输出提示并结束
{
printf("Input Error!\n");
return 0;
}
player_sort(player1);player_sort(player2);//排序两个玩家的手牌
switch(who_win(player1,player2)) //根据who_win函数的返回值判断谁赢并输出
{
case 0: printf("Winner is A!\n");break;
case 1: printf("Winner is B!\n");break;
case 2: printf("Draw!\n");
}
printf("A:"); for(int i=0;i<3;i++) printf(" %s",player1[i]);printf("\n");//输出排序后的牌
printf("B:"); for(int i=0;i<3;i++) printf(" %s",player2[i]);printf("\n");
return 0;
}