第一周PTA筆記 德州撲克題解


德州撲克

最近,阿誇迷於德州撲克。所以她找到了很多人和她一起玩。由於人數眾多,阿誇必須更改游戲規則:
所有撲克牌均只看數字,不計花色。
每張卡的值為1、2、3、4、5、6、7、8、9、10、11、12、13 中的一種(對應A,2、3、4、5、6、7, 8、9、10,J,Q,K)
每位玩家從一副完整的撲克牌(沒有大小王)中抽出五張撲克牌,可能出現的手牌的值從低到高排列如下:
高牌:不包含以下牌的牌。對於都是高牌的牌,按照五張牌的值的和進行從大到小排序。
對子:手中的5張牌中有2張相同值的牌。對於都擁有對子的牌,按構成該對子的牌的值進行從大到小地排序。如果這些都相同,則按手牌中余下3張牌的值的和進行從大到小排序。
兩對:手中擁有兩對不同的對子。對於都包含兩對的手牌,按其最高對子的值進行從大到小排序。如果最高對子相同,則按另一個對子的值從大到小地進行排序。如果這些值相同,則按剩余牌的值從大到小地進行排序。
三條:手中擁有3張相同值的牌。對於都包含三條的手牌按構成三條的牌的值進行從大到小地排序。如果這些值相同,則按剩余牌的值從大到小地進行排序。
滿堂紅:手中擁有一個三條和一個對子。同理,先按三條大小排序,如果三條大小相同,則按對子大小進行排序。
四條:手中擁有4張相同值的牌。對於都包含四條的手牌按構成四條的牌的值進行從大到小地排序。如果這些值相同,則按剩余牌的值從大到小地進行排序。
順子:手中擁有5張連續值的卡。對於都包含順子的手牌按順子最大的牌進行排序。
皇家同花順:手中擁有10到A(10、J、Q、K、A)。是最大的手牌!

現在,阿誇已經知道了每個人的手牌,她想要知道所有人的排名列表。如果玩家的手牌大小相等,則按玩家名字的字典序輸出。保證沒有重復的名字。你能幫幫她嗎?
輸入格式:
第一行包含一個正整數 N (1<=N<=100000) ,表示玩家的人數。
接下來 N 行,每行包含兩個字符串:m (1<=|m|<=10 ) ,表示玩家的名字;s (1<=|s|<=10),表示玩家的手牌。
輸出格式:
輸出 N個玩家的排名列表。

輸入樣例:
3
Alice AAA109
Bob 678910
Boa 678910
輸出樣例:
Boa
Bob
Alice

思路:

一開始我是將牌型通過等級,數值,名字字典序來進行逐級排序,但這樣會使代碼冗長而繁瑣,不易檢查還會導致代碼運行時間超出。而后通過查閱資料和詢問轉換了一下思路,就是將牌型分別轉化為數字,再通過qsort函數對於數字大小進行比較。

