扑克牌游戏
游戏规则在程序开头有注释
C语言初学时写的,逻辑较多,仅供娱乐~~~
代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define HOLD 440
//操作日志
//可实现判断八倍、五倍、三倍、已实现 (牌的三个数进行编码(例如组成一串数字*10*100*1000)后,进行数组对比)
//可实现准确加点数*************(已实现(子函数compare、firstround,)
//输出有倍的输出需要修改,用if判断(子函数实现,putout2)(已实现)每一位玩家的点数倍数的文字输出//最终的输出需要再建子函数//有鬼还被判断为青盲(已解决,在putout2里面)
//有鬼要把补牌后的状况打印出来(已实现,在king子函数里面)不补牌牌的结果也要打印(已实现)
//bug 当第三支牌是鬼的时候,会直接被判断为有鬼而必须补牌(已解决)
//JQK被判断青盲(似乎已解决)**+++++++++++++++++++++++++++++++++
//3.3时会判断为双倍六,但没有输出点数(已解决)
//2.有鬼情况补牌后的牌显示出来(已实现)
//bug 似乎54张牌不是一张一张取完,因为每个人是取到三张不重复的牌,但是每个人的牌还是有重复(已解决)
//两支牌补牌后,无型的,没有打印点数 两支不补偶尔也会出现那种情况(似乎情况已解决)(是由ghost全局变量引起,已解决)
//判断为有倍后,点数应当弄为一个数,用于最终输出的判断(不需要,只需判断sign>=4)
//poutout1子函数用于输出花色和牌名,需要完善----或许需要两个子函数,1.最终结算结果的输出,按倍数和点数这两个参数传入。(已解决)
//补鬼情况,需要增加(补鬼情况解决,鬼补鬼情况需要增加(已实现))
//随机数部分,需要检查(已检查 应该是%54,才能取0-53范围的54个数,起先again数组应该全部初始化为一个不可能的数,例如55)
//两支四要判断为双倍八(已实现)
//补到的那支牌,打印出来(已解决)
//有鬼情况下的三倍九/在king函数里面/(之前已经实现)
//无倍打印点数,有倍只打印数字(已实现)
//while咨询用户是否补牌的时候用死循环控制只能输入0或1(已实现)
//用while语句限制输入的牌最多17张(已实现)
//初始化提示用户的打印信息,用子函数(已实现)
//做while循环,使得可以多次进行游戏(已实现)
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&((注意))--------/逻辑语句里面的if(a==4)如果少了=,编译器检查不出来/
//增加音乐功能(做不出来)
int score=0; //点数,每一个子函数的判断都有改变score的值
int sign=1;//倍数,每一个子函数的值都有改变sign的值
int ghost=0;//有鬼时ghost置1,在putout2里面用到
int gui=0;//鬼的大小标志数,1为小鬼,2为大鬼,1,2,3代表三张牌。 11,12,13(小鬼第一张、第二张、第三张) 21,22,23(大鬼第一张、第二张、第三张)
int main()
{
system("mode con cols=120 lines=30");
system("title 《添空卡牌》");
system("color f0");
welcome();
while(1)
{
//set---------------------for (i=0;i<12;i++)
srand(time(NULL));
int i,j,c,q;//i,j是循环用到的变量,c是随机数,q是玩家人数
int people;
//int output[2]={};
int answer; //用户的选择
int list[3]; //储存抽中的3张牌对应编号
int type[3][2]; //花色加点数的储存
int scoremain[17]={};//存储17个人的点数
int signmain[17]={}; //存储17个人的花色
int joy; //和joyful一起使用的循环变量
int joyful;
int jump;
int again[18][3]=
{{55,55,55},{55,55,55},{55,55,55},
{55,55,55},{55,55,55},{55,55,55},
{55,55,55},{55,55,55},{55,55,55},
{55,55,55},{55,55,55},{55,55,55},
{55,55,55},{55,55,55},{55,55,55},
{55,55,55},{55,55,55},{55,55,55}
};
//work-------------------------------------
// printf("请问有多少个玩家进行游戏?(1-17)\n");
//scanf("%d",&people);
people=ask(0);//调用函数,mode 0,控制1-17的输入
printf("\n");
for(q=0;q<people;q++)//总共q位玩家进行游戏
{
printf("|这是第%d个玩家|\n",q+1);Sleep(HOLD);
sign=1;
score=0;
ghost=0;
//*************************************************
for(i=0;i<3;i++)//取三个0-53的不重复的数,且每一轮后不重复
{
while(1)
{
c=random();
jump=0;//标志内循环跳出
for(joy=0;joy<18;joy++)
{
for(joyful = 0; joyful<3;joyful++)
{
if(again[joy][joyful]==c)
{
jump++;
break;//检查重复。跳出内循环jump标志一下
}
}//小循环
if(jump!=0)
break;//跳出 joy18循环
}//大循环
if(joy==18&&joyful==3)//没有重复值,保存到list中。
{
list[i] = c;
again[q][i]=list[i];//q从0开始计数
break;
}
}//while 结束
//*********************************************************
type[i][0]=c/13;//数组指点0-4代表花色 0:黑桃,1:红桃,2:梅花,3方角,4:鬼
type[i][1]=c%13;//0-12代表牌点数1-13
}
//上面for i 3发牌结束
//先自动判别10倍,再判别是否有鬼,再进行无鬼的是否补牌//下面是看牌阶段
if ((list[0]==53&&list[1]==52)||(list[0]==52&&list[1]==53))//十倍
{
for(j=0;j<2;j++)//这个位置打印两张牌花色和点数
{
putoutflower(type[j][0],type[j][1]);//-----花色、点数---------给putoutflower传入参数
}
printf("由于是两支鬼,是十倍,等级最高");Sleep(HOLD);
sign=10;
ghost=1;
}
else//非十倍情况
{
if (list[0]==53||list[1]==53||list[0]==52||list[1]==52)//此处有bug,当第三支牌是鬼的时候,会直接被判断为有鬼而必须补牌(此处无错误)*******************************-------------
{
for(j=0;j<2;j++) //这个位置打印三张牌花色和点数
{
putoutflower(type[j][0],type[j][1]); //**花色、点数*************输出的事情交给putoutflower
}
printf("由于有鬼,所以一定要补牌\n");Sleep(HOLD);//在判断有两支鬼(十倍)的情况上出了问题(问题已解决)
printf("补到了: "); Sleep(HOLD);
putoutflower(type[2][0],type[2][1]);//打印出补到的牌
printf("结果为:\n"); Sleep(HOLD);
king(type[0][0],type[0][1],type[1][0],type[1][1],type[2][0],type[2][1]);//鬼型函数
ghost=1; //有鬼
}
else //无鬼情况
{
ghost=0;//无鬼
for(j=0;j<2;j++)//这个位置打印两张牌花色和点数
{
putoutflower(type[j][0],type[j][1]);//-----花色、点数---------给putoutflower传入参数
//printf("%d ",type[j][k]+1);
}
//printf("是否补一支牌?(1补牌。0不补)");
//scanf("%d",&answer);
answer=ask(1); //调用函数,mode 0,0或者1的输入
switch(answer) //根据用户答案进入2支或3支牌的情况
{
case 0:
{
firstround(type[0][0],type[0][1],type[1][0],type[1][1]); //调用函数
printf("结果是:\n");
for(j=0;j<2;j++) //打印两张牌花色和点数
{
putoutflower(type[j][0],type[j][1]);//**花色、点数************************************------------------------------给putoutflower传入参数
//printf("%d ",type[j][k]+1);
}
}
break;
case 1:
{
compare(type[0][0],type[0][1],type[1][0],type[1][1],type[2][0],type[2][1]);//调用函数compare
printf("补到了: "); Sleep(HOLD);
putoutflower(type[2][0],type[2][1]);//打印出补到的牌
printf("结果为:\n");Sleep(HOLD);
for(j=0;j<3;j++) //打印三张牌花色和点数
{
putoutflower(type[j][0],type[j][1]);//**花色、点数*************输出的事情交给putoutflower
}
}
break;
}
}
}
scoremain[q]=score;//记录每个人对应点数
signmain[q]=sign; //记录每个人对应倍数
/*for(j=0;j<3;j++)//打印牌的编号,是编程过程的辅助方法,让我看见数的状态
{
printf("牌的编号%d ",list[j]+1);
}*/
// printf("\n点数为:%d\n",score);
// printf("倍数为:%d\n\n",sign);
printf("牌点是:");
Sleep(HOLD);
putout2(); //每一轮结束打印一下玩家的牌型
}//以上为多位玩家抽完牌的循环**********************************************-----------------------------
//sum output---------------------------------
printf("|所有人牌型|\n");
for(j=0;j<people;j++)//最终的打印
{
putout1(j+1,scoremain[j],signmain[j]);
//printf("%d号玩家:%d倍%d\n",j+1,signmain[j],scoremain[j]);//四倍、五倍、八倍和十倍的输出需要调整(if)判断
}
printf("\n");
printf("-----本轮游戏结束-----\n\n");
Sleep(HOLD);
printf("稍等10秒再次进行游戏\n\n\n\n");
Sleep(10000);
system("cls");
Sleep(HOLD);
printf("-----游戏开始-----\n\n");
Sleep(HOLD);
}
}
int random() //产生随机数
{
int z;
z=rand()%54;
return z;
}
int ask(int mode)//询问函数(此法似乎不可用)(可以使用)//mode 0:玩家人数限制输入,1:是否补牌限制输入
{
int a;
switch(mode)
{
case 1:
{printf("请问要补牌吗?(补牌输入1,不补牌输入0)");
scanf("%d",&a);
while(a!=0&&a!=1)
{
printf("\n请重新输入(补牌输入1,不补牌输入0):");
scanf("%d",&a);
}
}
break;
case 0:
{
printf("请问有多少个玩家进行游戏?(1-17)\n");
scanf("%d",&a);
while(a>17||a<1)
{
printf("\n请重新输入(1-17):");
scanf("%d",&a);
}
}
}
return a;
}//*///无用的子函数,留作纪念,(由于无法实现想要的询问功能)(是因为返回类型设置错误,应该是返回int)
int compare(int A,int a,int B,int b,int C,int c) //补牌并且实现八倍、五倍、四倍、三倍的判断
{
//可实现判断八倍、五倍、三倍、
//可实现准确加点数*************
//set---------------------------------
int T,t;
int i;//循环变量
if(C==4)//无鬼补鬼
{
king(A,a,B,b,C,c);//当做鬼型处理
}
else//非补鬼情况
{
a++;b++;c++;//注意abc的值改变
//排序************//a到c从小到大
if (a>b)
{
T=A;t=a;
A=B;a=b;
B=T;b=t;
}
if(a>c)
{
T=A;t=a;
A=C;a=c;
C=T;c=t;
}
if (b>c)
{
T=B;t=b;
B=C;b=c;
C=T;c=t;
}
//printf("a=%d,b=%d,c=%d",a,b,c);//测试用的,用于看数据变化
//***************
int k=0;
int x,y,z; //每张牌点数
//把abc组合为一个数k用于比较
if (a<=7)k=a*100+b*10+c;
if (a==8)k=a*1000+b*100+c;
if (a>8&&a<=11)k=a*10000+b*100+c;
if ((c==13&&a==1&&b==2)||(a==1&&b==12&&c==13))sign=4;//QK1,K12
int examplebird[]={123,234,345,456,567,678,789,8910,91011,101112,111213,1213,11213};
int num[3][13]={
{1,2,3,4,5,6,7,8,9,10,10,10,10},
{1,2,3,4,5,6,7,8,9,10,10,10,10},
{1,2,3,4,5,6,7,8,9,10,10,10,10},
};
//work--------------------------------------------------
a--;b--;c--;//abc的值恢复
x=num[0][a];
y=num[1][b];
z=num[2][c];//把abc翻译成点数
//printf("A=%d,B=%d,C=%d,k=%d\n",A,B,C,k);用于观察数据变化
{ //倍的比对与判断
for(i=0;i<13;i++)//鸟型的比对,先判断是鸟型
if (k==examplebird[i])
sign=4;
if((sign==4)&&(A==B&&B==C))
{sign=8;} //八倍5
else
{
if (sign==4)sign=4;//四倍
else
{
if (a==b&&b==c)
sign=5;//5倍
else
{
if(A==B&&B==C)
{
sign=3;score=(x+y+z)%10;
} //三倍
else
{
sign=1;score=(x+y+z)%10;
}
}
}
}
}
}
}
int firstround(int A,int a,int B,int b) //第一轮发牌 实现空九、空八、双倍的判断
{
//set--------------------------------------
int x,y;//每张牌点数
//int kong8[]={810,811,812,813};
// int kong9[]={18,27,36,45};
int num[2][13]={
{1,2,3,4,5,6,7,8,9,10,10,10,10},//牌点
{1,2,3,4,5,6,7,8,9,10,10,10,10},
};
//work------------------------------------
x=num[0][a];
y=num[1][b];
score=(x+y)%10;
if(score==9&&A==B)
sign=14;//空九双倍
else
{
if (score==9)
sign=13;//空九
else
{if ((score==8&&A==B)||(score==8&&a==b))
sign=12;//空八双倍,两支四也算
else
{
if (score==8)
sign=11;//空八
else
{
score=(x+y)%10;
sign=1;//无倍
if (A==B||a==b)//双倍的判断
{
sign=2;//在无倍基础上,有平样的花色或者点数就把sign置2
}
}
}
}
}
//output----------------------------------
}
int king(int A,int a,int B,int b,int C,int c) //有鬼情况的牌型判断 ******* //用if进行判断是否有鬼,从而调用函数(已实现)
{
//鬼也具有点数,所以导致Q2被判为五倍(已解决)
//ABC在本子函数里没有变值,abc在本子函数里起先加1,后减1
if((A==4&&C==4)||(B==4&&C==4))//鬼补鬼
{
sign=8;
}
else
{
int t,T;//排序的中间量
a++;b++;c++;//加加一次
{//小鬼情况的判断,把鬼的点数置6,从而把鬼的点数与普通牌的点数区分开
if (A==4&&a==1)
{
a=6;//小鬼
if(b>c)
{
t=b;T=B;
b=c;B=C;
c=t;C=T;
}
if((c-b==2)||(c-b==1)||(b==1&&c==13)||(b==1&&c==12)||(b==2&&c==13))//K1,Q1,K2
sign=4;
}
if (B==4&&b==1)
{
b=6;//小鬼
if(a>c)
{
t=a;T=A;
a=c;A=C;
c=t;C=T;
}
if((c-a==2)||(c-a==1)||(a==1&&c==13)||(a==1&&c==12)||(a==2&&c==13))//K1,Q1,K2
sign=4;
}
if (C==4&&c==1)
{
c=6;//小鬼,帮助输出
if(a>b)
{
t=a;T=A;
a=b;A=B;
b=t;B=T;
}
if((b-a==2)||(b-a==1)||(a==1&&b==13)||(a==1&&b==12)||(a==2&&b==13))//K1,Q1,K2
sign=4;
}
}
{//大鬼情况的判断,把鬼的点数置11
if (A==4&&a==2)
{
a=11;//大鬼
if(b>c)
{
t=b;T=B;
b=c;B=C;
c=t;C=T;
}
if((c-b==2)||(c-b==1)||(b==1&&c==13)||(b==1&&c==12)||(b==2&&c==13))//K1,Q1,K2
sign=4;
}
if (B==4&&b==2)
{
b=11;//大鬼
if(a>c)
{
t=a;T=A;
a=c;A=C;
c=t;C=T;
}
if((c-a==2)||(c-a==1)||(a==1&&c==13)||(a==1&&c==12)||(a==2&&c==13))//K1,Q1,K2
sign=4;
}
if (C==4&&c==2)
{
c=11;//大鬼,帮助输出
if(a>b)
{
t=a;T=A;
a=b;A=B;
b=t;B=T;
}
if((b-a==2)||(b-a==1)||(a==1&&b==13)||(a==1&&b==12)||(a==2&&b==13))//K1,Q1,K2
sign=4;
}
}
//set----------------------
//int example[]={12,13,23,24,34,35,45,46,56,57,67,68,78,79,89,810,910,911,1011,1012,1112,1113,1213,112,113,213};//八倍型,鸟型//此处编码有问题,例如:120=10*b+c,b和c可以有不同组合
//for (i=0;i<26;i++)//进行26次倍数的比对
if((sign==4)&&(A==B||A==C||B==C))//8,4,5,3,1倍的判断
{sign=8; } //八倍
else
{
if (sign==4)sign=4;//四倍
else
{
if (a==b||b==c||a==c)
{sign=5;}//5倍
else
{
if(A==B||A==C||B==C)
{sign=3;score=9;} //3倍
else {sign=1;score=9;}
}
}
}
//output---------------------------------
a--;b--;c--;//减减回来
char card[13]={'A','2','3','4','5','6','7','8','9','+','J','Q','K'};
char shape[6][5]={"黑桃","红桃","梅花","方块","大鬼","小鬼"};
{ //第某支牌的大小鬼判断,便于输出
//经过减减,鬼的点数5代表小鬼,10代表大鬼
if (A==4&&a==5)//第一支牌小鬼
{
printf("第一支牌:小鬼\n");
printf("第二支牌:%s %c\n",shape[B],card[b]);
printf("第三支牌:%s %c\n",shape[C],card[c]);
}
if (A==4&&a==10)//第一支牌大鬼
{
printf("第一支牌:大鬼\n");
printf("第二支牌:%s %c\n",shape[B],card[b]);
printf("第三支牌:%s %c\n",shape[C],card[c]);
}
if (B==4&&b==5)//第二支牌小鬼
{
printf("第一支牌:%s %c\n",shape[A],card[a]);
printf("第二支牌:小鬼\n");
printf("第三支牌:%s %c\n",shape[C],card[c]);
}
if (B==4&&b==10)//第二支牌大鬼
{
printf("第一支牌:%s %c\n",shape[A],card[a]);
printf("第二支牌:大鬼\n");
printf("第三支牌:%s %c\n",shape[C],card[c]);
}
if (C==4&&c==5)//
{
printf("第一支牌:%s %c\n",shape[A],card[a]);
printf("第三支牌:%s %c\n",shape[B],card[b]);
printf("第三支牌:小鬼\n");
}
if (C==4&&c==10)//
{
printf("第一支牌:%s %c\n",shape[A],card[a]);
printf("第三支牌:%s %c\n",shape[B],card[b]);
printf("第三支牌:大鬼\n");
}
}
}
//int example5[]={11,22,33,44,55,66,77,88,99,1010,1111,1212,1313};
}
int putout1(int q,int a,int b) //最终输出全部玩家的倍数和点数
{
int i;
char rank[14][12]={"无倍","双倍","三倍","一鸟(四倍)","五倍","六倍","七倍","八倍","九倍","十倍","添空八","添空八*双倍","添空九","添空九*双倍"};
char point[10][6]={"青盲","一点","二点","三点","四点","五点","六点","七点","八点","九点"};
char point2[10][6]={"盲","一","二","三","四","五","六","七","八","九"};
printf("第%d位玩家:",q);Sleep(HOLD);
if(q<10)printf(" ");//对齐
if (b>=4)//大于等于4倍,只打印倍数
{
for (i=0;i<12;i++)
printf("%c",rank[b-1][i]);Sleep(HOLD);
}
else
{
if(b==2||b==3)
{
for (i=0;i<12;i++)
printf("%c",rank[b-1][i]);Sleep(HOLD);
for (i=0;i<3;i++)
printf("%c",point2[a][i]);Sleep(HOLD);
}
else
{
for (i=0;i<12;i++)
printf("%c",rank[b-1][i]);Sleep(HOLD);
for (i=0;i<6;i++)
printf("%c",point[a][i]);Sleep(HOLD);
}
}
printf("\n");
}
int putout2() //用于每一次补牌后结算后,打印倍数和点数
{
int i,j;
char rank[14][12]={"无倍","双倍","三倍","一鸟(四倍)","五倍","六倍","七倍","八倍","九倍","十倍","添空八","添空八*双倍","添空九","添空九*双倍"};
char point[10][6]={"青盲","一点","二点","三点","四点","五点","六点","七点","八点","九点"};
char point2[10][6]={"盲","一","二","三","四","五","六","七","八","九"};
//work------------------------------------
if (sign>=4)//大于等于四倍
{
for (i=0;i<12;i++)
printf("%c",rank[sign-1][i]);
Sleep(HOLD);
}
else
{
if(sign==2||sign==3)
{
for (i=0;i<12;i++)
printf("%c",rank[sign-1][i]);Sleep(HOLD);
for (i=0;i<6;i++)
printf("%c",point2[score][i]);Sleep(HOLD);
}
else
{
for (i=0;i<12;i++)
printf("%c",rank[sign-1][i]);Sleep(HOLD);
for (i=0;i<6;i++)
printf("%c",point[score][i]);Sleep(HOLD);
}
}
printf("\n");
//output-------------------------------------
/* for (i=0;i<12;i++)
printf("%c",rank[sign-1][i]);
printf("\n");*/
/*for (i=0;i<14;i++)
{
for (j=0;j<12;j++)
{
printf("%c",rank[i][j]);
}
}*/
printf("\n");
/* for (i=0;i<10;i++)
{
for (j=0;j<5;j++)
{
printf("%c",point[i][j]);
}
}*/
}
int putoutflower(int a,int b) //打印“花色”和“点数”的符号
{
char shape[6][5]={"黑桃","红桃","梅花","方块","小鬼","大鬼"};
char card[13]={'A','2','3','4','5','6','7','8','9','+','J','Q','K'};
int i,j;//随机数的取法仍然有问题(问题解决)
if(a!=4)
{
printf("%s %c\n",shape[a],card[b]);Sleep(HOLD);
}
else
{
if (b==0){printf("%s \n",shape[4]);Sleep(HOLD);}
if(b==1) {printf("%s\n",shape[5]); Sleep(HOLD);}
}
}
int welcome()
{
printf("\n");
{int i;//滑条来回滑动一次
int j;
for(i=0;i<44;i++)
{
for(j=0;j<i;j++)
{
printf(" ");
}
printf("======\n");
Sleep(18);
system("cls");
}
for(i=0;i<44;i++)
{
for(j=44;j>i;j--)
{
printf(" ");
}
printf("======\n");
Sleep(18);
system("cls");
}
}
printf("\n");
printf("欢迎来到《添空卡牌》模拟扑克牌游戏!!\n\n");
Sleep(HOLD);
printf("-------------------------------------------------------------------------------------------------------------------\n");
Sleep(HOLD);
printf("首先:我来介绍一下游戏规则\n\n");
Sleep(HOLD);
printf("1:一个玩家发2张牌,看牌后考虑是否补牌\n");
Sleep(HOLD);
printf("2:牌的最终等级分为“无倍”、“双倍”、“三倍”、“四倍”、“五倍”、“八倍”、“十倍”依次增大\n");
Sleep(HOLD);
printf("3:牌的点数最终分为“青盲”、“一点”、“两点”、“三点”、“四点”、“五点”、“六点”、“七点”、“八点”、“九点”\n\n");
Sleep(HOLD);
printf("其中特殊的是:\n");
Sleep(HOLD);
printf("1:两支鬼为十倍、三支花色一样而且顺的是八倍、三支点数一样是五倍、三支花色不一样的顺是四倍(一鸟)、\n 三支花色一样但不顺是三倍、两支花色一样或点数一样是双倍、普通类型为无倍\n");
Sleep(HOLD);
printf("2:牌的点数是每一支牌点相加,JQK按照10点算,只取尾数(即三张牌点数和的个位)作为最终的点数\n");
Sleep(HOLD);
printf("3:两张牌和为“九点”或“八点”的判断为添空九、添空八\n");
Sleep(HOLD);
printf("4:有鬼就一定要补牌哦!\n");
Sleep(HOLD);
printf("-------------------------------------------------------------------------------------------------------------------\n\n");
Sleep(HOLD);
printf("-----游戏开始-----\n\n");
Sleep(HOLD);
}