题目描述
四个人围成一圈打牌,四个方向为北、东、南、西,一共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型的数上,再进行比较,就不需要再分情况讨论,简单很多。
- 另一个关键点在于如何在发牌人不固定的前提下,将每一张牌都能准确存入到对应人的数组中,这里只需仔细观察,就能找到对应的规律,基本的对应关系在之前的解题思路中已经找到,利用这种对应关系,很简单地就能将牌的信息存入正确的位置。