牌型轉換
for(i=0;i<N;i++)
		{
			n=strlen(p[i].s);
			for(j=0;j<n;j++)
				{
					if(p[i].s[j]=='1'){//遇到1時肯定是數值為10的牌
						for(r=j+1;r<n-1;r++)
							{
								p[i].s[r]=p[i].s[r+1];//將之后的牌都往前進一位
							}
							p[i].s[n-1]='\0';
							p[i].s[j]=10;
					}
					else if(p[i].s[j]=='J')p[i].s[j]=11;
					else if(p[i].s[j]=='Q')p[i].s[j]=12;
					else if(p[i].s[j]=='K')p[i].s[j]=13;
					else if(p[i].s[j]=='A')p[i].s[j]=1;
					else if(p[i].s[j]=='2')p[i].s[j]=2;
					else if(p[i].s[j]=='3')p[i].s[j]=3;
					else if(p[i].s[j]=='4')p[i].s[j]=4;
					else if(p[i].s[j]=='5')p[i].s[j]=5;
					else if(p[i].s[j]=='6')p[i].s[j]=6;
					else if(p[i].s[j]=='7')p[i].s[j]=7;
					else if(p[i].s[j]=='8')p[i].s[j]=8;
					else if(p[i].s[j]=='9')p[i].s[j]=9;}

一開始是直接將2看作字符‘2’,它的ASCII碼值為50,再將其它數字以大小范圍使之分布在50左右的地方,例如牌A就使它為49,但這樣數值太大,到后面會不方便自己檢查錯誤,於是直接將牌值轉換為1、2、3等等。為了方便牌型判斷,我對五張牌進行了非降序的排序:

for(j=0;j<4;j++)
				{
					for(r=0;r<4-j;r++)
						{
							if(p[i].s[r]<p[i].s[r+1]){
								t=p[i].s[r];
								p[i].s[r]=p[i].s[r+1];
								p[i].s[r+1]=t;
							}//對牌進行非降序排序 (冒泡排序法)
						}
				}
牌型判斷
if(p[i].s[0]==p[i].s[4]){
				p[i].b-=p[i].s[2]*4;//除去四條的牌數
				p[i].a=60+p[i].s[2]*0.01+p[i].b*0.0001; //將判斷標准分級乘以小數方便比較,我將每個小等級以0.01的數量級來分開,以0.1來分應該也是可以的
				continue; 
			}//這是五張牌都相等的情況,判斷為四條
		   else if(p[i].s[0]==p[i].s[3]||p[i].s[1]==p[i].s[4]){
				p[i].b-=p[i].s[2]*4;
				p[i].a=60+p[i].s[2]*0.01+p[i].b*0.0001; 
				continue; 
			} //判斷四條
		   else if(p[i].s[1]==p[i].s[3]){
				p[i].b-=p[i].s[2]*3;
				p[i].a=40+p[i].s[2]*0.01+p[i].b*0.0001;
				continue;
			}//三條 
			else if(p[i].s[0]==p[i].s[2]){
				if(p[i].s[3]==p[i].s[4]){
					p[i].a=50+p[i].s[0]*0.01+p[i].s[3]*0.0001;
					continue;
				}//滿堂紅
				else{
					p[i].b-=p[i].s[0]*3;
					p[i].a=40+p[i].s[0]*0.01+p[i].b*0.0001;
					continue;
				}//三條
			}
			else if(p[i].s[2]==p[i].s[4]){
				if(p[i].s[0]==p[i].s[1]){
					p[i].a=50+p[i].s[2]*0.01+p[i].s[0]*0.0001;
					continue;
				}//滿堂紅
				else{
					p[i].b-=p[i].s[2]*3;
					p[i].a=40+p[i].s[2]*0.01+p[i].b*0.0001;
					continue;
				}//三條
			}
			else if(p[i].s[0]==p[i].s[1]){
				if(p[i].s[2]==p[i].s[3]||p[i].s[3]==p[i].s[4]){
					p[i].b=p[i].b-p[i].s[0]*2-p[i].s[3]*2;
					p[i].a=30+p[i].s[0]*0.01+p[i].s[3]*0.0001+p[i].b*0.000001;
					continue;
				}//兩對
				else{
					p[i].b-=p[i].s[0]*2;
					p[i].a=20+p[i].s[0]*0.01+p[i].b*0.0001;
					continue;
				}//一對
			}
			else if(p[i].s[1]==p[i].s[2]){
				if(p[i].s[3]==p[i].s[4]){
					p[i].a=30+p[i].s[1]*0.01+p[i].s[3]*0.0001+p[i].s[0]*0.000001;
					continue;
				}//兩對
				else{
					p[i].b-=p[i].s[1]*2;
					p[i].a=20+p[i].s[1]*0.01+p[i].b*0.0001;
					continue;
				}//一對
			}
			else if(p[i].s[2]==p[i].s[3]||p[i].s[3]==p[i].s[4]){
				p[i].b-=p[i].s[3]*2;
				p[i].a=20+p[i].s[3]*0.01+p[i].b*0.0001;
				continue;
			}//一對
			for(j=0;j<4;j++)
				{
					if(p[i].s[j]-p[i].s[j+1]!=1)break;
				}//判斷順子和同花順
			if(j==4){
				p[i].a=70+p[i].s[0]*0.01;
				continue;
			}//順子
			else if(j==3&&p[i].s[4]==1&&p[i].s[0]==13){
				p[i].a=80;
				continue;
			}//同花順
			p[i].a=10+p[i].b*0.1;//高牌
			
		 } 

這次遇到的問題歸根結底還是cmp的編寫,這讓我一直只過了兩個點(郁悶)

