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语言能够有所帮助。