基于c++控制台的扫雷游戏

 

Screen   类用于与控制台交互

gotoxy(short x, short y)跳转到控制台的指定位置

void Init() 获取控制台 句柄

bool changeColor(WORD color)变更颜色

/*
0 = 黑色       8 = 灰色搜索
1 = 蓝色       9 = 淡蓝色
2 = 绿色       A = 淡绿色
3 = 浅绿色     B = 淡浅绿色
4 = 红色       C = 淡红色
5 = 紫色       D = 淡紫色
6 = 黄色       E = 淡黄色
7 = 白色       F = 亮白色


FOREGROUND_BLUE	字体颜色:蓝	1
FOREGROUND_GREEN	字体颜色:绿	2
FOREGROUND_RED	字体颜色:红	4
FOREGROUND_INTENSITY	前景色高亮显示	8
BACKGROUND_BLUE	背景颜色:蓝	16
BACKGROUND_GREEN	背景颜色:绿	32
BACKGROUND_RED	背景颜色:红	64
BACKGROUND_INTENSITY	背景色高亮显示	128
*/
class Screen {
public:
	void gotoxy(short x, short y) {
		COORD pos;
		pos.X = x;
		pos.Y = y;
		SetConsoleCursorPosition(hOut, pos);
	};
	void Init()
	{
		hOut = GetStdHandle(STD_OUTPUT_HANDLE);
		assert(hOut != 0);
	}
	bool changeColor(WORD color)
	{
		SetConsoleTextAttribute(hOut,color);
		return true;
	}
	static Screen* instance() {
		static Screen screen;
		return &screen;
	}
private:

	Screen() {
	}
	Screen(const Screen&);
	const Screen& operator=(const Screen&);
	HANDLE hOut;
	INPUT_RECORD inRec;/*  返回数据记录 */
	DWORD numRead; /*  返回已读取的记录数 */
};

  SL扫雷类

Init()初始化窗口高度宽度和类的数量,生成表格

InitTable() 有雷的地方值为-1,其它为周边雷的个数

DrawIn() 画窗口内部格子

DrawOut()画窗口边框

Run()运行游戏

bfs(int h,int w)对于值为0的格子,宽度搜索其周边的格子直到非0

show(int h,int w)当用户点击单击位置h,w 时被调用

完整代码:

#include<Windows.h>
#include<iostream>
#include<cassert>
using std::cout;
using std::cin;
#include<vector>
#include<time.h>
#include<conio.h>
#include<queue>
using std::pair;
using std::make_pair;
using std::queue;
using std::vector;

/*
0 = 黑色       8 = 灰色搜索
1 = 蓝色       9 = 淡蓝色
2 = 绿色       A = 淡绿色
3 = 浅绿色     B = 淡浅绿色
4 = 红色       C = 淡红色
5 = 紫色       D = 淡紫色
6 = 黄色       E = 淡黄色
7 = 白色       F = 亮白色


FOREGROUND_BLUE	字体颜色:蓝	1
FOREGROUND_GREEN	字体颜色:绿	2
FOREGROUND_RED	字体颜色:红	4
FOREGROUND_INTENSITY	前景色高亮显示	8
BACKGROUND_BLUE	背景颜色:蓝	16
BACKGROUND_GREEN	背景颜色:绿	32
BACKGROUND_RED	背景颜色:红	64
BACKGROUND_INTENSITY	背景色高亮显示	128
*/
class Screen {
public:
	void gotoxy(short x, short y) {
		COORD pos;
		pos.X = x;
		pos.Y = y;
		SetConsoleCursorPosition(hOut, pos);
	};
	void Init()
	{
		hOut = GetStdHandle(STD_OUTPUT_HANDLE);
		assert(hOut != 0);
	}
	bool changeColor(WORD color)
	{
		SetConsoleTextAttribute(hOut,color);
		return true;
	}
	static Screen* instance() {
		static Screen screen;
		return &screen;
	}
private:

