最强C++控制台扫雷版本(难易可选,自带新手易学游戏框架)

本文分享了使用C++编写的扫雷游戏代码,游戏难度可调,适合初学者学习。详细分析见链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

废话不多说,直接上代码,看官们先去试试,然后回来看分析
分析文章见:
https://blog.youkuaiyun.com/ycczbasd/article/details/103511457

#include <iostream>
#include <windows.h>
#include <time.h>
#include <vector>
using namespace std;

void GameInit();
void GameRun();
void GameDraw();
void GameLogic();
void GameEnd();
void SetThunderPosition();
void CountThunder();
void Spread(int index);
void ShowCompleteMap();

HANDLE hOutput;
COORD coord = { 0,0 };


int MapW = 0;
int MapH = 0;
int MapS = 0;
//0空白;
//1代表该位置附近有1颗雷,最多有8颗
//9代表该位置有雷
//-9代表该位置的雷被排除了
char* Map;    //地图动态数组
char* DisplayMap;//屏幕展示出来的地图
int* ThunderIndex; //雷位置索引动态数组

int difficult = 0;
bool isRun = true;
int ThunderNum = 0;  //雷数量

//Game光标
int CursonX = 0;
int CursonY = 0;

char pic[][3] = { "□","①","②","③","④","⑤","⑥","⑦","⑧","⊕","▶","■","↖" };

//游戏状态 0:开始场景  1:难度选择场景 2:游戏运行场景 3:胜利场景 4:失败场景 5:游戏结束场景 
int status = 0;

void main()
{
	int input;

	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);

	//隐藏缓冲区的光标
	CONSOLE_CURSOR_INFO cci;
	cci.bVisible = 0;
	cci.dwSize = 1;
	SetConsoleCursorInfo(hOutput, &cci);

	while (isRun)
	{
		system("cls");
		if (status == 0)
		{
			cout << "请选择:\n" << "1.开始\n" << "2.退出\n" << "请选择:" << endl;
			cin >> input;
			if (input == 1)
				status = 1;
			if (input == 2)
				status = 5;
		}
		else if (status == 1)
		{
			cout << "难度选择:\n" << "1.简单\n" << "2.容易\n" << "3.困难\n" << "4.退出\n" << "请选择:" << endl;
			cin >> input;
			if (input >= 1 && input <= 3)
			{
				status = 2;
				difficult = input;
				GameInit();
			}
			if (input == 4)
				status = 5;
		}
		else if (status == 2)
		{
			GameRun();
		}
		else if (status == 3)  //win界面,可以扩展
		{
			ShowCompleteMap();
			cout << "          You Win!!!!!!!";
			Sleep(2000);
			status = 5;
		}
		else if (status == 4) //failed界面,可以扩展
		{
			ShowCompleteMap();
			cout << "          You Failed!!!!!!!";
			Sleep(2000);
			status = 5;
		}
		else if (status == 5) //结束界面,可以扩展
		{
			isRun = false;
			GameEnd();
		}
	}

	system("pause");
}

void GameInit()
{
	if (difficult == 1)
	{
		MapW = 11;
		MapH = 11;
		ThunderNum = 15;
	}
	else if (difficult == 2)
	{
		MapW = 15;
		MapH = 15;
		ThunderNum = 23;
	}
	else if (difficult == 3)
	{
		MapW = 19;
		MapH = 19;
		ThunderNum = 31;
	}
	MapS = MapW * MapH;
	//初始化地图
	Map = new char[MapS];
	memset(Map, 0, MapS);
	DisplayMap = new char[MapS];
	memset(DisplayMap, 11, MapS);
	ThunderIndex = new int[ThunderNum];
	SetThunderPosition();
	CountThunder();
}

void GameRun()
{
	GameDraw();
	GameLogic();
}

void GameDraw()
{
	for (int i = 0; i < MapS; ++i)
	{
		if (CursonX + CursonY * MapW == i)
			cout << pic[12];
		else
			cout << pic[DisplayMap[i]];
		if (i % MapW == MapW - 1)
			cout << endl;
	}
	/*for (int i = 0; i < MapH; ++i)
	{
		coord.Y = i;
		SetConsoleCursorPosition(hOutput, coord);
		for (int j = 0; j < MapW; ++j)
		{
			if (CursonX == j && CursonY == i)
				cout << pic[12];
			else
				cout << pic[DisplayMap[i]];
		}
	}
	Sleep(50);*/
}

