【啊哈!算法】系列文章目录
需求介绍
星期天小哼和小哈约在一起玩桌游,他们正在玩一个非常古怪的扑克游戏——“小猫钓鱼”。游戏的规则是这样的:将一副扑克牌平均分成两份,每人拿一份。小哼先拿出手中的第一张扑克牌放在桌上,然后小哈也拿出手中的第一张扑克牌,并放在小哼刚打出的扑克牌的上面,就像这样两人交替出牌。出牌时,如果某人打出的牌与桌上某张牌的牌面相同,即可将两张相同的牌及其中间所夹的牌全部取走,并依次放到自己手中牌的末尾。当任意一人手中的牌全部出完时,游戏结束,对手获胜。(牌面为1~9)
数据输入: 第一行分别为为小哼、小哈手中牌的数目,第二行是小哼手中的牌,第三行是小哈手中的牌,不同牌之间用空格隔开。
数据输出: 第一行是胜利者,如小哼胜,则为“小哼win”;如小哈胜,则为“小哈win”;
第二行是胜利者手中的牌,中间用空格隔开;
第三行是桌上的牌,中间用空格隔开。
思路分析
我们先来分析一下这个游戏有哪几种操作。小哼有两种操作,分别是出牌和赢牌。这恰好对应队列的两个操作,出牌就是出队,赢牌就是入队。小哈的操作和小哼是一样的。而桌子就是一个栈,每打出一张牌放到桌上就相当于入栈。当有人赢牌的时候,依次将牌从桌上拿走,这就相当于出栈。那如何解决赢牌的问题呢?赢牌的规则是:如果某人打出的牌与桌上的某张牌相同,即可将两张牌以及中间所夹的牌全部取走。那如何知道桌上已经有哪些牌了呢?最简单的方法就是枚举桌上的每一张牌,当然也有更好的办法,就是用一个数组来记录桌上有哪些牌。因为牌面只有 1~9,因此只需开一个大小为 10 的数组来记录当前桌上已经有哪些牌面就可以了。
OK,小结一下,我们需要两个队列、一个栈来模拟整个游戏。
C语言代码
#include <stdio.h>
struct queue {
int data[1000];
int head;
int tail;
};
struct stack {
int data[20];
int top;
};
int book[20];
void chupai(struct queue *q, struct stack *s) {
int t;
t = q->data[q->head]; //小哼出一张牌
q->head++;
// 判断小哼当前打出的牌是否能赢得桌上的牌
if(book[t]==0) {
//表明桌上没有牌面为t的牌
//小哼此轮没有赢牌
s->top++;
s->data[s->top] = t; //再把打出的牌放到桌上,即入栈
book[t] = 1; //标记桌上现在已经有牌面为t的牌
}
else {
//小哼此轮可以赢牌
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--; //栈中少了一张牌,所以栈顶要减1
}
//收起最后一张一样的牌,并将标志置0
book[s->data[s->top]]=0; //取消标记
q->data[q->tail] = s->data[s->top]; ///依次放入队尾
q->tail++;
s->top--; //栈中少了一张牌,所以栈顶要减