游戏规则:
1、将一副牌中的大小王去掉,剩余的52张牌(1-13)*4,洗牌后按顺序分配给两名选手(这里用的方法是随机抽取其中的一张牌发给选手);
2、随机抽取其中一人先出牌,之后两人轮流将自己手里最前面的牌放到桌面;
3、如果放下去的牌,在桌面上已经存在,则选手将两个相同点数的牌面之间的所有牌(含相同点数的牌),收取到自己手中,并放到最后;
4、直到其中一人手中没有牌,游戏结束;手里有牌的人胜出。
要点:
1、两名选手,所持牌面符合“先进先出”的原则,用顺序表作为数据结构存储(本文采用的是顺序链,方便摘除和增加结点)
2、桌面的牌符合”先进后出“的原则,利用栈数据结构存储
3、为了增加游戏的过程可读性,增加了每一轮出牌情况,及两名选手和桌面牌面的展示;
运行情况:
开始->
结束->
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
/*定义,每张牌*/
typedef struct Card
{
int hcard;
struct Card *front;
struct Card *back;
} Bcard;
/*初始化选手和桌面,创建选手牌面队列头结点和桌面牌面栈*/
Bcard *initcard()
{
Bcard *p=(Bcard *)malloc(sizeof(Bcard));
p->front=p;
p->back=p;
return p;
}
/*选手取牌*/
pushcard(Bcard *p,int temcard)
{
Bcard *t = (Bcard *)malloc(sizeof(Bcard));
if(t==NULL)
{
printf("申请空间失败!\n");
}
//将牌发到选手手中,申请新空间结点,连接到选手队列
t->hcard=temcard;
t->back=p->back;
p->back->front=t;
t->front=p;
p->back=t;
}
/*选手出牌*/
popcard(Bcard *p)
{
Bcard *t;
t=p->front;//定位要出的牌
//摘除牌所占结点
t->front->back=p;
p->front=t->front;
printf("%3d\n",t->hcard);//显示选手出的牌
free(t);//释放选手已经出的牌
}
/*遇到相同点数的牌,桌面上的牌给选手,出栈*/
popsharcard(Bcard *p12,Bcard *p3card)
{
Bcard *t;
pushcard(p12,p3card->back->hcard);
t=p3card->back;
p3card->back=p3card->back->back;
p3card->back->front=p3card;
free(t);//释放已经被选手收取的牌所占空间
}
/*初始发牌*/
void fapai(Bcard *p1card,Bcard *p2card)
{
Bcard *p4card=initcard();//链表 整副牌初始化 1-13 * 4
//将52张牌(不含大小王)放入临时链表
int i,j;
for(i=1;i<=4;i++)
{
for(j=1;j<=13;j++)
{
pushcard(p4card,j);
}
}
//洗牌结束,开始给两名选手发牌
int select=1; //发牌标记
srand(time(NULL)); //随机种子
for(i=1;i<=52;i++)
{
Bcard *ptem1;
Bcard *ptem2;
if(1==select)//两人轮流取牌
{
ptem2=p1card;
}
else
{
ptem2=p2card;
}
select*=-1;//转换发牌标记
ptem1=p4card;
j=rand()%(53-i)+1;//在整副牌中随机抽取一张 发牌
while(j>0)//定位到收取的的牌
{
ptem1=ptem1->back;
j--;
}
pushcard(ptem2,ptem1->hcard);//发牌给选手
popcard(ptem1->back); //去除已经发过的牌
}
system("cls");//清屏,之前发牌的时候每发一次都输出一次+回车,为了看起来好看
printf("\n发牌结束\n");
}
/*输出选手和桌面上的牌面信息*/
void shuchuxuanchou(Bcard *pp)
{
Bcard *ppt;
ppt=pp;
while(1)
{
if(ppt->front==pp)
{
break;
}
printf("%3d",ppt->front->hcard);
ppt=ppt->front;
}
printf("\n");
}
/*遍历桌面牌面,查看是否存在和要出的牌点数相同的牌*/
int bianli(Bcard *p3,int temcard)
{
Bcard *pt;
pt=p3;
while(pt->back!=p3)
{
if(temcard==pt->back->hcard)
{
return 1;
}
pt=pt->back;
}
return -1;
}
/*收牌,先将自己要出的牌放在最后,再按顺序将桌面上相同点数的牌之前的牌收取到手中,放在最后*/
void shouqu(Bcard *ptem,Bcard *p3card)
{
int temcard=ptem->front->hcard;
pushcard(ptem,ptem->front->hcard);
popcard(ptem);
while(1)
{
if(temcard==p3card->back->hcard)
{
pushcard(ptem,p3card->back->hcard);
popcard(p3card->back->back);
break;
}
else
{
printf("%3d\n",p3card->back->hcard);
popsharcard(ptem,p3card);
}
}
}
/*开始游戏,随机抽取先出牌的选手,展示桌面牌面,选手牌面,其中一人手里没有牌,则对方胜利*/
void playgame(Bcard *p1card,Bcard *p2card,Bcard *p3card)
{
srand(time(NULL)); //随机种子
int select=rand()%3;//随机确定谁先出牌 0-选手 1 先出 ,1-选手 2 先出
Bcard *ptem;
if(2==select)//确定谁先出牌
{
ptem=p1card;
}
else
{
ptem=p2card;
}
int sum=0;
while(1)
{
printf("\n第 %d 轮",++sum);
printf("\n桌面牌面");
shuchuxuanchou(p3card);
if(p1card->front==p1card)
{
printf("\n\n选手 NO.1 手中已经无牌可出\n\n");
printf("恭喜 NO.2 获得胜利\n");
exit(0);
}
else if(p2card->front==p2card)
{
printf("\n\n选 NO.2 手中已经无牌可出\n\n");
printf("恭喜 NO.1 获得胜利\n");
exit(0);
}
int result=bianli(p3card,ptem->front->hcard);//查看桌面是否有要出的牌
if(-1==result)//没有 则放入桌面
{
pushcard(p3card,ptem->front->hcard);
popcard(ptem);
}
else//有 则收取到正在出牌的选手手里,放在最后
{
printf("\n选手收牌:\n");
shouqu(ptem,p3card);
printf("\n选手 NO.1 \n");
shuchuxuanchou(p1card);
printf("\n选手 NO.2 \n");
shuchuxuanchou(p2card);
}
/*转换出牌选手*/
if(ptem==p1card)
{
ptem=p2card;
}
else if(ptem==p2card)
{
ptem=p1card;
}
}
}
/*主函数*/
int main()
{
//初始化两名对手和桌面
Bcard *p1card=initcard();//队列 选手 1
Bcard *p2card=initcard();//队列 选手 2
Bcard *p3card=initcard();//栈 桌面
//发牌
fapai(p1card,p2card);
//展示选手 手里的牌面
printf("\n选手 NO.1 \n");
shuchuxuanchou(p1card);
printf("\n选手 NO.2 \n");
shuchuxuanchou(p2card);
//开始游戏
printf("\n选手出牌\n");
playgame(p1card,p2card,p3card);
//游戏结束
getchar();
return 0;
}