德州撲克
最近,阿誇迷於德州撲克。所以她找到了很多人和她一起玩。由於人數眾多,阿誇必須更改游戲規則:
所有撲克牌均只看數字,不計花色。
每張卡的值為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;
}
}
寫此題解為了紀念我被這道題折磨的這幾天(土撥鼠尖叫)啊啊啊啊啊啊啊啊