日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Poker time 2 (enhanced version)

發布時間:2024/1/8 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Poker time 2 (enhanced version) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

聲明:

????????本文很長,并且最終不會有完整代碼,僅提供算法;

????????本文知識點中等偏難,但是看懂和學會之后有一定好處;

????????本文絕對不是最優解,并且很多步驟待封裝成函數,這里逐一分析;

????????本文純屬個人刷題方法和總結,如有錯誤,歡迎指正;

? ? ? ? 如果你做的時候有些吃力,真正想學點什么,請耐心看完,看懂。

題目如下:

????????背景:兩個人每人發3張牌(各從一副牌中),每張牌包括花色(紅桃(Heart)>黑桃(Spade)>方塊(Diamond)>梅花(Club))和大小(從小到大依次是:2-10、J、Q、K、A),勝負規則如下:同花順(3張同花色的連牌,先比大小,再比花色后同)>炸彈(3張相同大小的牌)>連牌(3張不同花色的連牌)>對子(兩張相同大小的牌)>單牌。例如,紅桃QKA>黑桃QKA>梅花567>方塊234>AAA(紅桃、方塊、梅花)>AAA(黑桃、方塊、梅花)>JQK(紅桃、紅桃、方塊)>JQK(黑桃、紅桃、方塊)>AA2(梅花黑桃梅花)>QQJ(紅桃梅花方塊)>JQA(紅桃紅桃紅桃)。注:A23不算連牌。

輸入:A的3張牌(未排序)和B的3張牌(未排序)。

輸出:A的3張牌的排序后的輸出和B的3張牌的排序后的輸出,以及A和B誰獲勝。

分析:

? ? ? ? 這里繼承了上一題,也就是Poker time的部分內容,這里不多贅述那題的做法,如果有需要的話可以私聊我,我視情況出第一題的算法。

? ? ? ? 首先是排序,這里的最終排序取決于取決于牌的大小而不是花色(*);其次是勝利條件的判斷,有明顯的分級,對于每一級內部也有嚴格的先大小后花色的判斷順序(**);再者,順子的QKA是否合理,這里沒有給出解釋,也是留了一手,不然題目的判斷會更惡心(***);最后是讓人最頭疼的10,這個數字在第一題就作為最后一個隱藏示例存雷。

? ? ? ? 不過有10必有‘1’,只需要找到這個1就行。

? ? ? ? 這次編寫,我不知道隱藏示例都是什么,主要是我一次就過了,除了一個本身就是錯誤的示例(凡爾賽)。

算法正文:

零、參數聲明

? ? ? ? 這里給出本文主要的參數

char a[20]; // 這里給20,防一下 10 的炸彈char b[20];gets(a);gets(b);int i=0;int j=0;int flag=1; // 循環進行指標 int flag1=1; // 是否雙贏指標 int flag2=0; // 判斷 A 贏 int flag3=0; // 判斷 B 贏

一、建立在排序基礎上的整體數組構造以及參數讀入

? ? ? ? 由于最終需要對牌進行先大小后花色的排序,我這里使用的是二位數組

????????為什么定義成13*4呢?????????例如:HA 就在數組 [0][0]的位置

? ? ? ? 我的思路是:13行存儲牌,4列存儲花色,數字大、花色大的牌前,最后一次遍歷輸出牌序。

? ? ? ? 這里需要將flag的指標置零,如果直接 return 0 也可以。

int As[13][4]={0};int Bs[13][4]={0};

?????????于是,可以對數組內讀入參數,這里只給出其中一個字符串的數據讀入

while(a[i]!='\0'&&flag) // A 的數據填充 {if(a[i]==' ') // 跳過空格{i++;continue;}if(a[i]=='H'||a[i]=='S'||a[i]=='D'||a[i]=='C'){int m=0; // 列指標switch(a[i]) // 判斷花色{case 'H':m=0;break;case 'S':m=1;break;case 'D':m=2;break;case 'C':m=3;break;}int n=0; // 行指標//往后是 i+1 因為現在的 i 指向的是花色,往后以為才是牌的內容 // 向二維數組中填充數據 if(isdigit(a[i+1])||a[i+1]=='A'||a[i+1]=='J'||a[i+1]=='Q'||a[i+1]=='K') {if(isdigit(a[i+1])&&a[i+1]!='1') //判斷2~9,小的在下往上填{n=12-(a[i+1]-'0'-2); // 回憶一下 ascii碼 就知道這步在干啥}else if(a[i+1]=='A') // 其他牌的讀入{n=0; }else if(a[i+1]=='K'){n=1;}else if(a[i+1]=='Q'){n=2;}else if(a[i+1]=='J'){n=3;} if(a[i+1]=='1'&&a[i+2]!='\0'&&a[i+2]=='0') // 判斷是不是 10 {n=4;}i+=n==4?3:2; // 結合 i 的指向,如果不是10就跳過兩位,是10就跳過三位}else // 不符合的剔除 {printf("Input Error!\n");flag=0;flag1=0;break; }if(As[n][m]==0) // 如果沒有重復的牌,那就可以在數組中標記這張牌{As[n][m]++;}else // 否則報錯{printf("Input Error!\n");flag=0; flag1=0;break;}}else{printf("Input Error!\n");flag=0;flag1=0;break;}}

二、建立在先大小后花色基礎上的排序

? ? ? ? 是插入過程的逆,重新輸出符合要求的字符串

int k=0;for(i=0;i<13;i++){for(j=0;j<4;j++){if(As[i][j]==1) //判斷有沒有這張牌{switch (j) // 以下的選擇與剛才插入的時候剛好相反,屬于反操作{case 0:a[k++]='H';break;case 1:a[k++]='S';break;case 2:a[k++]='D';break;case 3:a[k++]='C';break;} switch (i){case 0:a[k++]='A';break; // 根據牌所在的行數回推牌的內容case 1:a[k++]='K';break;case 2:a[k++]='Q';break;case 3:a[k++]='J';break;case 4:a[k++]='1';a[k++]='0';break;default:a[k++]=14-i+'0'; // 2~9 轉回字符}a[k++]=' ';}elsecontinue;}}a[--k]='\0'; // 數組結尾,最好加上,免得訪問越界

三、建立在規則上的初判斷與初步輸贏判定

? ? ? ? 這里初判斷 a 和 b 的牌型,如果牌型不同,直接就可以輸出唯一勝者

????????這里粗返回的 0~4 可以初步判斷勝者,或者仍需比較

? ? ? ? 這里返回的0~4可不是亂來的,后面有用到

? ? ? ? 函數如下:

// 返回差,類似與冒泡排序,前一個與后一個比,根據差調整數組中元素的位置 // 打一下,試一試就會了,這個函數,很容易上手 int cmp(const void*e1,const void*e2) // 比較方式 {return *(int*)e1-*(int*)e2; }int search(int a[13][4]) // 初步判斷牌的類型 {int i=0;int j=0;int c[3]={0}; // 創建新的數組,存儲牌的 行指標 !!!int current=0; // 因為 行指標 標記了牌的大小for(i=0;i<13;i++) // 遍歷查找牌{for(j=0;j<4;j++){if(a[i][j]==1){// 同花順,占據連續的一列中的三個,最易判斷if(a[i+1][j]==1&&a[i+2][j]==1&&i<=10) // 這里i防止越界訪問{return 4;}c[current++]=i;}elsecontinue;}}qsort(c,3,sizeof(int),cmp); // 對牌進行排序,這里使用了 qsort 函數// qsort(數組名,元素個數,元素大小,比較函數)if(c[0]==c[1]&&c[1]==c[2]) // 炸彈(全部相等){return 3;}else if(c[2]-c[1]==1&&c[1]-c[0]==1) // 順子(等差數列){return 2;}else if(c[0]==c[1]||c[1]==c[2]) // 對子{return 1;}return 0; // 啥也不是,只有單牌 }

?

?判斷是否有勝者:

if((flag2>flag3||flag2<flag3)&&flag1) // 唯一勝者,且獲勝方式單純 {if(flag2>flag3){printf("Winner is A!\n");}else if(flag2<flag3){printf("Winner is B!\n");}printf("A: %s\n",a); // 打印排序后的牌內容printf("B: %s\n",b);}else if(flag2==flag3&&flag1) // 需要下一步比較

?

?四、建立在再次判斷上的函數指針數組及其調用

? ? ? ? 函數指針數組:一個數組(定語),數組內元素是函數指針(狀語)

? ? ? ? 故名思意:根據牌型,選擇不同的函數來判斷最終的勝利,也稱回調函數

int (*pfarr[4])(char c[15],char d[15])={nmsl,wdnm,cnmd,mdzz};// *pfarr[4] 指針數組,運算符優先級決定它先與 [4] 結合成為數組 // (char c[15],char d[15]),參數類型,類似于函數的參數聲明 // {nmsl,wdnm,cnmd,mdzz},函數名,我亂起的,沒別的意思// 總的意思就是,一個數組,里面四個元素,分別指向一個獨立的函數 else if(flag2==flag3&&flag1) // 需要下一步比較 {if(flag2) // 非零 {int (*pfarr[4])(char c[15],char d[15])={nmsl,wdnm,cnmd,mdzz};switch(flag2){case 4: // 這里的調用都是已經排序過的牌的字符串t=pfarr[0](a,b);break; // 函數調用類似于訪問數組的元素case 3: // 不過記得帶上函數的參數調用,就是后面的 (a,b)t=pfarr[1](a,b);break;case 2:t=pfarr[2](a,b);break;case 1:t=pfarr[3](a,b);break;}if(t==0){printf("Winner is A!\n"); }else if(t==1){printf("Winner is B!\n"); }else{printf("Draw!\n");}}else // 都是單牌,比較方法就是第一題的全部內容,不說了{int count=0;for(i=0;i<4&&flag;i++) // 對比兩個數組判斷輸贏 {for(j=0;j<13&&flag;j++){if((As[i][j]==0&&Bs[i][j]==0)){continue;}else if(As[i][j]==1&&Bs[i][j]==1){count++;if(count==3){printf("Draw!\n");goto end;}}else if(As[i][j]>Bs[i][j]){printf("Winner is A!\n");flag=0;break;}else if(As[i][j]<Bs[i][j]){printf("Winner is B!\n");flag=0;break;}}}}

五、建立在近似判斷機制上的四個函數

? ? ? ? 剛才我們設定了四個函數,分別是{nmsl,wdnm,cnmd,mdzz},現在需要一一實現他們,達到我們預期的不同情況下的比較效果。

// 同花順 判斷 int nmsl(char a[15],char b[15]) {int i=0;if(strlen(a)==8) // 判斷有沒有萬惡的 10,這里顯然沒有{for(i=0;i<15;i++){if(a[i]==b[i]) //相同跳過{continue;}else{if(a[i]=='H'&&b[i]!='H') // 花色碾壓{return 1;}else if(a[i]!='H'&&b[i]=='H'){return 0;}else if(a[i]=='A'&&b[i]!='A') // 謹記,有A就沒有10,這里是大小碾壓{return 0;}else if(a[i]!='A'&&b[i]=='A'){return 1;}else // 其他牌的大小碾壓{return b[i]-a[i]?1:0;}}}}else // 如果有萬惡的10{for(i=0;i<15;i++){if(a[i]==b[i]){continue;}else{if(a[i]=='H'&&b[i]!='H'){return 1;}else if(a[i]!='H'&&b[i]=='H'){return 0;}else if(a[i]=='1'||b[i]=='1') // 出現了 10 !{if(a[i]=='1'){return b[i]<=57?0:1; // 10 跟另外一張牌比較,這里57,代表字符'9'} // 細想一下,是不是也合理?else{return a[i]<=57?1:0;}}else // 其他牌的大小碾壓{return b[i]-a[i]?1:0;}}}}return 2; }

?

????????其余的判斷都是建立在剛才判斷的基礎上的,可以說比較部分幾乎完全一致。

? ? ? ? 這里多說一句,對子的判斷,可以先找到是哪一對,創建一個兩個元素的數組或者字符串,存下來這一個對子中的一張牌,然后跟另一個對子中的一張牌進行 皇城PK 即可。

? ? ? ? 這里不給出余下的三個函數了,有心的同學看懂上面的思路一定信手拈來,不就是三個函數嘛?!何況這里已經給出了最核心的比較算法了。

六、寫在最后的話

? ? ? ? 我不否認出這道題的人有很多沒有考慮到的地方,題目出的不是很嚴謹,但是在現有知識點的使用上,這絕對是綜合的難題(就我的算法而言)

? ? ? ? 如果你說你用一次遍歷,哈希遍歷,等等,那你可以完美的優化這道題的全部算法;

? ? ? ? 但是就我而言,我希望寫可讀性更高的代碼,不是說我不會寫高效代碼,hashmap我也可以寫,但是這只是獨善其身,不是每一個學C的人一開始就可以寫0ms,2Mb的代碼。

? ? ? ? 如果你覺得這很難,那很抱歉,我已經盡我的一切可能,寫最詳細的注釋,寫最簡單的代碼了,誰又能剛開始一看就懂呢?

? ? ? ? 如果你說,這博主怎么這么扣,這也不寫,那也不贅述。

????????不好意思,我都寫了,是時候舉一反三了。

????????

? ? ? ? 最后的最后,碼字不易,要是本文多少學了點東西的友友們,點個贊讓我看一下唄,至少我會覺得我的付出可以讓大家獲益

總結

以上是生活随笔為你收集整理的Poker time 2 (enhanced version)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 一级大片黄色 | 在线国产区 | 黄色a网站 | 亚洲美女视频在线 | 欧美激情18p | 精品久久久无码中文字幕边打电话 | 亚洲电影在线看 | 日韩黄色成人 | 婷婷亚洲综合五月天小说 | 久久精品色 | 亚洲经典一区二区 | 国产网红主播精品av | 青青草成人影视 | 亚洲午夜网站 | 成年人在线视频网站 | 四虎音影 | 亚洲欧美日韩高清 | 精品久久香蕉国产线看观看亚洲 | 国产精品毛片一区二区在线看 | 少女国产免费观看 | 亚洲欧美在线视频观看 | 大奶子在线观看 | 伊人久久中文 | 亚洲欧美中文字幕 | 天天爽视频| 秋霞午夜影院 | 欧美日韩精品一区二区三区视频播放 | 高清日韩一区二区 | 九一天堂 | 欧美一区二区视频在线观看 | 艳妇臀荡乳欲伦交换在线播放 | 亚洲中文无码久久 | 在线免费黄色网 | 人人妻人人澡人人爽国产一区 | 天天爽影院 | 成人一区二区三区四区 | 春色校园激情 | 91.xxx.高清在线 | 国产人妻久久精品一区二区三区 | 国产美女无遮挡免费 | 国产精品影片 | 色哟哟视频在线观看 | 四虎视频在线观看 | 免费裸体美女网站 | 久久久久国产精品 | 亚洲三级视频在线观看 | 国产在线观看一区二区三区 | 欧美一区二区最爽乱淫视频免费看 | av高清一区二区 | 国产探花一区 | 日批视屏| 13日本xxxxxⅹxxx20| 精品国产乱码久久久久久牛牛 | 人妻在卧室被老板疯狂进入 | jizz亚洲女人高潮大叫 | 奇米影视一区二区三区 | 最新日韩av在线 | 黄色调教视频 | www毛片com | 日本精品视频在线 | 木下凛凛子av一区二区三区 | 日韩高清不卡一区 | 三级黄片毛片 | 国产爽爽视频 | 视频在线a | 国产又粗又猛又黄视频 | 91视频国产一区 | 天堂8av| 色欲欲www成人网站 老色鬼av | 插综合 | 国产精品免费视频观看 | 中文字幕在线观看线人 | 超碰免费公开在线 | 一级片一级片 | 伊人365影院 | 男男一级淫片免费播放 | www色| 狠狠干影视 | 国产在线观看免费视频软件 | 免费色片 | 国产乱淫av麻豆国产免费 | 天天操天天干视频 | 国产熟女精品视频 | 私人av | 无码一区二区三区视频 | 久久久久久久人妻无码中文字幕爆 | 亚洲免费在线播放 | 欧美激情偷拍 | 午夜影片 | www国产com| 日韩精品一区二区三区视频 | 一级黄色大片免费观看 | 国产又粗又猛又黄又爽无遮挡 | 国产成人免费片在线观看 | 色版视频在线观看 | 福利二区三区 | 少妇又紧又色又爽又刺激视频 | 欧美日韩国产片 | 口爆吞精一区二区三区 |