提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
题目
扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A、2各4张,小王1张,大王1张。牌面从小到大用如下字符和字符串表示(其中,小写joker表示小王,大写JOKER表示大王):
3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER
输入两手牌,两手牌之间用"-“连接,每手牌的每张牌以空格分隔,”-"两边没有空格,如:4 4 4 4-joker JOKER。
请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR。
基本规则:
(1)输入每手牌可能是个子、对子、顺子(连续5张)、三个、炸弹(四个)和对王中的一种,不存在其他情况,由输入保证两手牌都是合法的,顺子已经从小到大排列;
(2)除了炸弹和对王可以和所有牌比较之外,其他类型的牌只能跟相同类型的存在比较关系(如,对子跟对子比较,三个跟三个比较),不考虑拆牌情况(如:将对子拆分成个子);
(3)大小规则跟大家平时了解的常见规则相同,个子、对子、三个比较牌面大小;顺子比较最小牌大小;炸弹大于前面所有的牌,炸弹之间比较牌面大小;对王是最大的牌;
(4)输入的两手牌不会出现相等的情况。
数据范围:字符串长度:3\le s\le 10\3≤s≤10 。
输入描述:
输入两手牌,两手牌之间用"-“连接,每手牌的每张牌以空格分隔,”-"两边没有空格,如 4 4 4 4-joker JOKER。
输出描述:
输出两手牌中较大的那手,不含连接符,扑克牌顺序不变,仍以空格隔开;如果不存在比较关系则输出ERROR。
最蠢的解法,不知道谁给我的勇气用200多行代码去解一道题,也许是梁静茹吧!
一、题目介绍
这道题首先需要注意的是题目要求,已经说了只能是一张/两张/三张/四张/五张扑克牌,需要注意的是两张一定是对子或者是王炸,三张一定是牌数一样的三个牌,四张一定是炸弹,五张一定是顺子。了解了这些,就好像写扫雷一样,慢慢满足条件,慢慢改就行了。
二、分析
1.尽量简答表示
我认为的是读取出来的牌数比如:大王JOKER和小王joker还有10这三种牌最好换一个表示方式,不然存储和读取起来较为麻烦,最终存储的是大王:W,小王:w,10:S,表示,然后比较大小的时候,字符之间比较也比较麻烦,故使用a b c d e f…等等代替原来的牌数进行比较。
2.拉跨的源码
代码如下(示例):
#include <stdio.h>
#include <string.h>
char ptoa(char po)
{
switch(po)//使用小写字母代替进行比较
{
case '3':return 'a';
case '4':return 'b';
case '5':return 'c';
case '6':return 'd';
case '7':return 'e';
case '8':return 'f';
case '9':return 'g';
case 'S':return 'h';
case 'J':return 'i';
case 'Q':return 'j';
case 'K':return 'k';
case 'A':return 'm';
case '2':return 'n';
case 'w':return 'o';
case 'W':return 'p';
default: return 0;
}
}
int PokerCmp(char po1, char po2)//比较两个牌的大小
{
char tmp1 = ptoa(po1);
char tmp2 = ptoa(po2);
if(tmp1 > tmp2)
{
return 1;
}
else if(tmp1 < tmp2)
{
return -1;
}
else
{
return 0;
}
}
void PokerPrint(char* poker1, char* poker2, int ret, int len)//打印赢的牌数
{
int i = 0;
if(ret > 0)
{
for(i = 0; i < len; i++)
{
if(poker1[i] == 'w')
{
printf("joker ");
}
else if(poker1[i] == 'W')
{
printf("JOKER ");
}
else if(poker1[i] == 'S')
{
printf("10 ");
}
else
{
printf("%c ", poker1[i]);
}
}
}
else
{
for(i = 0; i < len; i++)
{
if(poker2[i] == 'w')
{
printf("joker ");
}
else if(poker2[i] == 'W')
{
printf("JOKER ");
}
else if(poker2[i] == 'S')
{
printf("10 ");
}
else
{
printf("%c ", poker2[i]);
}
}
}
}
int main()
{
char str[50] = {0};
scanf("%[^\n]", str);
char* s1 = "joker";
char* s2 = "JOKER";
char* s3 = "10";
char* tmp1 = strstr(str, s1);//把大小王转换为字符'w'避免使用二维数组
char* tmp2 = strstr(str, s2);
char* tmp3 = strstr(str,s3);
int i = 0;
char poker1[10] = {0};
char poker2[10] = {0};
if(tmp1 != NULL)
{
tmp1[0] = 'w';//转换为w,后面的变成空格,方便去除
for(i = 1; i < 5; i++)
{
tmp1[i] = ' ';
}
}
if(tmp2 != NULL)
{
tmp2[0] = 'W';
for(i = 1; i < 5; i++)
{
tmp2[i] = ' ';
}
}
while(tmp3 != NULL)//注意这里替换10的时候不同,10可以出现多次,需要用调用多次strstr寻找,小王和大王只有一次
{//保证10全部替换成S
tmp3[0] = 'S';
for(i = 1; i < 2; i++)
{
tmp3[i] = ' ';
}
tmp3 = strstr(str,s3);
}
int pos = 0;
int len1 = 0;
int len2 = 0;
while(str[pos] != '-')//前半部分的牌数
{
if(str[pos] != ' ')
{
poker1[len1] = str[pos];
len1++;
}
pos++;
}
pos++;//跳过-
while(str[pos] != '\0')//后半部分牌数
{
if(str[pos] != ' ')
{
poker2[len2] = str[pos];
len2++;
}
pos++;
}
int ret = 0;
if(len1 == len2)//纸牌数相同
{
switch(len1)
{
case 1://1张牌
ret = PokerCmp(poker1[0], poker2[0]);
PokerPrint(poker1, poker2, ret, len1);
break;
case 2:
ret = PokerCmp(poker1[0], poker2[0]);
PokerPrint(poker1, poker2, ret, len1);
break;
case 3:
ret = PokerCmp(poker1[0], poker2[0]);
PokerPrint(poker1, poker2, ret, len1);
break;
case 4:
ret = PokerCmp(poker1[0], poker2[0]);
PokerPrint(poker1, poker2, ret, len1);
break;
case 5:
ret = PokerCmp(poker1[0], poker2[0]);
PokerPrint(poker1, poker2, ret, len1);
break;
}
}
else//纸牌数不同时比较
{//按照poker进行分类
if(len1 == 4)//poker1四张牌
{
if(poker2[0] == 'w')
{
PokerPrint(poker1, poker2, -1, len2);
}
else
{
PokerPrint(poker1, poker2, 1, len1);
}
}
else if(len1 == 2)//poker1两张牌
//故poker2不可能是两张牌,故不可能是王炸
{
if(poker1[0] == 'w')
{
PokerPrint(poker1, poker2, 1, len1);
}
else if(len2 == 4)
{
PokerPrint(poker1, poker2, -1, len2);
}
else
{
printf("ERROR");
}
}
else//poker1既不是4张,也不是两张
{
if(poker2[0] == 'w')
{
PokerPrint(poker1, poker2, -1, len2);
}
else if(len2 == 4)
{
PokerPrint(poker1, poker2, -1, len2);
}
else
{
printf("ERROR");
}
}
}
return 0;
}
总结
虽然是烂活,但胜在思路比较清晰,没有复杂的数据结构,仅仅是分析情况或者转换数据的时候麻烦了些,介绍都在源码的注释中。