数据结构16: 扑克牌游戏

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


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

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

设计思路

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

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

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

实现代码

#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; }
运行结果:
小王赢
手中还有:7 张牌

 

转载于:https://www.cnblogs.com/ciyeer/p/9031558.html

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.纸牌游戏 任务:编号为1-52张牌,正面向上,从第2张开始,以2为基数,是2的倍数的牌翻一次,直到最后一张牌;然后,从第3张开始,以3为基数,是3的倍数的牌翻一次,直到最后一张牌;然后…从第4张开始,以4为基数,是4的倍数的牌翻一次, 直到最后一张牌;...再依次5的倍数的牌翻一次,6的,7的 直到 以52为基数的 翻过,输出:这时正面向上的牌有哪些? 题目比较简单。但用了MFC的一些知识,实现了图形化,比较形象。 2.哈弗曼压缩 实现哈弗曼压缩及解压缩功能,并计算压缩前后文件占用空间比 模型建立与题目分析 压缩: 以二机制可读形式打开源文件,以二进制可写形式打开压缩目标文件。每次从源文件读取八个比特(一字节),作为一个ASCII码,并统计所有出现的字节的频率,将字节作为哈夫曼数的叶子结点插入到一个链表中。然后根据链表建立哈夫曼树,按照哈夫曼算法对所有出现的字节编码。然后重新从头开始读源文件,每次读入一字节,从哈夫曼树相应叶子结点移到树的根结点,在找的过程中,把其哈夫曼编码存入一个栈,把栈中所有元素(0或1)写到缓冲区,如果缓冲区比特数到8了,则将缓冲区的8个比特(一个字节)写入压缩文件。如果最后缓冲区不到8比特,则在低位补零,补齐8位后写入压缩文件。 解压: 以二进制可读形式打开解压文件,以二进制可写形式打开解压目标文件。每次从解压文件读一个字节,放入缓冲区,然后从缓冲区每次读一个比特。在建立的哈夫曼树中,从根结点开始,取出的比特为0则取左孩子,为1取右孩子,直至到叶子结点,把叶子结点的字节(ASCII码)写入解压目标文件。读到缓冲区为空时,再读入一个字节,重复上述操作,直到读完压缩文件。 模型实质: 以二进制读取文件。从源文件每次读一个字节(8比特),并统计所有出现字节的频率,根据频率对所有字节以频率作为权值建立哈夫曼树,对每个字节重新编码。根据新的编码进行编码译码。 算法设计与分析 如果已知出现字符的出现频率,将较短的比特串分给高频字符,将较长的比特串分给低频字符,则会到压缩文件的目的。哈夫曼编码就是利用这一点,以字符作为叶子结点,以其频率作为权值,建立最优二叉树。 一 下面先重点讨论一下建立哈夫曼数的算法。哈夫曼算法: 根据给定叶子结点及其权值(这里即字符及其频率)构成二叉树的集合,每个叶子结点作为一棵树的根结点。 在二叉树集合中选取根结点权值最小的树作为左右子树构造新的二叉树,且新二叉树的权值为左右子树权值之和。 从二叉树集合中删除这两棵树,将新构造的树加入集合 4 . 重复2,3,直至二叉树集合中只有一棵树。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值