void GameLogic()
{
	//输赢判断
	int n = 0; //统计雷个数 
	for (int i = 0; i < MapS; ++i)
	{
		if (DisplayMap[i] != Map[i])
		{
			n++;
			if (n > ThunderNum)
				break;
		}
	}
	if (n == ThunderNum)  //赢了
	{
		status = 3;
		return;
	}
	//光标移动
	if (GetAsyncKeyState(VK_LEFT) & 0x8000 && CursonX > 0)
	{
		CursonX--;
	}
	else if (GetAsyncKeyState(VK_RIGHT) & 0x8000 && CursonX < MapW - 1)
	{
		CursonX++;
	}
	else if (GetAsyncKeyState(VK_UP) & 0x8000 && CursonY > 0)
	{
		CursonY--;
	}
	else if (GetAsyncKeyState(VK_DOWN) & 0x8000 && CursonY < MapH - 1)
	{
		CursonY++;
	}
	else if (GetAsyncKeyState(VK_SPACE) & 0x8000)
	{
		//只能在未展示的地图上按键
		int index = CursonX + CursonY * MapW;
		if (DisplayMap[index] == 11)
		{
			if (Map[index] == 0)
				Spread(index);
			else if (Map[index] > 0 && Map[index] < 9)
				DisplayMap[index] = Map[index];
			else if (Map[index] == 9)
			{
				status = 4;
				return;
			}
		}
	}
}

void GameEnd()
{
	if (Map != nullptr)
	{
		delete[]Map;
		Map = nullptr;
	}
	if (ThunderIndex != nullptr)
	{
		delete[]ThunderIndex;
		ThunderIndex = nullptr;
	}
}

void SetThunderPosition()
{
	int num = 0;
	//srand((unsigned)time(0));
	vector<int> vPosition;
	for (int i = 0; i < MapS; ++i)
	{
		vPosition.push_back(i);
	}
	while (num < ThunderNum)
	{
		int index = rand() % vPosition.size();
		Map[vPosition[index]] = 9;
		ThunderIndex[num] = vPosition[index];
		vPosition.erase(vPosition.begin() + index);
		num++;
	}
}
void CountThunder()
{
	const int dir[8] = { -1, -1 - MapW, -MapW, 1 - MapW, 1, 1 + MapW, MapW, -1 + MapW };
	for (int i = 0; i < ThunderNum; ++i)
	{
		for (int j = 0; j < 8; ++j)
		{
			int CountPosition = dir[j] + ThunderIndex[i];
			if (CountPosition < 0 || CountPosition >= MapS)
				continue;
			int Difference_W = CountPosition % MapW - ThunderIndex[i] % MapW;
			int Difference_H = CountPosition / MapW - ThunderIndex[i] / MapW;
			if (Difference_W >= -1 && Difference_W <= 1 && Difference_H >= -1 && Difference_H <= 1)
			{
				if (Map[CountPosition] == 9)
					continue;
				Map[CountPosition]++;
			}
		}
	}
}

//扩散
void Spread(int index)
{
	const int dir[8] = { -1, -1 - MapW, -MapW, 1 - MapW, 1, 1 + MapW, MapW, -1 + MapW };
	vector<int> vecSpread;  //没学过的可以先看看,或者用长度大一点的数组
	vecSpread.push_back(index);
	DisplayMap[index] = 0;
	for (int i = 0; i < vecSpread.size(); ++i)
	{
		if (DisplayMap[vecSpread[i]] != 0)
			continue;
		for (int j = 0; j < 8; ++j)
		{
			int temp_index = vecSpread[i] + dir[j];
			if (temp_index < 0 || temp_index >= MapS) //越界
				continue;
			int Difference_W = temp_index % MapW - vecSpread[i] % MapW;
			int Difference_H = temp_index / MapW - vecSpread[i] / MapW;
			if (Difference_W >= -1 && Difference_W <= 1 && Difference_H >= -1 && Difference_H <= 1) //相邻判断
			{
				if (DisplayMap[temp_index] != 11) //记录过的无法再记录
					continue;
				if (Map[temp_index] >= 0 && Map[temp_index] <= 8)
				{
					vecSpread.push_back(temp_index);
					DisplayMap[temp_index] = Map[temp_index];
				}
			}
		}
	}
}

void ShowCompleteMap()
{
	for (int i = 0; i < MapS; ++i)
	{
		if (CursonX + CursonY * MapW == i)
			cout << pic[12];
		else
			cout << pic[Map[i]];
		if (i % MapW == MapW - 1)
			cout << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值