程序设计Week2实验——C-瑞神打牌

题目描述

四个人围成一圈打牌,四个方向为北、东、南、西,一共52张牌,每人13张,指定一个发牌人(东南西北中的一个,英文首字母标识),从顺时针的下一个人开始,顺时针发牌。定义牌序:
花色:梅花(C)<方片(D)<黑桃(S)<红桃(H);
牌面:2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A。
从小到大排序每个人手中的牌,并按照指定格式输出。

Input

输入包含多组数据
每组数据的第一行包含一个大写字符,表示发牌员是谁。如果该字符为‘#’则表示输入结束。
接下来有两行,每行有52个字符,表示了26张牌,两行加起来一共52张牌。每张牌都由两个字符组成,第一个字符表示花色,第二个字符表示数值。

Output

输出多组数据发牌的结果,每组数据之后需要额外多输出一个空行!!!!!
每组数据应该由24行的组成,输出按照顺时针方向,始终先输出South Player的结果,每位玩家先输出一行即玩家名称(东南西北),接下来五行,第一行和第五行输出固定格式(见样例),第二行和第四行按顺序和格式输出数值(见样例),第三行按顺序和格式输出花色(见样例)。

样例

在这里插入图片描述
在这里插入图片描述

解题思路

  • 建立结构体来存储每张牌的信息,花色和牌面都用字符记录,并重载<,以进行sort排序;
  • 建立map的映射关系,将char映射到int上,这样就能在int上直接对牌的大小进行比较,从而实现运算符重载;
  • 建立结构体的二维数组P[4][13],用于记录每个人的每张牌的信息;
  • 因为输出的格式是固定的,而发牌的顺序是不定的,所以我们不妨令P[0]~P[3]就是输出的人的顺序,这样一来在发牌的时候就需要一个修正量,使得无论从谁开始发牌,总能使对应的牌的信息存入到对应人的数组中去,简单分析即可得到对应的关系如下:
  • 当发牌人为N时,第一张牌属于E,应存入P[3],以此类推,E对应P[0],S对应P[1],W对应P[2],基于这种关系,可以得到每一个发牌人对应的“偏移量” t;
  • 发牌时,由于每四个人一次循环,每个人可得到13张牌,因此第 i 张牌(0 <= i < 52)应该存入P[(i+t)%4][i/4]中;
  • 依照这种关系,就能实现对每个人手牌的准确记录,由此再进行排序、输出就很简单了。

实现代码

#include<iostream>
#include<map>
#include<algorithm>
using namespace std;

map<char,int> mp;		//char到int的映射,用于比较牌的大小

struct card
{//牌的结构体
	char h,v;
	bool operator<(const card &p) const
	{//利用映射map来比较大小
		if(h!=p.h)
			return mp[h]<mp[p.h];
		if(v!=p.v)
			return mp[v]<mp[p.v];
	}
};

card P[4][13];		//每个人每张牌的信息记录

int change(char c)
{//根据不同发牌人,来将每张牌存入到指定人对应的数组里
	if(c=='N')
		return 3;
	if(c=='S')
		return 1;
	if(c=='E')
		return 0;
	if(c=='W')
		return 2;
}

void output(card *p)
{//根据题目要求以及字符的性质进行输出
	cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
	for(int i=0;i<13;++i)
	{
		cout<<"|";
		if(p[i].v<58)
			cout<<p[i].v-'0'<<" "<<p[i].v-'0';
		else
			cout<<p[i].v<<" "<<p[i].v;
	}
	cout<<"|"<<endl;
	for(int i=0;i<13;++i)
		cout<<"| "<<p[i].h<<" ";
	cout<<"|"<<endl;
	for(int i=0;i<13;++i)
	{
		cout<<"|";
		if(p[i].v<58)
			cout<<p[i].v-'0'<<" "<<p[i].v-'0';
		else
			cout<<p[i].v<<" "<<p[i].v;
	}
	cout<<"|"<<endl;
	cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
}

int main()
{
	char c;
	cin>>c;
	//map初始化赋值仅在C++11中支持,故采用insert赋值map
	mp.insert(pair<char,int>('C',0));
	mp.insert(pair<char,int>('D',1));
	mp.insert(pair<char,int>('S',2));
	mp.insert(pair<char,int>('H',3));
	mp.insert(pair<char,int>('2',4));
	mp.insert(pair<char,int>('3',5));	
	mp.insert(pair<char,int>('4',6));
	mp.insert(pair<char,int>('5',7));
	mp.insert(pair<char,int>('6',8));
	mp.insert(pair<char,int>('7',9));
	mp.insert(pair<char,int>('8',10));
	mp.insert(pair<char,int>('9',11));	
	mp.insert(pair<char,int>('T',12));
	mp.insert(pair<char,int>('J',13));
	mp.insert(pair<char,int>('Q',14));
	mp.insert(pair<char,int>('K',15));
	mp.insert(pair<char,int>('A',16));
 
	while(c!='#')
	{
		char a,b;
		//依照对应关系将每张牌存入相应人所对应的数组中
		int t=change(c);
		for(int i=0;i<52;++i)			
			cin>>P[(i+t)%4][i/4].h>>P[(i+t)%4][i/4].v;
		//对每个人的手牌进行排序
		for(int i=0;i<4;++i)
			sort(P[i],P[i]+13);
		//按照格式次序输出结果
		cout<<"South player:"<<endl;
		output(P[0]);
		cout<<"West player:"<<endl;
		output(P[1]);
		cout<<"North player:"<<endl;
		output(P[2]);
		cout<<"East player:"<<endl;
		output(P[3]);
		cout<<endl;
		cin>>c;
	} 
	return 0;
}

总结

  • 本题依然是对结构体多关键字排序的考查,只要应用sort函数即可解决,而这里对于结构体内运算符重载时,利用map将字符型的数字和字母,按照题目给定的大小次序映射到int型的数上,再进行比较,就不需要再分情况讨论,简单很多。
  • 另一个关键点在于如何在发牌人不固定的前提下,将每一张牌都能准确存入到对应人的数组中,这里只需仔细观察,就能找到对应的规律,基本的对应关系在之前的解题思路中已经找到,利用这种对应关系,很简单地就能将牌的信息存入正确的位置。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值