扑克牌游戏
一、问题阐述
实现一个简单的扑克牌游戏,可以洗牌、发牌,还有玩家打牌等功能,具体任务如下:
(1)一副扑克52张牌(去掉大小王),分别是A、2、3、4、5、6、7、8、9、10、J、Q、K,每种4张(不考虑花色);
(2)由电脑随机洗牌,并分成4份(4个电脑玩家),并设计出一个对弈函数,每家调用该函数实现自动出牌;出牌后,若所有下家都没有牌出,则当前这一家可以选择出其它牌。
二、流程图
三、设计思路
(1)利用结构体定义扑克牌以及玩家
(2)通过random随机写洗牌函数
(3)基本代码完成玩家之间的对弈,再写出一个删除牌的函数
四、代码实现
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>struct Poker{
int num;
};
struct Poker allpoker[52]; //一整副牌 52张struct poker{ //一个玩家13张牌
int cards[13];
};
struct poker player[4]; //设置玩家,一共四个玩家void wash(); //洗牌函数
int seekmin(int cnt); //找手牌中最小牌
void remove(int minimum, int cn); //移除出过的牌
int judge(int inde); //转到下一个玩家
int seek(int o, int p); //找到比上一家出的牌大的牌
int search(int r[],int g); //从比上一家出的牌大的牌里面找到最小的牌const char *face[] = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"}; //牌面的设置( 0-12)
int main()
{
printf("扑克牌游戏来啦!");
wash();
int index1[13];
int index2[4];
int m1, m2, m3=0, m4;
int n=0;
srand((unsigned)time(NULL));
for(int k=0;k<52;k++) //这个for循环一整个为发牌
{
if(k%13==0)
{
for(int j=k, h=0;j<(k+13)&&h<13;j++,h++)
{
player[n].cards[h] = allpoker[j].num%13; //通过对0-51取余13得到1-13,通过0-12去表达牌面
}
printf("\n玩家%d:",k/13+1);
index2[n] = (k/13+1); //将玩家存起来 (0-3)
for(int m=0;m<13;m++)
{
printf("%s ",face[player[n].cards[m]]); //手牌
}
n++; //下一个玩家
}
}
printf("\n!!游戏开始!!\n");
m1 = rand()%4; //随机挑选一个玩家作为庄
printf("玩家%d先出牌:", index2[m1]);
m2 = seekmin(m1); //寻找庄主手中最小的牌
printf("%s \n",face[m2]);
remove(m2, m1); //移除这一张出过的牌
if(m1==3)
{
m1 = 0; //如果m1=3的话,加1就变为了4 ,而储存玩家的数组中是0-3 。当m1=3时是玩家4,下一个玩家应为玩家1,所以判断m1是否为3
}
else if(m1>=0&&m1<3)
{
m1++; //如果m1!=3,则加一即可
}
while(player[m1].cards[0]!=88)
{
m2 = seek(m2, m1); //寻找比上一家出的牌大的牌,seek函数的返回值有两种,一种是返回玩家手中最小牌,二是没有找到比上一家大的牌返回-1
if(m2>=0) //有比上一家大的牌,则进入这个if
{
printf("玩家%d出牌:%s \n",index2[m1], face[m2]);
m4 = m2; //将m2保存起来,方便于下一家的使用,如果不存起来,下一次循环会改变m2的值
remove(m2, m1); //移除这张出过的牌
m1 = judge(m1); //转到下一家
m3 = 0; //通过后面再了解这一步,这里是避免有玩家可以出牌但是却会进入要不起的判断
continue; //当玩家出了牌,就跳回到循环头部,不要继续走下去
}
else if(m2==-1) //当m2返回值为-1,则是该玩家要不起
{
printf("玩家%d要不起\n",index2[m1]);
m2 = m4; //这里就将上一个if里面的m4再给回m2,就可以用于找大于上家的牌,否则这里返回的m2是-1;
m1 = judge(m1);
if(player[m1].cards[0]==88) //判断是否有玩家已经出完了牌,如果出完直接跳出循环
{
break;
}
m3++;
if(m3%3==0) //当有连续三个玩家要不起,就会回到出最大牌的那名玩家,但是每当可以%3的时候都会进入这里,所以上一个if里面要加m3=0,就是避免进入这个if
{
m2 = seekmin(m1); //寻找这名玩家手中最小牌
printf("玩家%d出牌:%s\n",index2[m1], face[m2]);
remove(m2, m1); //移除这张出过的牌
m1 = judge(m1); //到下一个玩家
continue; //回到循环头部
}
}
}
printf("赢家是%d,恭喜他!!",index2[m1]);
return 0;
}void wash()
{
int number;
int count;
srand((unsigned)time(NULL));
for(int i=0;i<52;i++) //得到一副牌
{
allpoker[i].num = i;
}
for(int i=0;i<52;i++) //打乱牌的顺序
{
number = rand()%52;
count = allpoker[number].num;
allpoker[number].num = allpoker[i].num;
allpoker[i].num = count;
}
}
int seekmin(int cnt)
{
int min = player[cnt].cards[0]; //设置最小值
for(int k=1;k<13;k++)
{
if(min>player[cnt].cards[k]&&min!=88)
{
min = player[cnt].cards[k];
}
}
return min;
}
void remove(int minimum, int cn)
{
int l, x=0;
for(int k=0;k<13;k++)
{
if((player[cn].cards[k])==minimum)
{
for(l=k;l<13;l++)
{
x=1;
player[cn].cards[l] = player[cn].cards[l+1]; //通过将后一个数移到前一个数,从而达到移除的效果
}
player[cn].cards[l-1] = 88; //让最后一张牌的位置,也就是12这个位置为88
}
if(x==1)
break;
}
}
int judge(int inde) //利用switch语句转到下一个玩家
{
int num;
switch(inde)
{
case 0:num=1;break;
case 1:num=2;break;
case 2:num=3;break;
case 3:num=0;break;
}
return num;
}
int seek(int o, int p)
{
int w=0, t[13], e[13], q;
int result;
for(int k=0;k<13;k++)
{
t[k] = player[p].cards[k]; //先将下一家的手牌存到这个数组中
}
for(int i=0;i<13;i++)
{
if(t[i]>o&&t[i]!=88) //判断这个玩家手牌中大于上一家的出的牌
{
e[w] = t[i]; //将这些大的牌存到这个数组之中
w++;
}
}
if(w!=0) //若是有大的牌,那w肯定不为0
{
q = search(e, w); //进入到这个函数中去寻找这些大的牌里面的最小牌
return q;
}
else if(w==0) //没有大的牌就返回-1
{
return -1;
}
}
int search(int r[],int g) //用于寻找大的牌里面最小的牌
{
int min;
min = r[0];
for(int i=0;i<g;i++)
{
if(min>=r[i]&&r[i]!=88)
{
min = r[i];
}
}
return min;
}