	Screen() {
	}
	Screen(const Screen&);
	const Screen& operator=(const Screen&);
	HANDLE hOut;
	INPUT_RECORD inRec;/*  返回数据记录 */
	DWORD numRead; /*  返回已读取的记录数 */
};

class SL {
public:
	SL() {
		output = Screen::instance();
	};

	bool Init()
	{
		system("color 70");
		SetWidth();

		SetHeight();
		SetNum();
		InitTable();
		right = 0;
		return true;
	}

	void InitTable()
	{
		table.resize(Height);
		for (int h = 0; h < Height; h++)
		{
			table[h].resize(Width);
		}

		int n = num;
		for (int i = 0; i < Height; i++)
		{
			for (int j = 0; j < Width; j++)
			{
					n--;
					table[i][j] = -1;
					if (n <= 0) {
						j = Width;
						i = Height;
					}
			}
		}
		
		srand(time(0));
		for (int i = 0; i < Height; i++)
		{
			for (int j = 0; j < Width; j++)
			{
				int pi = rand() % Height;
				int pj = rand() % Width;
				std::swap(table[i][j], table[pi][pj]);
			}
		}

		for (int i = 0; i < Height; i++)
		{
			for (int j = 0; j < Width; j++)
			{
				if (table[i][j] == -1)
				{
					int pos[][2] = { {-1,-1},{-1,1},{-1,0},{0,1},{0,-1},{ 1,-1 },{ 1,1 },{ 1,0 } };

					for (int k = 0; k < 8; k++)
					{
						int hh = pos[k][0] + i;
						int ww = pos[k][1] + j;

						if (hh >= 0 && hh < Height && ww >= 0 && ww < Width && table[hh][ww] != -1)
						{
							table[hh][ww]++;
						}
					}

				}
			}
		}

		int a;
		a = 1;
	}

	void SetWidth()
	{
		output->gotoxy(0, 0);
		printf("%s", "请输入扫雷游戏的宽度:                              ");
		output->gotoxy(22, 0);

		cin >> Width;
		while (!check(Width, 20, 60)) {
			output->gotoxy(0, 0);
			printf("%s", "请重新输入扫雷游戏的宽度:                              ");
			output->gotoxy(26, 0);
			cin >> Width;
		}
	}

	void SetHeight()
	{
		output->gotoxy(0, 1);
		printf("%s", "请输入扫雷游戏的高度:                              ");
		output->gotoxy(22, 1);

		cin >> Height;
		while (!check(Height, 20, 60)) {
			output->gotoxy(0, 1);
			printf("%s", "请重新输入扫雷游戏的高度:                              ");
			output->gotoxy(26, 1);
			cin >> Height;
		}
	}

	void SetNum()
	{
		output->gotoxy(0, 2);
		printf("%s", "请输入雷的个数:                              ");
		output->gotoxy(22, 2);

		cin >> num;
		while ((num >= (Width*Height>>1))) {
			output->gotoxy(0, 2);
			printf("%s", "请重新输入雷的个数:                              ");
			output->gotoxy(26, 2);
			cin >> num;
		}
	}

	bool check(int val,int low,int height)
	{
		return val >= low && val <= height;
	}

	void DrawIn()
	{
		output->changeColor(0x76);
		for (int h = 0; h < Height; h++)
		{
			output->gotoxy(5, 4+h);
			for (int w = 0; w < Width; w++)
			{
				printf("%s", "■");
				/*
				if (table[h][w] == -1)
					printf("%s", "★");
				else
					printf("%c ", table[h][w]+'0');				
				*/

			}
		}		
	}

	void DrawOut()
	{
		output->changeColor(0x75);
		output->gotoxy(3, 3);
		//printf("%s\n", "■");
		for (int w = 0; w < (Width+2);w++)
			printf("%s", "■");
		output->gotoxy(3, 3 + Height + 1);
		for (int w = 0; w < (Width + 2); w++)
			printf("%s", "■");
		for (int h = 0; h < (Height + 2); h++)
		{
			output->gotoxy(3, 3 + h);
			printf("%s", "■");
			output->gotoxy(3+(Width+1)*2, 3 + h);
			printf("%s", "■");
		}

	}