//錯誤代碼
int cmp(const void *p1,const void *p2)
{
	struct pai *c=(struct pai*)p1;
	struct pai *d=(struct pai*)p2;
	if(c->a!=d->a)return c->a<d->a?1:-1;
	else return c->name>c->name?1:-1;
//正確代碼
int cmp(const void *p1,const void *p2)
{
	struct pai *c=(struct pai*)p1;
	struct pai *d=(struct pai*)p2;
	if(c->a!=d->a)return c->a<d->a?1:-1;
	else {
		if(strcmp(c->name,d->name)>0)return 1;//用字符串函數來判斷名字字典序
		else return -1;
	}
}

不知道錯誤代碼的錯誤究竟在哪,但正確代碼比較好理解又不容易出錯吧,希望知道我為什么錯的能幫助指出哦
以下附上完整代碼

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct pai{
	char name[10];
	char s[10];
	double a;
	int b;
}p[100005];
int main()
{
	int cmp(const void *p1,const void *p2);
	int N,i,j,r,n,x;
	char t;
	scanf("%d",&N);
	for(i=0;i<N;i++)
		{
			scanf("%s %s",p[i].name,p[i].s);
			
		}
	for(i=0;i<N;i++)
		{
			n=strlen(p[i].s);
			for(j=0;j<n;j++)
				{
					if(p[i].s[j]=='1'){
						for(r=j+1;r<n-1;r++)
							{
								p[i].s[r]=p[i].s[r+1];
							}
							p[i].s[n-1]='\0';
							p[i].s[j]=10;
					}
					else if(p[i].s[j]=='J')p[i].s[j]=11;
					else if(p[i].s[j]=='Q')p[i].s[j]=12;
					else if(p[i].s[j]=='K')p[i].s[j]=13;
					else if(p[i].s[j]=='A')p[i].s[j]=1;
					else if(p[i].s[j]=='2')p[i].s[j]=2;
					else if(p[i].s[j]=='3')p[i].s[j]=3;
					else if(p[i].s[j]=='4')p[i].s[j]=4;
					else if(p[i].s[j]=='5')p[i].s[j]=5;
					else if(p[i].s[j]=='6')p[i].s[j]=6;
					else if(p[i].s[j]=='7')p[i].s[j]=7;
					else if(p[i].s[j]=='8')p[i].s[j]=8;
					else if(p[i].s[j]=='9')p[i].s[j]=9;}
					p[i].b=0;
			
			for(j=0;j<5;j++){
				x=p[i].s[j];
			
				p[i].b+=x;
			
			}	
		
			
			for(j=0;j<4;j++)
				{
					for(r=0;r<4-j;r++)
						{
							if(p[i].s[r]<p[i].s[r+1]){
								t=p[i].s[r];
								p[i].s[r]=p[i].s[r+1];
								p[i].s[r+1]=t;
							}//對牌進行非降序排序 
						}
				}
			
			if(p[i].s[0]==p[i].s[4]){
				p[i].b-=p[i].s[2]*4;//不是四條的牌數 
				p[i].a=60+p[i].s[2]*0.01+p[i].b*0.0001; 
				continue; 
			}
		   else if(p[i].s[0]==p[i].s[3]||p[i].s[1]==p[i].s[4]){
				p[i].b-=p[i].s[2]*4;//不是四條的牌數 
				p[i].a=60+p[i].s[2]*0.01+p[i].b*0.0001; 
				continue; 
			} 
		   else if(p[i].s[1]==p[i].s[3]){
				p[i].b-=p[i].s[2]*3;
				p[i].a=40+p[i].s[2]*0.01+p[i].b*0.0001;
				continue;
			}//三條 
			else if(p[i].s[0]==p[i].s[2]){
				if(p[i].s[3]==p[i].s[4]){
					p[i].a=50+p[i].s[0]*0.01+p[i].s[3]*0.0001;
					continue;
				}
				else{
					p[i].b-=p[i].s[0]*3;
					p[i].a=40+p[i].s[0]*0.01+p[i].b*0.0001;
					continue;
				}
			}
			else if(p[i].s[2]==p[i].s[4]){
				if(p[i].s[0]==p[i].s[1]){
					p[i].a=50+p[i].s[2]*0.01+p[i].s[0]*0.0001;
					continue;
				}
				else{
					p[i].b-=p[i].s[2]*3;
					p[i].a=40+p[i].s[2]*0.01+p[i].b*0.0001;
					continue;
				}
			}
			else if(p[i].s[0]==p[i].s[1]){
				if(p[i].s[2]==p[i].s[3]||p[i].s[3]==p[i].s[4]){
					p[i].b=p[i].b-p[i].s[0]*2-p[i].s[3]*2;
					p[i].a=30+p[i].s[0]*0.01+p[i].s[3]*0.0001+p[i].b*0.000001;
					continue;
				}
				else{
					p[i].b-=p[i].s[0]*2;
					p[i].a=20+p[i].s[0]*0.01+p[i].b*0.0001;
					continue;
				}
			}
			else if(p[i].s[1]==p[i].s[2]){
				if(p[i].s[3]==p[i].s[4]){
					p[i].a=30+p[i].s[1]*0.01+p[i].s[3]*0.0001+p[i].s[0]*0.000001;
					continue;
				}
				else{
					p[i].b-=p[i].s[1]*2;
					p[i].a=20+p[i].s[1]*0.01+p[i].b*0.0001;
					continue;
				}
			}
			else if(p[i].s[2]==p[i].s[3]||p[i].s[3]==p[i].s[4]){
				p[i].b-=p[i].s[3]*2;
				p[i].a=20+p[i].s[3]*0.01+p[i].b*0.0001;
				continue;
			}
			for(j=0;j<4;j++)
				{
					if(p[i].s[j]-p[i].s[j+1]!=1)break;
				}
			if(j==4){
				p[i].a=70+p[i].s[0]*0.01;
				continue;
			}
			else if(j==3&&p[i].s[4]==1&&p[i].s[0]==13){
				p[i].a=80;
				continue;
			}
			p[i].a=10+p[i].b*0.1;
			
		 } 
	
	qsort(p,N,sizeof(struct pai),cmp);

	for(i=0;i<N;i++)
		{
			printf("%s\n",p[i].name);
		}
	return 0;
}
int cmp(const void *p1,const void *p2)
{
	struct pai *c=(struct pai*)p1;
	struct pai *d=(struct pai*)p2;
	if(c->a!=d->a)return c->a<d->a?1:-1;
	else {
		if(strcmp(c->name,d->name)>0)return 1;
		else return -1;
	}
}

寫此題解為了紀念我被這道題折磨的這幾天(土撥鼠尖叫)啊啊啊啊啊啊啊啊


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM