C語言實(shí)現(xiàn)斗地主的核心算法
數(shù)據(jù)結(jié)構(gòu)只選擇了順序表,沒有選擇鏈表,靈活性和抽象性不足,不能普適。
head.h
#ifndef __HEAD_H__ #define __HEAD_H__ #define MAXLEVEL 15 typedef struct CARD{ int number; int level; char *flower; char point; }card;//卡 typedef struct DECK{ int top; int arr[55]; }deck;//牌堆 typedef struct PLAYERS{ int id; int status; card handcard[21]; int size; }players;//玩家 typedef struct GAMES{ int type; int level; int sum; int who; int count; int arr[16]; }games;//桌面 typedef struct BUFFERS{ int arr[16]; int brr[20]; int sum; }buffers;//出牌緩沖區(qū) /*--------------------------------*/ void game_init(); void turning(); void handcard_sort(); void print(); int win(); void turn_switch(); #endif
op.c
#include<stdio.h> #include<stdlib.h> #include"head.h" #include<string.h> static int type_buffer(); static char point[]={'0','3','4','5','6','7','8','9','X','J','Q','K','A','2','w','W'}; static char *farr[]={"方片","梅花","紅桃","黑桃"}; static char* type_arr[]={"棄權(quán)","單張","對(duì)子","王炸","骷髏","骷髏單","炸彈","骷髏對(duì)","炸帶單","順子","炸帶一對(duì)","飛機(jī)不帶","連對(duì)","飛機(jī)單","飛機(jī)帶對(duì)"}; static char* sta_arr[2]={"農(nóng)民","地主"}; static players player[3];//玩家 static games game; /*洗牌堆*/ static deck* deck_init(){ int i,j; srand(time(0)); deck *p_deck=(deck*)malloc(sizeof(deck)); if(!p_deck){ printf("分配內(nèi)存失敗\n"); return NULL; } for(i=1;i<=54;i++){ p_deck->arr[i]=rand()%54; for(j=1;j<i;j++){ if(p_deck->arr[i]==p_deck->arr[j]){ i--; break; } } } p_deck->top=54; return p_deck; } /*初始化玩家(洗牌,id,身份 手牌,總數(shù))*/ static void player_init(){ int i,j; for(j=0;j<3;j++){ for(i=1;i<=20;i++){ player[j].handcard[i].number=100; player[j].handcard[i].level =0; } } deck *p=deck_init(); if(!p){ printf("沒有牌堆\n"); return ; } int which=0; which=rand()%3; game.who=which; for(i=0;i<3;i++){ player[i].id=i; if(i==which){//地主 player[i].status=1; for(j=1;j<=20;j++){ player[i].handcard[j].number=p->arr[(p->top)--]; } player[i].size=20; } else{//農(nóng)民 player[i].status=0; for(j=1;j<=17;j++){ player[i].handcard[j].number=p->arr[(p->top)--]; } player[i].size=17; } } free(p); p=NULL; } /*手牌信息補(bǔ)完*/ static void handcard_init(){ int i,j; for(i=0;i<3;i++){ for(j=1;j<=20;j++){ int number=player[i].handcard[j].number; int *p_level=&(player[i].handcard[j].level); char **pp_flower=&(player[i].handcard[j].flower); char *p_point=&(player[i].handcard[j].point); if(number>=0&&number<=51){ *p_level=number/4+1; *p_point=point[number/4+1]; *pp_flower=farr[number%4]; } else if(number==52){ *p_level=14; *p_point='w'; *pp_flower="小王"; } else if(number==53){ *p_level=15; *p_point='W'; *pp_flower="大王"; } else { *p_level=0; *p_point=' '; *pp_flower=" "; } } } } /*打印當(dāng)前玩家手牌*/ void print(){ int i,j; for(i=0;i<3;i++){ if (i!=game.who) continue; for(j=1;j<=player[i].size;j++){ //printf("======"); if(player[i].handcard[j].number == 100){ printf(" "); } else { char *p_tmp=player[i].handcard[j].flower; printf("%s ",p_tmp); } } printf("\n"); for(j=1;j<=player[i].size;j++){ if(player[i].handcard[j].number == 100){ printf(" "); } else { printf(" %c ",player[i].handcard[j].point); } } } printf("\n"); for(j=1;j<=player[game.who].size;j++){ if(! (j>9)) printf("(%d) ",j); else printf("(%d) ",j); } printf("\n"); } /*游戲初始化*/ void game_init(){ game.count=2;//棄權(quán)次數(shù) player_init();//洗牌 發(fā)牌 handcard_init();//手牌信息補(bǔ)完 } int fcmp(const void *pa,const void *pb){//升序 return *(int*)pa-*(int*)pb; } static void rehandcard_sort(players *p_player,int* p_number){//真正的排序函數(shù) int *base=p_number; size_t nmemb=p_player->size; size_t size= sizeof(card); qsort(base,20,size,fcmp); } void handcard_sort(){//外殼排序函數(shù) rehandcard_sort(&player[0],&(player->handcard[1].number)); rehandcard_sort(&player[1],&((player+1)->handcard[1].number)); rehandcard_sort(&player[2],&((player+2)->handcard[1].number)); } /*詢問是否出牌*/ static int require(){ //1表示出牌 0表示棄權(quán) if(game.type == 3 ){ if(game.count != 2){ printf("要不起!\n"); return 0; } else return 1; } if(game.count !=2){ printf("出牌嗎?(y表示出牌,n棄權(quán)):"); char choice; scanf("%c",&choice); scanf("%*[^\n]"); scanf("%*c"); if(choice == 'n' || choice == 'N'){ return 0; } else return 1; } else { printf("繼續(xù)出牌\n"); return 1; } } buffers buffer={};//出牌緩沖區(qū) /*清空出牌緩沖區(qū)*/ static void reset(){ int a; for(a=0;a<16;a++) buffer.arr[a]=0; for(a=0;a<20;a++) buffer.brr[a]=0; buffer.sum=0; } /*放牌進(jìn)入緩沖區(qū)*/ static void buffer_put(){ char intput[40]={};//把字符串轉(zhuǎn)換為數(shù)字 int brr[20]={}; int i=0; int j; int sum; int flag=0; while(1){ reset(); sig: printf("請(qǐng)輸入要放的牌...:"); fgets(intput,40,stdin); if(strlen(intput)==39&&intput[38]!='\n'){ scanf("%*[^\n]"); scanf("%*c"); } for(j=0,i=0,sum=0;i<strlen(intput);i++){//記錄出牌下標(biāo) if(intput[i]>='0'&&intput[i]<='9'){ sum=sum*10+(intput[i]-'0'); flag=1; } else { if(flag) brr[j] = sum; sum=0; j++; flag=0; } } int k; printf("要出: "); for(k=0;brr[k];k++) printf("%d ",brr[k]); printf("號(hào)牌\n"); int who = game.who; players* p_player=&(player[who]); int index; for(i=0;brr[i];i++){//記錄出的牌是什么 index=brr[i]; if(index>(p_player->size) || index<=0 ){//輸入的字符串范圍有誤 printf("輸入內(nèi)容超出范圍,重新輸入\n"); goto sig; } else{ int level=p_player->handcard[index].level; ++(buffer.arr[level]); buffer.brr[i] =brr[i]; } } for(i=1;i<=15;i++)//記錄出了多少張牌 buffer.sum+=buffer.arr[i]; char aff= 'N'; int type = type_buffer(); if(type != -1) printf("要出的類型是:%s\n\n",type_arr[type]); else { printf("不存在此類型的牌\n\n"); reset(); return; } printf("確定要這樣出嗎?(確定輸入y,否則按其它)"); scanf("%c",&aff); scanf("%*[^\n]"); scanf("%*c"); if(aff == 'y' || aff =='Y') break; } } static void turnstart(){ char u; printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n==============================================================斗地主======================================================\n\n\n\n\n"); printf("輪到下一家"); scanf("%c",&u); int i; printf("\n\n\n\n\n\n\n牌面張數(shù)為%d張\n",game.sum); printf("牌面類型為: %s%c\n",type_arr[game.type],point[game.level]); printf("=============================================================%s的回合==========================================================\n\n",sta_arr[player[game.who].status]); printf("現(xiàn)在輪到玩家%d",game.who+1); printf(" 玩家1(%s)手牌%d ",sta_arr[player[0].status],player[0].size);if(game.who==0) printf("<=====\n");else printf("\n"); printf(" 玩家2(%s)手牌%d ",sta_arr[player[1].status],player[1].size);if(game.who == 1) printf("<=====\n"); else printf("\n"); printf(" 玩家3(%s)手牌%d ",sta_arr[player[2].status],player[2].size);if(game.who == 2) printf("<=====\n"); else printf("\n"); } /*判斷是否連續(xù)*/ static int continuum(int num,int total){ int i,count=0; int flag=0;//有值則標(biāo)記為1 int sig=0;//從 有到無 改標(biāo)記為1 for(i=1;i<=15;i++){ if(buffer.arr[i]==num){ if(sig) return 0;//非連續(xù) count++; if(count==total) return 1;//連續(xù) flag=1; }else { if (flag) sig=1; } } } /*獲取緩沖區(qū)牌類類型*/ static int type_buffer(){ int i, one=0,pair=0,triple=0,quattuor=0,zero=0; for(i=1;i<=15;i++){//統(tǒng)計(jì)單張,對(duì)子,三同,四同各有多少 if(buffer.arr[i] == 1) one++; else if(buffer.arr[i] == 2) pair ++; else if(buffer.arr[i] == 3) triple ++; else if(buffer.arr[i] == 4) quattuor ++; else zero++; } //printf("單%d 對(duì)%d 三%d 四%d 零%d,sum%d===\n",one,pair,triple,quattuor,zero,buffer.sum); if(!(buffer.sum)){ return -1;//非法 } else if(buffer.sum<=5){//1~5 if(one == 1 && !pair && !triple && !quattuor)//單張 return 1; else if(pair == 1 && !one && !triple && !quattuor)//對(duì)子 return 2; else if(one == 2 &&buffer.arr[14]&&buffer.arr[15])//王炸 return 3; else if(triple == 1 && !one && !pair && !quattuor) //骷髏 return 4; else if(one ==1 && !pair && triple == 1 && !quattuor )//骷髏單 return 5; else if(!one && !pair && !triple && quattuor == 1)//炸 return 6; else if(!one && pair == 1 && triple == 1 && !quattuor)//骷髏對(duì) return 7; else if(one == 1 && !pair && !triple && !quattuor){//炸帶單 return 8; } else if(!pair && !triple && !quattuor && (!buffer.arr[14] && !buffer.arr[15])&& buffer.sum == 5){//順子 if( continuum(1,one))//所有1連續(xù) return 9; else { return -1; } } else return -1; } else if(buffer.sum>=6){ if((!one) && (pair == 1) && (!triple) && (quattuor == 1) )//炸帶對(duì) return 10; else if(!one && !pair && !quattuor){//只有2個(gè)以上個(gè)三張相同 飛機(jī)不帶 if(continuum(3,triple))//所有3連續(xù) return 11; else return -1; } else if(!one && !triple && !quattuor){//連對(duì) if(continuum(2,pair)) return 12; else return -1; } else if(buffer.sum == 4*triple){//飛機(jī)單 if(continuum(3,triple)) return 13; else return -1; } else if((buffer.sum == 5*triple) && (triple == pair)){//飛機(jī)對(duì) if(continuum(3,triple)) return 14; else return -1; } else if(!pair && !triple && !quattuor &&(!buffer.arr[14] && !buffer.arr[15])){ if(continuum(1,one)) return 9; else return -1; } else return -1; } } /*最大下標(biāo)*/ static int maxindex(int count){ int i; for (i=15;i>=1;i--){ if(buffer.arr[i] == count) return i; } } /*獲取緩沖區(qū)牌類等級(jí)*/ static int level_buffer(int type){ switch(type){ case 1: return maxindex(1); break; case 2: return maxindex(2); break; case 3: return 15; break; case 4: return maxindex(3); break; case 5: return maxindex(3); break; case 6: return maxindex(4); break; case 7: return maxindex(3); break; case 8: return maxindex(4); break; case 9: return maxindex(1); break; case 10: return maxindex(4); break; case 11: return maxindex(3); break; case 12: return maxindex(2); break; case 13: return maxindex(3); break; case 14: return maxindex(3); break; } } /*消減手牌*/ static void annealation(){ int i=1; int j=0; int who=game.who; for(i = 1,j=0;buffer.brr[j];i++,j++){ int index = buffer.brr[j]; player[who].handcard[index].number = 100; player[who].size = player[who].size - 1; } game.sum=buffer.sum; game.count=0; handcard_sort(); //printf("出牌成功\n"); } /*回合進(jìn)行中*/ //這個(gè)模塊有很大的修改空間 例如return 改為break... void turning(){ turnstart(); /* 開始階段 */ handcard_sort(); print(); int level= 0; while(1){ if(!require()){ printf("\n\n\n\n\n\n\n\n不要\n"); game.count++; if(game.count == 2){ game.type=0; game.level=0; game.sum=0; } return ; /* 開始階段 */ } buffer_put(); /* 出牌階段在這函數(shù)判斷是否棄權(quán)比較好 */ int type = type_buffer(); int level=level_buffer(type); if(type == -1){ printf("牌類非法!-----\n"); continue; } if(type == 3){//王炸 printf("\n\n\n\n\n王炸!!\n"); annealation(); game.type=3; game.level=MAXLEVEL; return ; } else if(type == 6){//炸彈 if(game.type != 6){ printf("\n\n\n\n炸彈\n"); annealation(); game.type = 6; game.level = level_buffer(type); return; } else { if(level > game.level){ printf("\n\n\n\n\n壓死\n"); annealation();//消減手牌 game.type = 6; game.level = level; return; } else if(level < game.level||level == game.level){ printf("牌的等級(jí)不夠大\n"); continue; } } } else if(game.count == 2 ){//兩家棄權(quán) annealation(); game.type = type; game.level = level; return ; } else {//除了炸彈 兩家棄權(quán) 王炸 非法 以外的合理牌類 if(type != game.type){ //不對(duì)應(yīng) printf("類型不對(duì)應(yīng)\n"); continue; } else { //對(duì)應(yīng) if(buffer.sum != game.sum){ printf("數(shù)量不對(duì)應(yīng)\n"); continue; } if(level < game.level|| level==game.level){ printf("牌的等級(jí)不夠大\n"); continue; } else if(level > game.level){ printf("\n\n\n\n\n壓死\n"); annealation(); game.type = type; game.level = level; return ; } } } } } /*0 1 2 3判斷是否是誰勝利 0表示沒有 1表示玩家一*/ int win(){ int now = game.who; if(!player[now].size) return now; else return 0; } /*切換當(dāng)前玩家為下家*/ void turn_switch(){ int who = game.who; who++; game.who = who%3; }
main.c
#include<stdio.h> #include"head.h" int main(){ while(1){ int which; game_init();//初始化游戲 while(1){ turning();//回合進(jìn)行中 printf("\n\n\n"); if(which=win())//是否產(chǎn)生勝者 break; turn_switch();//切換出牌方 } printf("勝負(fù)已出!勝利者是玩家%d\n",which+1); printf("是否重新游戲?(y為繼續(xù),其它退出程序):"); char choice; scanf("%c",&choice); scanf("%*[^\n]"); scanf("%*c"); if(choice == 'y'||choice =='Y') continue; break; } printf("謝謝試玩\n"); }
以上所述就是本文的全部內(nèi)容了,希望對(duì)大家熟練應(yīng)用C語言能夠有所幫助。
- 基于C語言實(shí)現(xiàn)的迷宮算法示例
- C語言使用深度優(yōu)先搜索算法解決迷宮問題(堆棧)
- C語言使用廣度優(yōu)先搜索算法解決迷宮問題(隊(duì)列)
- C語言數(shù)據(jù)結(jié)構(gòu)算法之實(shí)現(xiàn)快速傅立葉變換
- C語言實(shí)現(xiàn)二叉樹的搜索及相關(guān)算法示例
- 基于C語言實(shí)現(xiàn)的aes256加密算法示例
- C語言實(shí)現(xiàn)的猴子分桃問題算法解決方案
- C語言實(shí)現(xiàn)的猴子吃桃問題算法解決方案
- C語言經(jīng)典算法例題求100-999之間的“水仙花數(shù)”
- C語言實(shí)現(xiàn)魔方陣算法(幻方陣 奇魔方 單偶魔方實(shí)現(xiàn))
- 詳解約瑟夫環(huán)問題及其相關(guān)的C語言算法實(shí)現(xiàn)
- C語言實(shí)現(xiàn)運(yùn)籌學(xué)中的馬氏決策算法實(shí)例
相關(guān)文章
VSCODE+cmake配置C++開發(fā)環(huán)境的實(shí)現(xiàn)步驟
這篇文章主要介紹了VSCODE+cmake配置C++開發(fā)環(huán)境的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03詳解C語言中sizeof如何在自定義函數(shù)中正常工作
在main函數(shù)中,sizeof是可以正常工作的,但是在自定義函數(shù)中就不可以了。所以本文將為大家詳細(xì)講解一下如何解決這一問題,感興趣的可以了解一下2022-05-05對(duì)比C語言中memccpy()函數(shù)和memcpy()函數(shù)的用法
這篇文章主要介紹了對(duì)比C語言中memccpy()函數(shù)和memcpy()函數(shù)的用法,二者都是用于復(fù)制內(nèi)存內(nèi)容,注意區(qū)別,需要的朋友可以參考下2015-08-08C++中靜態(tài)成員函數(shù)與靜態(tài)成員變量(static )
這篇文章主要介紹了C++中靜態(tài)成員函數(shù)與靜態(tài)成員變量(static )的相關(guān)資料,需要的朋友可以參考下2017-06-06北郵計(jì)算機(jī)考研復(fù)試題的C語言解答精選
這篇文章主要介紹了北郵計(jì)算機(jī)考研復(fù)試題目的C語言解答精選,選自2012年的一些基礎(chǔ)的上機(jī)題目,需要的朋友可以參考下2015-08-08一篇文章帶你了解C++(STL基礎(chǔ)、Vector)
這篇文章主要為大家詳細(xì)介紹了C++ STL基礎(chǔ),vector向量容器使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助2021-08-08C語言實(shí)現(xiàn)大數(shù)據(jù)文件的內(nèi)存映射機(jī)制
這篇文章主要介紹了C語言實(shí)現(xiàn)大數(shù)據(jù)文件的內(nèi)存映射機(jī)制的相關(guān)資料,需要的朋友可以參考下2017-01-01