题目:
背景:
两个人每人发3张牌(各从一副牌中),每张牌包括花色(红桃(Heart)>黑桃(Spade)>方块(Diamond)>梅花(Club))和大小(从小到大依次是:2-10、J、Q、K、A),谁手上有最大的一张或多张(如果有相同的牌)牌谁获胜。
输入:
A的3张牌(未排序)和B的3张牌(未排序)。(参见用例)
输出:
A的3张牌的排序后的输出和B的3张牌的排序后的输出,以及A和B谁获胜。(参见用例)
测试用例:
问题分析及解决思路:
题中重要信息总结:
1.输入一直是两人共六张牌,大体格式不变;
2.两人各从一副牌中发牌,即一个人不能有与自己相同的牌,但可以有与他人相同的牌;
3.可能有不合法输入,包含花色、点数、牌的唯一性问题;
4.排序时花色的优先级高于点数;
5.点数中存在10,与其它点数有位数上的区别;
6.输出时首先要输出胜者,若平局则输出X为胜者;
7.需要输出两人按从大到小顺序的手牌,还有不能忘记"A:"和"B:";
可能存在的困惑点:
1.以什么方式储存两人共六张牌;
2.如何对手牌进行排序;
解决问题的思路:
1.以两个3行4列的二维字符数组储存,4列可以预留最后一个'\0'的位置;
2.首先利用字符数组存储各花色、点数大小的相对位置,用字符数组对应下标的大小比较其大小,并结合冒泡排序思路实现对手牌的排序;
完整代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//构造函数判断手牌是否合法
void check(char(*in)[4])
{
//定义所需变量及点数可能性
int i = 0, j = 0;
char possible[12] = { '2','3','4','5','6','7','8','9','J','Q','K','A' };
//判断是否有重复的手牌
if (strcmp(in[0], in[1]) == 0 || strcmp(in[1], in[2]) == 0 || strcmp(in[0], in[2]) == 0)
{
printf("Input Error!\n");
exit(-1);
}
//判断花色是否合法
for (i = 0; i < 3; i++)
{
if (in[i][0] == 'H' || in[i][0] == 'S' || in[i][0] == 'D' || in[i][0] == 'C')
continue;
else
{
printf("Input Error!\n");
exit(-1);
}
}
//判断点数是否合法
for (i = 0; i < 3; i++)
{
//先判断点数第二位是否合法
if (in[i][2] == '0' || in[i][2] == '\0')
{
//点数为一位时
if (in[i][2] == '\0')
{
//判断一位的点数是否合法
int flag = 0;
for (j = 0; j < 12; j++)
{
if (in[i][1] == possible[j]) flag = 1;
}
//一位点数合法
if (flag)
continue;
//一位点数不合法
else
{
printf("Input Error!\n");
exit(-1);
}
}
//点数为两位时
else
{
//点数为10
if (in[i][1] == '1')
continue;
//点数为两位,但不为10
else
{
printf("Input Error!\n");
exit(-1);
}
}
}
//点数第二位不合法
else
{
printf("Input Error!\n");
exit(-1);
}
}
}
//构造函数对手牌进行排序,采取"以1代10"的方式处理两位点数
void sort(char(*in)[4])
{
//定义所需变量及花色、点数顺序表
int i = 0, j = 0, k = 0, temp1 = 0, temp2 = 0;
char colororder[4] = { 'C','D','S','H' };
char pointorder[13] = { '2','3','4','5','6','7','8','9','1','J','Q','K','A' };
//对花色进行排序(类似冒泡排序)
for (k = 0; k < 2; k++)
{
for (i = 0; i < 2 - k; i++)
{
//记下前后两个的花色大小
for (j = 0; j < 4; j++)
{
if (in[i][0] == colororder[j])
{
temp1 = j;
break;
}
else
continue;
}
for (j = 0; j < 4; j++)
{
if (in[i + 1][0] == colororder[j])
{
temp2 = j;
break;
}
else
continue;
}
//判断前后花色的大小,若需要则交换次序
if (temp1 < temp2)
{
char temp[4] = { '\0' };
strcpy(temp, in[i + 1]);
strcpy(in[i + 1], in[i]);
strcpy(in[i], temp);
}
else
continue;
}
}
//对点数进行排序(此处完全地跑两次较保险)
for (k = 0; k < 2; k++)
{
for (i = 0; i < 2; i++)
{
//判断花色是否一致
if (in[i][0] == in[i + 1][0])
{
//记下前后两个的点数大小
for (j = 0; j < 13; j++)
{
if (in[i][1] == pointorder[j])
{
temp1 = j;
break;
}
else
continue;
}
for (j = 0; j < 13; j++)
{
if (in[i + 1][1] == pointorder[j])
{
temp2 = j;
break;
}
else
continue;
}
//判断前后点数的大小,若需要则交换次序
if (temp1 < temp2)
{
char temp[4] = { '\0' };
strcpy(temp, in[i + 1]);
strcpy(in[i + 1], in[i]);
strcpy(in[i], temp);
}
else
continue;
}
else
continue;
}
}
}
//构造函数比较二者手牌
int compare(char(*a)[4], char(*b)[4])
{
//定义所需变量及花色、点数顺序表
int i = 0,j=0, temp1 = 0, temp2 = 0;
char colororder[4] = { 'C','D','S','H' };
char pointorder[13] = { '2','3','4','5','6','7','8','9','1','J','Q','K','A' };
//逐个比较二者手牌
for (i = 0; i < 3; i++)
{
//记下a、b两个手牌的花色大小
for (j = 0; j < 4; j++)
{
if (a[i][0] == colororder[j])
{
temp1 = j;
break;
}
else
continue;
}
for (j = 0; j < 4; j++)
{
if (b[i][0] == colororder[j])
{
temp2 = j;
break;
}
else
continue;
}
//比较手牌花色大小
if (temp1 > temp2)
return 1;
else
{
if (temp1 < temp2)
return 2;
//a,b花色一致
else
{
//记下a、b两个手牌的点数大小
for (j = 0; j < 13; j++)
{
if (a[i][1] == pointorder[j])
{
temp1 = j;
break;
}
else
continue;
}
for (j = 0; j < 13; j++)
{
if (b[i][1] == pointorder[j])
{
temp2 = j;
break;
}
else
continue;
}
if (temp1 > temp2)
return 1;
else
{
if (temp1 < temp2)
return 2;
else
continue;
}
}
}
}
return 0;
}
//主函数部分
int main()
{
//定义存储二者手牌的空间及所需变量
char a[3][4] = { '\0' }, b[3][4] = { '\0' };
int i = 0;
//输入手牌,用getchar函数清除缓存区
for (i = 0; i < 3; i++)
{
scanf("%s", a[i]);
getchar();
}
for (i = 0; i < 3; i++)
{
scanf("%s", b[i]);
getchar();
}
//判断手牌是否合法
check(a);
check(b);
//对手牌进行排序
sort(a);
sort(b);
//比较二者手牌
int flag = compare(a, b);
//判断比较结果
switch (flag)
{
case 1:printf("Winner is A!\n"); break;
case 2:printf("Winner is B!\n"); break;
case 0:printf("Winner is X!\n"); break;
}
//输出排序后的二者手牌
printf("A:");
for (i = 0; i < 3; i++)
{
printf(" %s", a[i]);
}
printf("\n");
printf("B:");
for (i = 0; i < 3; i++)
{
printf(" %s", b[i]);
}
printf("\n");
return 0;
}
结语:
本文只是记录自己的做题历程,对于该题目来说,算法绝对不是最简单的,代码也一定有很多地方值得优化,欢迎也期待各位大佬的留言。