SDU--C - 瑞神打牌

题目描述

瑞神HRZ因为疫情在家闲得无聊,同时他又非常厉害,所有的课对他来说都是水一水就能拿A+,所以他无聊,找来了另外三个人:咕咕东,腾神以及zjm来打牌(天下苦瑞神久矣)。
显然,牌局由四个人构成,围成一圈。我们称四个方向为北 东 南 西。对应的英文是North,East,South,West。游戏一共由一副扑克,也就是52张构成。开始,我们指定一位发牌员(东南西北中的一个,用英文首字母标识)开始发牌,发牌顺序为顺时针,发牌员第一个不发自己,而是发他的下一个人(顺时针的下一个人)。这样,每个人都会拿到13张牌。
现在我们定义牌的顺序,首先,花色是(梅花)<(方片)<(黑桃)<(红桃),(输入时,我们用C,D,S,H分别表示梅花,方片,黑桃,红桃,即其单词首字母)。对于牌面的值,我们规定2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A。
现在你作为上帝,你要从小到大排序每个人手中的牌,并按照给定格式输出。(具体格式见输出描述和样例输出)。

输入

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

输出

  根据这些学生的得分现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出。

样例输入

  NCTCAH8CJD4C6D9SQC7S5HAD2HJH9CKD3H6D6D7H3HQH4C5DKHKS9SJDTS3S7S4C4CQHTSAH2D8DJSTSKS2H5D5DQDAH7C9S8C8S6C2C3#

样例输出

在这里插入图片描述

思路

综述

该题涉及到的知识:
1)多关键字排序
对于多关键字排序的题目,可以构造结构体P,重载小于号,再构造优先队列priority_queue<P>,从而达到排序的目的;
2)map的利用
因为不同的花色,代表的大小不同,但是代表花色的字母代号并不是按照ASCII码顺序排列,(梅花)<(方片)<(黑桃)<(红桃),(输入时,我们用C,D,S,H分别表示梅花,方片,黑桃,红桃,即其单词首字母)所以可以如下操作:

map<char,int> mp;
	mp['C'] = 1;
	mp['D'] = 2;
	mp['S'] = 3;
	mp['H'] = 4;

对于牌号码的大小也相同:2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A

	mp['2'] = 1;
	mp['3'] = 2;
	mp['4'] = 3;
	mp['5'] = 4;
	mp['6'] = 5;
	mp['7'] = 6;
	mp['8'] = 7;
	mp['9'] = 8;
	mp['T'] = 9;
	mp['J'] = 10;
	mp['Q'] = 11;
	mp['K'] = 12;
	mp['A'] = 13;

过程

结构体:

struct P {
	char card;//花色
	char value;//数值
	bool operator < (const P &p)const{
		if(card!=p.card) return mp[card]>mp[p.card];//先按照花色排序
		return mp[value]>mp[p.value];//再按照数值排序
	}
};

step1:
接收发牌人,记录其编号

		cin>>x;
		int first;
		for(i=0;i<=3;i++)
		if(mp2[i]==x) first = i;

step2:
接收所有牌,并且分发给四个人
四个人的牌存在优先队列数组内:priority_queue<P> pai[4];
fapai(int):记录下一张牌应发的人

		string s1,s2;
		cin>>s1>>s2;
		s1+=s2;
		int fapai = (first+1)%4;//从发牌人下一个开始
	    P nextcard;
		for(i=0;i<s1.size();i++){
			nextcard.card = s1[i];
			nextcard.value = s1[++i];
			pai[fapai].push(nextcard);
			fapai=(fapai+1) % 4;//构成循环
		}

step3:
输出
因为每一个优先队列已经按顺序排好,所以只需要顺序输出即可
对每个人:
分三波:牌号–>花色->牌号
构造结构体数组

struct P term[13];

第一次输出牌号的时候,顺便记录所有牌,第二三次顺序输出即可;

出现的小问题

sizeof和strlen的应用

  1. strlen() 时函数,他在程序运行时才能计算。它的参数类型要求时 char *,且必须是以’/0’结尾。数组在传入时已经退化为指针。它的作用是返回数组中字符串的长度。
  2. sizeof()时运算符,它在程序编译时就已经计算好了,用于计算数据空间的字节数。所以它不能用于返回动态分配的内存空间大小,常用于静态分配的类型,对象,结构或数组所占的空间。返回值和他们所存储的内容没有关系。

下图是dev中的输出:
在这里插入图片描述
下三图是VS中的输出:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
所以,strlen()来求解字符数组,并不是很好的选择。

因为优先队列输出完后,为空。不能再从头输出一遍。但是如果再构造一个优先队列,采用复制构造函数。这样虽然可以正确输出,但是时间复杂度高,结果是超时;
所以,构造了一个结构体数组,这样后两遍便不需要再构造优先队列。

