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

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章