C++模拟扑克过五关

本文介绍了使用C++ STL实现扑克过五关游戏模拟的过程,包括洗牌、发牌、收牌策略的逻辑。通过队列和映射处理牌的存储和数值映射,使用deque存储五关,利用逻辑变量处理重复收牌检查。代码中还存在对于不同收牌方式的优先级问题,有待优化以实现更真实的随机性。
摘要由CSDN通过智能技术生成

起因

一日见家人无聊排扑克过五关以消磨时间,便萌生这样的想法:打扑克过五关确实不失为消磨时间的一个好方法,但要自己动手就很麻烦,而且感觉这个游戏只是这么玩,确实是很智障,何不自己动手写个代码模拟呢?又能练练自己的编程能力。于是便有了这篇文章

实现工具

C++ STL 控制台程序

代码实现需要考虑的一些问题

我们把整个过程进行抽象概括,首先是洗牌,然后是不停的发牌,看看是否可以收牌,如果自己手上的牌发完这一局便失败了。下面是细节阐述:
(1)发牌这个过程显然可以用一个队列去存储,发牌便是出队的过程,收牌便是入队的过程。源代码中为:queue<unsigned int>deal_cards
(2)在计算的过程中,实际上我们将11,12,13(J,Q,K)视为10来计算,也就是说数值大小可能与其面值不同,这里我们借助一个映射map来处理:

map<unsigned int, unsigned int>value;
·
·
·
for (unsigned int i = 1; i <= 10; i++) {
		value[i] = i;
	}
	value[11] = value[12] = value[13] = 10;

(3)五关的存储:这里的存储结构不能选择 queue 而应该是 deque 原因很直观,我们有时从队头收牌,有时从队尾收牌,有时同时从队头队尾收牌。源代码中选择用 vector<deque>card_group 进行存储。这里有一个难点,我们首先得初始化这个向量,使其大小为5,在后续的操作中,切记vector[ ]中[ ]只能是访问,不能进行修改!!要修改我们只能借助迭代器 vector<deque>::iterator iter 进行后续修改
(4)前两轮不会收牌,我们可以直接先进行前两轮,无需任何判断
(5)第三轮起,开始判断是否需要收牌。这一组的牌数为0时,直接跳到下一组;牌数为1或2时,直接发一张牌。牌数大于2时,这时候就要小心了。要两个需要注意的地方:一是前面说到的不同的收牌方式,共三种:第一张+最后一张+发的牌;第一张+第二张+发的牌;最后一张+倒数第二张+发的牌;二是要是我们进行计算后,发现确实能收牌,我们将牌收完之后,就直接到下一组了吗?不不不,或许我们还能再收一次牌,发一张牌,收6张牌的情况并不少见吧?这才是整个模拟过程中最有意思的一部分。这里我的解决方案是引进一个逻辑变量 repeat_inspect 来指示我们是否需要进行重复检查。具体用法见源代码。

源代码

#include<iostream>
#include<functional>
#include<time.h>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
#include<Windows.h>
#include<deque>
#include<iterator>

using namespace std;