	void Run()
	{
		COORD pos;
		pos.X = 5;
		pos.Y = 4;
		output->gotoxy(5, 4);
		bool run = true;
		while (run)
		{
			char ch = _getch();
			switch (ch)
			{
			case 72:  //printf("UP\n"); break;
			{
				pos.Y--;
				pos.Y = pos.Y < 4 ? 4 : pos.Y;
				output->gotoxy(pos.X, pos.Y);
			}break;
			case 80:  //printf("DOWN\n"); break;
			{
				pos.Y++;
				pos.Y = pos.Y > (4 + Height - 1) ? (4 + Height - 1) : pos.Y;
				output->gotoxy(pos.X, pos.Y);
			}break;
			case 75:  //printf("LEFT\n"); break;
			{
				pos.X-=2;
				pos.X = pos.X >= 5 ? pos.X : 5;
				output->gotoxy(pos.X, pos.Y);
			}break;
			case 77:  //printf("RIGHT\n"); break;
			{
				pos.X += 2;
				pos.X = pos.X <= 5+(Width-1)*2 ? pos.X : 5 + (Width - 1) * 2;
				output->gotoxy(pos.X, pos.Y);
			}break;
			case 13:  //Enter
			{
				int h = pos.Y - 4;
				int w = (pos.X - 5) >> 1;
				bool ret = show(h, w);
				if (!ret)
				{
					output->gotoxy(70, 0);
					printf("你输了!!!");
					return;
				}
				else if((right+num) == (Width*Height))
				{
					output->gotoxy(70, 0);
					printf("胜利!!!");
					for (int h = 0; h < Height; h++)
					{
						for (int w = 0; w < Width; w++)
						{
							show(h, w);
						}
					}
					return;
				}
			}
			}
		}
	}

	bool show(int h,int w)
	{
		int ret = true;
		output->gotoxy(5 + w * 2, 4 + h);
		switch (table[h][w])
		{
		case -2:break;//已处理过
		case -1:
			printf("%s", "★");
			ret = false;
			break;
		case 0:
			bfs(h,w);
			break;
		default:
			printf("%c ", table[h][w]+'0');
			right++;
			table[h][w] = -2;
		}
		output->gotoxy(5 + w * 2, 4 + h);
		return ret;
	}

	void bfs(int h,int w)
	{
		using std::queue;
		queue<pair<int,int>> q;
		q.push(make_pair(h, w));

		while (!q.empty())
		{
			pair<int, int> n = q.front();
			q.pop();
			int h = n.first;
			int w = n.second;
			if (table[h][w] == -2)continue;
			output->gotoxy(5 + w * 2, 4 + h);
			if (table[h][w] == 0)
			{
				printf("%s", "  ");
				right++;
				int pos[][2] = { { -1,-1 },{ -1,1 },{ -1,0 },{ 0,1 },{ 0,-1 },{ 1,-1 },{ 1,1 },{ 1,0 } };

				for (int k = 0; k < 8; k++)
				{
					int hh = pos[k][0] + h;
					int ww = pos[k][1] + w;
					if (InWindow(hh, ww) && table[hh][ww]>=0)
					{
						q.push(make_pair(hh, ww));
					}
				}
			}
			else
			{
				printf("%c ", table[h][w] + '0');
				right++;
			}
			table[h][w] = -2;


		}
	}

	bool InWindow(int h, int w)
	{
		return h >= 0 && h < Height && w >= 0 && w < Width;
	}

private:
	Screen* output;
	int Width;  //窗口宽度
	int Height; //窗口高度
	int num;    //雷的数量
	int right;
	vector<vector<int>> table;
};

int main()
{
	Screen::instance()->Init();
	Screen::instance()->gotoxy(20, 20);
	SL game;
	game.Init();
	game.DrawOut();
	game.DrawIn();
	game.Run();
	system("pause");
	return 0;	
}

  

 

posted @ 2017-05-09 20:08  风轻云淡走天涯  阅读(394)  评论(0编辑  收藏  举报