C语言实现斗地主的核心算法
数据结构只选择了顺序表,没有选择链表,灵活性和抽象性不足,不能普适。
head.h
#ifndef__HEAD_H__ #define__HEAD_H__ #defineMAXLEVEL15 typedefstructCARD{ intnumber; intlevel; char*flower; charpoint; }card;//卡 typedefstructDECK{ inttop; intarr[55]; }deck;//牌堆 typedefstructPLAYERS{ intid; intstatus; cardhandcard[21]; intsize; }players;//玩家 typedefstructGAMES{ inttype; intlevel; intsum; intwho; intcount; intarr[16]; }games;//桌面 typedefstructBUFFERS{ intarr[16]; intbrr[20]; intsum; }buffers;//出牌缓冲区 /*--------------------------------*/ voidgame_init(); voidturning(); voidhandcard_sort(); voidprint(); intwin(); voidturn_switch(); #endif
op.c
#include<stdio.h> #include<stdlib.h> #include"head.h" #include<string.h> staticinttype_buffer(); staticcharpoint[]={'0','3','4','5','6','7','8','9','X','J','Q','K','A','2','w','W'}; staticchar*farr[]={"方片","梅花","红桃","黑桃"}; staticchar*type_arr[]={"弃权","单张","对子","王炸","骷髅","骷髅单","炸弹","骷髅对","炸带单","顺子","炸带一对","飞机不带","连对","飞机单","飞机带对"}; staticchar*sta_arr[2]={"农民","地主"}; staticplayersplayer[3];//玩家 staticgamesgame; /*洗牌堆*/ staticdeck*deck_init(){ inti,j; srand(time(0)); deck*p_deck=(deck*)malloc(sizeof(deck)); if(!p_deck){ printf("分配内存失败\n"); returnNULL; } 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; returnp_deck; } /*初始化玩家(洗牌,id,身份手牌,总数)*/ staticvoidplayer_init(){ inti,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; } intwhich=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{//农民 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; } /*手牌信息补完*/ staticvoidhandcard_init(){ inti,j; for(i=0;i<3;i++){ for(j=1;j<=20;j++){ intnumber=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]; } elseif(number==52){ *p_level=14; *p_point='w'; *pp_flower="小王"; } elseif(number==53){ *p_level=15; *p_point='W'; *pp_flower="大王"; } else{ *p_level=0; *p_point=''; *pp_flower=""; } } } } /*打印当前玩家手牌*/ voidprint(){ inti,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"); } /*游戏初始化*/ voidgame_init(){ game.count=2;//弃权次数 player_init();//洗牌发牌 handcard_init();//手牌信息补完 } intfcmp(constvoid*pa,constvoid*pb){//升序 return*(int*)pa-*(int*)pb; } staticvoidrehandcard_sort(players*p_player,int*p_number){//真正的排序函数 int*base=p_number; size_tnmemb=p_player->size; size_tsize=sizeof(card); qsort(base,20,size,fcmp); } voidhandcard_sort(){//外壳排序函数 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)); } /*询问是否出牌*/ staticintrequire(){//1表示出牌0表示弃权 if(game.type==3){ if(game.count!=2){ printf("要不起!\n"); return0; } else return1; } if(game.count!=2){ printf("出牌吗?(y表示出牌,n弃权):"); charchoice; scanf("%c",&choice); scanf("%*[^\n]"); scanf("%*c"); if(choice=='n'||choice=='N'){ return0; } elsereturn1; } else{ printf("继续出牌\n"); return1; } } buffersbuffer={};//出牌缓冲区 /*清空出牌缓冲区*/ staticvoidreset(){ inta; for(a=0;a<16;a++) buffer.arr[a]=0; for(a=0;a<20;a++) buffer.brr[a]=0; buffer.sum=0; } /*放牌进入缓冲区*/ staticvoidbuffer_put(){ charintput[40]={};//把字符串转换为数字 intbrr[20]={}; inti=0; intj; intsum; intflag=0; while(1){ reset(); sig:printf("请输入要放的牌...:"); 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++){//记录出牌下标 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; } } intk; printf("要出:"); for(k=0;brr[k];k++) printf("%d",brr[k]); printf("号牌\n"); intwho=game.who; players*p_player=&(player[who]); intindex; for(i=0;brr[i];i++){//记录出的牌是什么 index=brr[i]; if(index>(p_player->size)||index<=0){//输入的字符串范围有误 printf("输入内容超出范围,重新输入\n"); gotosig; } else{ intlevel=p_player->handcard[index].level; ++(buffer.arr[level]); buffer.brr[i]=brr[i]; } } for(i=1;i<=15;i++)//记录出了多少张牌 buffer.sum+=buffer.arr[i]; charaff='N'; inttype=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; } } staticvoidturnstart(){ charu; 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); inti; printf("\n\n\n\n\n\n\n牌面张数为%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("现在轮到玩家%d",game.who+1); printf("玩家1(%s)手牌%d",sta_arr[player[0].status],player[0].size);if(game.who==0)printf("<=====\n");elseprintf("\n"); printf("玩家2(%s)手牌%d",sta_arr[player[1].status],player[1].size);if(game.who==1)printf("<=====\n");elseprintf("\n"); printf("玩家3(%s)手牌%d",sta_arr[player[2].status],player[2].size);if(game.who==2)printf("<=====\n");elseprintf("\n"); } /*判断是否连续*/ staticintcontinuum(intnum,inttotal){ inti,count=0; intflag=0;//有值则标记为1 intsig=0;//从有到无改标记为1 for(i=1;i<=15;i++){ if(buffer.arr[i]==num){ if(sig) return0;//非连续 count++; if(count==total) return1;//连续 flag=1; }else{ if(flag) sig=1; } } } /*获取缓冲区牌类类型*/ staticinttype_buffer(){ inti,one=0,pair=0,triple=0,quattuor=0,zero=0; for(i=1;i<=15;i++){//统计单张,对子,三同,四同各有多少 if(buffer.arr[i]==1) one++; elseif(buffer.arr[i]==2) pair++; elseif(buffer.arr[i]==3) triple++; elseif(buffer.arr[i]==4) quattuor++; elsezero++; } //printf("单%d对%d三%d四%d零%d,sum%d===\n",one,pair,triple,quattuor,zero,buffer.sum); if(!(buffer.sum)){ return-1;//非法 } elseif(buffer.sum<=5){//1~5 if(one==1&&!pair&&!triple&&!quattuor)//单张 return1; elseif(pair==1&&!one&&!triple&&!quattuor)//对子 return2; elseif(one==2&&buffer.arr[14]&&buffer.arr[15])//王炸 return3; elseif(triple==1&&!one&&!pair&&!quattuor)//骷髅 return4; elseif(one==1&&!pair&&triple==1&&!quattuor)//骷髅单 return5; elseif(!one&&!pair&&!triple&&quattuor==1)//炸 return6; elseif(!one&&pair==1&&triple==1&&!quattuor)//骷髅对 return7; elseif(one==1&&!pair&&!triple&&!quattuor){//炸带单 return8; } elseif(!pair&&!triple&&!quattuor&&(!buffer.arr[14]&&!buffer.arr[15])&&buffer.sum==5){//顺子 if(continuum(1,one))//所有1连续 return9; else{ return-1; } } elsereturn-1; } elseif(buffer.sum>=6){ if((!one)&&(pair==1)&&(!triple)&&(quattuor==1))//炸带对 return10; elseif(!one&&!pair&&!quattuor){//只有2个以上个三张相同飞机不带 if(continuum(3,triple))//所有3连续 return11; elsereturn-1; } elseif(!one&&!triple&&!quattuor){//连对 if(continuum(2,pair)) return12; elsereturn-1; } elseif(buffer.sum==4*triple){//飞机单 if(continuum(3,triple)) return13; elsereturn-1; } elseif((buffer.sum==5*triple)&&(triple==pair)){//飞机对 if(continuum(3,triple)) return14; elsereturn-1; } elseif(!pair&&!triple&&!quattuor&&(!buffer.arr[14]&&!buffer.arr[15])){ if(continuum(1,one)) return9; elsereturn-1; } elsereturn-1; } } /*最大下标*/ staticintmaxindex(intcount){ inti; for(i=15;i>=1;i--){ if(buffer.arr[i]==count) returni; } } /*获取缓冲区牌类等级*/ staticintlevel_buffer(inttype){ switch(type){ case1: returnmaxindex(1); break; case2: returnmaxindex(2); break; case3: return15; break; case4: returnmaxindex(3); break; case5: returnmaxindex(3); break; case6: returnmaxindex(4); break; case7: returnmaxindex(3); break; case8: returnmaxindex(4); break; case9: returnmaxindex(1); break; case10: returnmaxindex(4); break; case11: returnmaxindex(3); break; case12: returnmaxindex(2); break; case13: returnmaxindex(3); break; case14: returnmaxindex(3); break; } } /*消减手牌*/ staticvoidannealation(){ inti=1; intj=0; intwho=game.who; for(i=1,j=0;buffer.brr[j];i++,j++){ intindex=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"); } /*回合进行中*///这个模块有很大的修改空间例如return改为break... voidturning(){ turnstart();/*开始阶段*/ handcard_sort(); print(); intlevel=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();/*出牌阶段在这函数判断是否弃权比较好*/ inttype=type_buffer(); intlevel=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; } elseif(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; } elseif(level<game.level||level==game.level){ printf("牌的等级不够大\n"); continue; } } } elseif(game.count==2){//两家弃权 annealation(); game.type=type; game.level=level; return; } else{//除了炸弹两家弃权王炸非法以外的合理牌类 if(type!=game.type){//不对应 printf("类型不对应\n"); continue; } else{//对应 if(buffer.sum!=game.sum){ printf("数量不对应\n"); continue; } if(level<game.level||level==game.level){ printf("牌的等级不够大\n"); continue; } elseif(level>game.level){ printf("\n\n\n\n\n压死\n"); annealation(); game.type=type; game.level=level; return; } } } } } /*0123判断是否是谁胜利0表示没有1表示玩家一*/ intwin(){ intnow=game.who; if(!player[now].size) returnnow; elsereturn0; } /*切换当前玩家为下家*/ voidturn_switch(){ intwho=game.who; who++; game.who=who%3; }
main.c
#include<stdio.h> #include"head.h" intmain(){ while(1){ intwhich; game_init();//初始化游戏 while(1){ turning();//回合进行中 printf("\n\n\n"); if(which=win())//是否产生胜者 break; turn_switch();//切换出牌方 } printf("胜负已出!胜利者是玩家%d\n",which+1); printf("是否重新游戏?(y为继续,其它退出程序):"); charchoice; scanf("%c",&choice); scanf("%*[^\n]"); scanf("%*c"); if(choice=='y'||choice=='Y') continue; break; } printf("谢谢试玩\n"); }
以上所述就是本文的全部内容了,希望对大家熟练应用C语言能够有所帮助。