queue<unsigned int>deal_cards;
vector<deque<unsigned int>>card_group;
map<unsigned int, unsigned int>value;
void gotoxy(short x, short y)
{
	HANDLE hCONSOLE = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD coordScreen = { x,y };
	SetConsoleCursorPosition(hCONSOLE, coordScreen);
}
void display()
{
	system("cls");
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < card_group[i].size(); j++) {
			gotoxy(2 + i * 5, (j + 1) * 2);
			cout << card_group[i].at(j);
		}
	}
}
void initialization()
{
	for (unsigned int i = 1; i <= 10; i++) {
		value[i] = i;
	}
	value[11] = value[12] = value[13] = 10;
	vector<unsigned int>temp;
	for (unsigned int i = 1; i <= 13; i++)
	{
		for (int j = 1; j <= 4; j++) {
			temp.push_back(i);
		}
	}
	srand((unsigned int)time(0));
	random_shuffle(temp.begin(), temp.end());
	for (int i = 0; i < temp.size(); i++) {
		deal_cards.push(temp[i]);
	}
	//deal_cards.pop();
}
void run()
{
	vector<deque<unsigned int>>::iterator iter;
	for (int i = 0; i < 5; i++) {
		deque<unsigned int>temp;
		temp.push_back(deal_cards.front());
		deal_cards.pop();
		card_group.push_back(temp);
	}
	display();
	Sleep(1000);

	for (iter = card_group.begin(); iter != card_group.end(); iter++) {
		(*iter).push_back(deal_cards.front());
		deal_cards.pop();
	}
	display();
	Sleep(1000);

	int group = 0;
	unsigned int card;
	bool repeat_inspect=false;
	while (!deal_cards.empty()) {
		iter = card_group.begin();
		iter += group;
		switch ((*iter).size()) {
		case 0:
			repeat_inspect = false;
			group = (group + 1) % 5;
			break;
		case 1:
			if (!repeat_inspect) {
				(*iter).push_back(deal_cards.front());
				deal_cards.pop();
				display();
				Sleep(50);
			}
			else {
				repeat_inspect = false;
			}
			group = (group + 1) % 5;
			break;
		case 2:
			if (repeat_inspect) {
				repeat_inspect = false;
			}
			else {
				card = deal_cards.front();
				deal_cards.pop();
				if ((value[card] + value[(*iter).front()] + value[(*iter).back()]) % 10 == 0) {
					deal_cards.push((*iter).front());
					(*iter).pop_front();
					deal_cards.push((*iter).front());
					(*iter).pop_front();
					deal_cards.push(card);
				}
				else
				{
					(*iter).push_back(card);
				}				
				display();
				Sleep(50);
			}
			group = (group + 1) % 5;
			break;
		default:
			if (repeat_inspect) {
				if ((value[(*iter).front()] + value[(*iter).at(1)] + value[(*iter).back()]) % 10 == 0) {
					deal_cards.push((*iter).front());
					(*iter).pop_front();
					deal_cards.push((*iter).front());
					(*iter).pop_front();
					deal_cards.push((*iter).back());
					(*iter).pop_back();
				}
				else if ((value[(*iter).front()] + value[(*iter).at((*iter).size()-2)] + value[(*iter).back()]) % 10 == 0) {
					deal_cards.push((*iter).front());
					(*iter).pop_front();
					deal_cards.push((*iter).back());
					(*iter).pop_back();
					deal_cards.push((*iter).back());
					(*iter).pop_back();
				}
				else {
					repeat_inspect = false;
					group = (group + 1) % 5;
				}
			}
			else {
				card = deal_cards.front();
				deal_cards.pop();
				if ((value[card] + value[(*iter).front()] + value[(*iter).back()]) % 10 == 0) {
					repeat_inspect = true;
					deal_cards.push((*iter).front());
					(*iter).pop_front();
					deal_cards.push((*iter).back());
					(*iter).pop_back();
					deal_cards.push(card);
				}
				else if ((value[card] + value[(*iter).front()] + value[(*iter).at(1)]) % 10 == 0) {
					repeat_inspect = true;
					deal_cards.push((*iter).front());
					(*iter).pop_front();
					deal_cards.push((*iter).front());
					(*iter).pop_front();
					deal_cards.push(card);
				}
				else if ((value[card] + value[(*iter).back()] + value[(*iter).at((*iter).size() - 2)]) % 10 == 0) {
					repeat_inspect = true;
					deal_cards.push((*iter).back());
					(*iter).pop_back();
					deal_cards.push((*iter).back());
					(*iter).pop_back();
					deal_cards.push(card);
				}
				else {
					(*iter).push_back(card);
					group = (group + 1) % 5;
					display();
					Sleep(50);
				}
			}
			break;
		}
		
	}
	gotoxy(100, 60);
}
int main()
{
	initialization();
	run();
}

代码不足之处

由于技术水平,我无法完美解决一种情况:发一次牌后发现有两种不同的收牌方式。源代码中我是按一定顺序判断收牌的,所有会存在优先级。如果真的要模拟人的那种收牌的随机性,存储上将是个很大的考验。当然了,这对你们这些大佬来说,应该也不会是难事吧[doge]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值