小猫钓鱼卡牌游戏---栈、队列的应用

游戏规则

A和B两个同学玩简单的纸牌游戏,每人手里有n张牌,两人轮流出牌并依次排列在桌面上,每次出掉手里的第1张牌,出牌后如果发现桌面上有跟刚才打出的牌的数字相同的牌,则把从相同的那张牌开始的全部牌按次序放在自己手里的牌的末尾。当一个人手中的牌先出完时,游戏结束,对方获胜。
如n为5,每人手中有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;
依次类推,直到某人先出完牌为止,则对方是胜者。

设计思路

玩家手中的牌是按出牌顺序存储在队列中,队头出牌,队尾收牌;桌面上的牌是按玩家出牌顺序存储在栈结构中。

游戏开始,玩家出牌,即该玩家的手牌队头元素出队,然后到桌面栈中从栈顶向下依次与该玩家出的牌进行对比比较;若有相同的牌,即之前有玩家出过相同的牌,那么则按自栈顶向下的顺序直到相同牌处,将这些牌出栈,并将这些出栈牌逆序插入该出牌玩家的手牌队尾;如果没有相同牌,那么该玩家出的牌入桌面栈。接着下一玩家出牌,仍是按上述的规则进行,轮流往复,直到其中一名玩家的手牌队列为空,该玩家获胜。

综上,无论是玩家手牌队列还是桌面卡牌栈,都要进行多次的增删,所以都采用链式结构。

相关代码
//主程序
int main() {
	//设置游戏循环标识、轮流出牌标识、初始化时间种子
	int GameStart = 1, Skip = 0, NOG = 0;
	//设置时间种子,用于产生随机数作为卡牌值
	srand((int)time(0));

	//显示游戏介绍
	Show_Instruction();

	cout << "输入1开始游戏,输入0退出-----》" << endl;
	cin >> GameStart;
	while (GameStart == 1) {
		cout << "游戏开始!" << endl;
		//默认每人手中初始有十张牌,并初始化玩家手牌链队及桌面卡牌链栈
		int A[Card_Number], B[Card_Number];
		LinkQueue<int> A_Card;
		LinkQueue<int> B_Card;
		LinkStack<int> Table;

		//随机生成两组卡牌,卡牌范围默认是[1-9]
		cout << "正在发牌,请稍后......" << endl;
		//生成卡牌函数
		Deal_Card(A);
		Sleep(4 * 1000);
		Deal_Card(B);

		//将数组元素入链队
		for (int i = 0; i < Card_Number; i++) {
			A_Card.EnQueue(A[i]);
			B_Card.EnQueue(B[i]);
		}

		//将此时玩家手中的牌显示
		cout << "发牌后,两名玩家的手牌分别是:" << endl;
		cout << "A玩家:";
		A_Card.OutQueue();
		cout << endl << "B玩家:";
		B_Card.OutQueue();
		cout << endl;


		while (!A_Card.Empty() && !B_Card.Empty()) {
			Sleep(4 * 1000);

			NOG++;
			cout << endl;
			cout << endl << "第" << NOG << "次玩家出牌==============================" << endl;
			cout << "A玩家手牌:";
			A_Card.OutQueue();
			cout << endl << "B玩家手牌:";
			B_Card.OutQueue();
			cout << endl << "桌面上的牌:";
			Table.ReOut();
			cout << endl;

			LinkStack<int> Temp;//初始化一个临时链栈,暂时存储从桌面拿出的牌,重新放入玩家手中,保证按照之前出牌顺序收入玩家手中
			if (Skip == 1) {//默认A玩家先出牌
				int tempA = A_Card.DeQueue();//A玩家出牌
				cout << "此时A玩家出牌:" << tempA << endl;

				int siteA = Table.FindNum(tempA);//确定是否之前已经出过了相同的牌及位置
				if (siteA != 0) {//如果之前出过相同的牌
					cout << "回收桌面上,与玩家出牌相同的牌及相同牌之间的所有牌" << endl;
					for (int i = 0; i < siteA; i++)//循环将两张相同牌及之间所有的牌从桌面拿出
						Temp.Push(Table.Pop());
					for (int j = 0; j < siteA; j++)//并将拿出的牌列按之前的出牌顺序收回到A玩家的牌底
						A_Card.EnQueue(Temp.Pop());
					A_Card.EnQueue(tempA);
					Temp.~LinkStack();//销毁临时链栈
				}
				else {//如果之前没有出过相同的牌
					cout << "不回收" << endl;
					Table.Push(tempA);//将牌放到桌面
				}
				Skip--;//改变Skip参数,轮到另一玩家出牌
			}
			else {
				int tempB = B_Card.DeQueue();//B玩家出牌
				cout << "此时B玩家出牌:" << tempB << endl;

				int siteB = Table.FindNum(tempB);//确定是否之前已经出过了相同的牌及位置
				if (siteB != 0) {//如果之前出过相同的牌
					cout << "回收桌面上,与玩家出牌相同的牌及相同牌之间的所有牌" << endl;
					for (int i = 0; i < siteB; i++)//循环将两张相同牌及之间所有的牌从桌面拿出
						Temp.Push(Table.Pop());
					for (int j = 0; j < siteB; j++)//并将拿出的牌列按之前的出牌顺序收回到B玩家的牌底
						B_Card.EnQueue(Temp.Pop());
					B_Card.EnQueue(tempB);
					Temp.~LinkStack();//销毁临时链栈
				}
				else {//如果之前没有出过相同的牌
					cout << "不回收" << endl;
					Table.Push(tempB);//将牌放到桌面
				}
				Skip++;//改变Skip参数,轮到另一玩家出牌
			}
		}

		cout << endl;
		if (A_Card.Empty())
			cout << "A玩家最先出完手中的卡牌,A玩家获胜!" << endl;
		else
			cout << "B玩家最先出完手中的卡牌,B玩家获胜!" << endl;

		cout << endl << "是否继续游戏(输入1继续,输入0退出)-----》" << endl;
		cin >> GameStart;
	}

	return 0;
}
运行截图

在程序运行后,会先显示游戏的相关介绍
在这里插入图片描述

确认开始游戏后在这里插入图片描述

备注

在主函数中的Deal_Card(A),Table.FindNum(tempA)调用的函数均是单独函数,如若需要请点击这里下载,有分享的完整项目代码文件。
这是博主在学习过程中编写的,可能会存在瑕疵,分享仅供参考,望大佬们评判指点!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值