小猫钓鱼纸牌游戏

小猫钓鱼纸牌游戏

问题描述及要求
A和B两个同学玩简单的纸牌游戏,每人手里有n张牌,两人轮流出牌并依次排列在桌面上,每次出掉手里的第1张牌,出牌后如果发现桌面上有跟刚才打出的牌的数字相同的牌,则把从相同的那张牌开始的全部牌按次序放在自己手里的牌的末尾。当一个人手中的牌先出完时,游戏结束,对方获胜。
如n为5,A手里的牌依次为2 3 5 6 1,B手里的牌依次为1 5 4 2 9;
A出2;
B出1;
A出3;
B出5;
A出5,发现前面有一张5,则把两个5都拿掉,这时他手里有6 1 5 5;
桌子上的牌依次为2 1 3;
B出4;
A出6;
B出2,发现前面有一张2,则把从2开始的牌全部拿掉,这时他手里有9 2 1 3 4 6 2;
桌子上没有牌了;
A出1;
B出9;
A出5;
B出2;
依次类推,直到某人先出完牌为止,则对方是胜者。
编写程序,利用栈和队列,判断谁是胜者。

思路:
首先构建一个栈和队列的类函数。然后运用这两个数据结构模拟小猫钓鱼游戏的过程,这也是解决该题目的关键步骤。运用栈模拟牌堆,运用队列模拟A和B的手牌,一开始读入俩人手牌。游戏开始:以下A为所带表队列,B为B所代表队列,C为牌堆所代表的栈,再用一个book数组标记C中已出现的牌。判断A是否为空,若空则B获胜,之后A出队一张牌t,如果book中已标记该牌已存于C则该牌入队A,从C中出栈一张牌入队A循环直到出栈的牌等于t,将这最后一个牌入队于A。再判断B是否为空,若空则A获胜,之后B出队一张牌t,如果book中已标记该牌已存于C则该牌入队B,从C中出栈一张牌入队B循环直到出栈的牌等于t,将这最后一个牌入队于B。循环直到某人获胜。

Code

#include<iostream>
#include<string>
#include<map>
#include<algorithm>
#include<memory.h>
#define pii pair<int,int>
#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const int Max = 1e3 + 5;
int book[Max];

class cir_queue
{
   
public:
	void enqueue(int x)
	{
   
		if ((rear + 1) % Max == front)
		{
   
			cout << "溢出" << endl;return;
		}
		rear = (rear + 1) % Max;
		data[rear] = x;
	}
	int dequeue()
	{
   
		if (rear == front) 
		{
   
			cout << "下溢1" << endl;return 0;
		}
		front = (front + 1) % Max;
		return data[front];
	}
	int get_front()
	{
   
		if (rear == front) {
    cout << "下溢2" << endl;return 0; }
		return data[(front + 1) % Max];
	}
	bool is_empty()
	{
   
		if (front == rear)return true;
		else return false;
	}
private:
	int data[Max] = {
   0,0}, front = 0, rear = 0;
};

class stack
{
   
public:
	void push(int a)
	{
   
		if (length >= Max)cout << "溢出" << endl;
		data[++length] = a;
	}
	int gettop()
	{
   
		return data[length];
	}
	int pop()
	{
   
		if (length == 0)
		{
   
			cout << "下溢" << endl;
		}
		return data[length--];
	}
	bool is_empty()
	{
   
		if (length == 0)return true;
		else return false;
	}
private:
	int data[Max], length = 0;
};

void project()
{
   
	cir_queue q1, q2;
	stack sta;
	cout << "请输入每人手里的数字个数" << endl;
	int n;cin >> n;
	cout << "请输入每人手里的牌" << endl;
	for (int i = 1;i <= n;i++)
	{
   
		int t;cin >> t;
		q1.enqueue(t);
	}
	for (int i = 1;i <= n;i++)
	{
   
		int t;cin >> t;
		q2.enqueue(t);
	}
	int f;
	while (1)
	{
   
		if (q1.is_empty()) {
    cout<<"player_B win"<<endl; break; }
		else
		{
   
			int t = q1.get_front();
			if (book[t])
			{
   
				q1.dequeue();
				q1.enqueue(t);
				int q = sta.pop();
				while (q != t)
				{
   
					book[q] = 0;
					q1.enqueue(q);
					q = sta.pop();
				}
				q1.enqueue(q);
				book[t] = 0;
			}
			else
			{
   
				sta.push(q1.dequeue());
				book[t] = 1;
				if (q1.is_empty()) {
   
					cout << "player_B win" << endl;break;
				}
			}
		}
		if (q2.is_empty()) {
    cout<<"player_A win"; break; }
		else
		{
   
			int t = q2.get_front();
			if (book[t])
			{
   
				int q = sta.pop();
				q2.dequeue();
				q2.enqueue(t);
				while (q != t)
				{
   
					book[q] = 0;
					q2.enqueue(q);
					q = sta.pop();
				}
				q2.enqueue(q);
				book[t] = 0;
			}
			else
			{
   
				sta.push(q2.dequeue());
				book[t] = 1;
				if (q2.is_empty()) {
   
					cout << "player_A win" << endl;break;
				}
			}
		}

	}
}

int main()
{
   
	project();
}
全部评论
几天前在家看到这题,没看解析便睡了。次日坐火车在火车上想了一会儿,今天终于实现了。感觉细节还挺多的,我也没能耐。我想的是用两个循环队列代表A和B,每个队列数组大小是两者之和;用一个大小为十的数组作为牌堆,每个元素都是以索引值作为牌值、具有前后指针的结构。当A、B队列依次出队,按数值确定索引,存入大小为十的数组,当数值判断相应索引位置元素非空,则从该索引位置开始,通过后指针将该位置及之后所有元素都清空,并将所有被删元素值传给出牌队列。直到某队列为空退出循环,该队列获胜。
点赞 回复
分享
发布于 2023-03-01 23:41 黑龙江

相关推荐

1 2 评论
分享
牛客网
牛客企业服务