数据结构与算法——第3章-项目实战-扑克牌游戏(3.12)

一 概述

1
2
3
1.项目简介
2.设计思路
3.实现代码

二 项目简介

1
2
3
4
5
6
7
8
9
10
小时候在刚开始接触扑克牌的时候,最初学会的扑克游戏就是类似于“推小车”这样的无脑游戏,
本节带领大家使用学过的知识编写推小车卡牌游戏。

“推小车”扑克牌游戏适合 2-3 个人玩,游戏规则也超级简单:将一副扑克牌平均分成两份,
每人拿一份,每个人手中的扑克牌全部反面朝上,叠成一摞。
游戏进行时,每个人轮流拿出第一张扑克牌放到桌上,将其排成一竖行。
如果打出的牌与桌上某张牌的数字(红桃 5 和黑桃 5 在此游戏中相等)相等,
即可将两张相同的牌以及两张中间所夹的所有的牌全部取走,每次取走的一小摞牌都必须放到自己本摞的下面。

游戏过程中,一旦有人手中没有牌,则宣布另一人获胜,同时游戏结束。

三 设计思路

1
2
3
4
5
6
7
8
9
假设模拟两个人进行该扑克牌游戏。每个人在游戏过程中都是不断地从自己这一摞扑克牌的最上方去取牌,放到桌子上;
当发现自己的牌同桌子上的牌相等时,将赢得的牌依次放在自己扑克牌的下方。
这是典型的队列的“先进先出”。

而对于桌子而言,就相当于是一个栈。
每次放到桌子上的扑克牌,都相当于进栈;
当有相同的扑克牌时,相同的扑克牌连通之间的所有的扑克牌则依次出栈。

所以,模拟该扑克牌游戏需要同时使用 2 个队列和 1 个栈

四 实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <stdio.h>
#include <stdlib.h>
struct queue {
int data[1000];
int head;
int tail;
};
struct stack {
int data[10];
int top;
};
void showCard(struct queue *q,int *book,struct stack *s) {
int t=(*q).data[(*q).head]; //打出一张牌,即从队列 q 的队头取元素(此时还不往桌子的栈里放)
//判断取出的这张牌是否会赢牌
if(book[t]==0) { //若不赢牌,只需放到桌子上入栈即可
(*q).head++;//由于此时牌已经打出,所以队列的队头需要前进
(*s).top++;
(*s).data[(*s).top]=t; //再把打出的牌放到桌上,即入栈
book[t]=1; //标记桌上现在已经有牌面为 t 的牌
} else {
(*q).head++;//由于此时已经打出去一张牌,所以队头需要 +1
(*q).data[(*q).tail]=t;//将打出的牌放到手中牌的最后(再入队)
(*q).tail++;
//把桌子上赢得的牌依次放到手中牌的最后(依次出栈在入队列的过程)
while((*s).data[(*s).top]!=t) {
book[(*s).data[(*s).top]]=0;//取消对该牌号的标记
(*q).data[(*q).tail]=(*s).data[(*s).top];//依次放入队尾
(*q).tail++;
(*s).top--;
}
//最后别忘了将最后一张相等的牌取出放入队列
book[(*s).data[(*s).top]]=0;
(*q).data[(*q).tail]=(*s).data[(*s).top];
(*q).tail++;
(*s).top--;
}
}
int main() {
struct queue q1,q2;//两个队列,分别模拟两个人,假设分别为小王和小李
struct stack s;//栈,模拟桌子
int book[14];//为了便于判断桌子上的牌是否有相同的,增加一个数组用于判断
int i;
//初始化队列
q1.head=0;
q1.tail=0;
q2.head=0;
q2.tail=0;
//初始化栈
s.top=-1;
//初始化用来标记的数组
for(i=0; i<=13; i++)
book[i]=0;
//假设初期每个人手中仅有 6 张牌,每个人拥有的牌都是随机的,但都在 1-13 之间
for(i=1; i<=6; i++) {
q1.data[q1.tail]=rand()%13+1;
q1.tail++;
}
for(i=1; i<=6; i++) {
q2.data[q2.tail]=rand()%13+1;
q2.tail++;
}
//仅当其中一个人没有牌时,游戏结束
while(q1.head<q1.tail && q2.head<q2.tail ) {
showCard(&q2, book, &s);//小李出牌
showCard(&q1, book, &s);//小王出牌
}
//游戏结束时,输出最后的赢家以及手中剩余的牌数
if(q2.head==q2.tail) {
printf("小李赢\n");
printf("手中还有:%d 张牌",q1.tail-q1.head);
} else {
printf("小王赢\n");
printf("手中还有:%d 张牌",q2.tail-q2.head);
}
return 0;
}

运行结果

1
2
小王赢
手中还有:7 张牌

五 参考

  • C语言中文网—扑克牌游戏