(BOSS)Poker time (20 xp)

题目:

背景:

两个人每人发3张牌(各从一副牌中),每张牌包括花色(红桃(Heart)>黑桃(Spade)>方块(Diamond)>梅花(Club))和大小(从小到大依次是:2-10、J、Q、K、A),谁手上有最大的一张或多张(如果有相同的牌)牌谁获胜。

输入:

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

输出:

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

测试用例:

d7e2d2b798a441f0824f61a9c8d2cb9a.png

 

问题分析及解决思路:

题中重要信息总结:

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;
}

 

结语:

本文只是记录自己的做题历程,对于该题目来说,算法绝对不是最简单的,代码也一定有很多地方值得优化,欢迎也期待各位大佬的留言。

 

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yorunouta

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值