代码

#include <iostream>
#include <map>
#include <queue>
#include <string>
using namespace std;
map<char,int> mp;
struct P {
	char card;
	char value;
	bool operator < (const P &p)const{
		if(card!=p.card) return mp[card]>mp[p.card];
		return mp[value]>mp[p.value];
	}
};	
int main(){
	
	map<int,char> mp2;
	
	mp2[0]='N';
	mp2[1]='E';
	mp2[2]='S';
	mp2[3]='W';
	
	mp['C'] = 1;
	mp['D'] = 2;
	mp['S'] = 3;
	mp['H'] = 4;
	
	mp['2'] = 1;
	mp['3'] = 2;
	mp['4'] = 3;
	mp['5'] = 4;
	mp['6'] = 5;
	mp['7'] = 6;
	mp['8'] = 7;
	mp['9'] = 8;
	mp['T'] = 9;
	mp['J'] = 10;
	mp['Q'] = 11;
	mp['K'] = 12;
	mp['A'] = 13;
	
	int n,i,j,k;
	char x;
	priority_queue<P> pai[4];
	
	while(1){
		cin>>x;
		if(x=='#')break;
		
		int first;
		for(i=0;i<=3;i++)
		if(mp2[i]==x) first = i;
		
		string s1,s2;
		cin>>s1>>s2;
		s1+=s2;
		
		int fapai = (first+1)%4;
	    P nextcard;
		for(i=0;i<s1.size();i++){
			nextcard.card = s1[i];
			nextcard.value = s1[++i];
			pai[fapai].push(nextcard);
			fapai=(fapai+1) % 4;
		}
		
//		输出 
		P term[13]; 
		int sx;
		cout<<"South player:"<<endl;
		cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl; 
		for(sx=0;sx<13;sx++){
			term[sx].card = pai[2].top().card;
			term[sx].value = pai[2].top().value;
			cout<<"|"<<term[sx].value<<" "<<term[sx].value;
			pai[2].pop(); 
		}
		cout<<"|"<<endl;
		for(sx=0;sx<13;sx++){
		cout<<"| "<<term[sx].card<<" ";
		}
		cout<<"|"<<endl;
		for(sx=0;sx<13;sx++){
			cout<<"|"<<term[sx].value<<" "<<term[sx].value;
		}
		cout<<"|"<<endl;		
		cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
		
		cout<<"West player:"<<endl;
		cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl; 
		for(sx=0;sx<13;sx++){
			term[sx].card = pai[3].top().card;
			term[sx].value = pai[3].top().value;
			cout<<"|"<<term[sx].value<<" "<<term[sx].value;
			pai[3].pop(); 
		}
		cout<<"|"<<endl;
		for(sx=0;sx<13;sx++){
		cout<<"| "<<term[sx].card<<" ";
		}
		cout<<"|"<<endl;
		for(sx=0;sx<13;sx++){
			cout<<"|"<<term[sx].value<<" "<<term[sx].value;
		}
		cout<<"|"<<endl;		
		cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
		
		cout<<"North player:"<<endl;
		cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl; 
		for(sx=0;sx<13;sx++){
			term[sx].card = pai[0].top().card;
			term[sx].value = pai[0].top().value;
			cout<<"|"<<term[sx].value<<" "<<term[sx].value;
			pai[0].pop(); 
		}
		cout<<"|"<<endl;
		for(sx=0;sx<13;sx++){
		cout<<"| "<<term[sx].card<<" ";
		}
		cout<<"|"<<endl;
		for(sx=0;sx<13;sx++){
			cout<<"|"<<term[sx].value<<" "<<term[sx].value;
		}
		cout<<"|"<<endl;		
		cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
		
		cout<<"East player:"<<endl;
		cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl; 
		for(sx=0;sx<13;sx++){
			term[sx].card = pai[1].top().card;
			term[sx].value = pai[1].top().value;
			cout<<"|"<<term[sx].value<<" "<<term[sx].value;
			pai[1].pop(); 
		}
		cout<<"|"<<endl;
		for(sx=0;sx<13;sx++){
		cout<<"| "<<term[sx].card<<" ";
		}
		cout<<"|"<<endl;
		for(sx=0;sx<13;sx++){
			cout<<"|"<<term[sx].value<<" "<<term[sx].value;
		}
		cout<<"|"<<endl;		
		cout<<"+---+---+---+---+---+---+---+---+---+---+---+---+---+"<<endl;
		cout<<endl; 
	}

}


发布了29 篇原创文章 · 获赞 14 · 访问量 1266

猜你喜欢

转载自blog.csdn.net/weixin_44552961/article/details/104665158