【C++扫雷小游戏】

前言

尝试挑战经典的扫雷游戏,用C++实现自己的版本
扫雷,这个经典的休闲益智游戏,曾陪伴许多人度过无数时光。玩家需要根据已翻开的方块上的数字,推断出隐藏在方格中的地雷位置,然后用标记或者揭开其他方块的方式逐渐清理出安全的区域。通过逻辑推理与快速反应,玩家能够体验到紧张刺激以及智慧的成就感。

一.游戏规则

🚦设计游戏前先了解扫雷的基本规则,以围绕规则用C++实现:
一个扫雷盘面由许多方格(cell)组成,方格中随机分布着一定数量的雷(mine),一个格子中至多只有1雷。每个方格上都会显示数字来表示以此为中心的3*3的格子中有多少雷,胜利条件是打开所有非雷格(safe cell),失败条件是打开了一个雷格(踩雷)在这里插入图片描述

二.游戏菜单

1.创建菜单

先创建一个简单的游戏菜单

void menu()
{
	cout << "********** MENU **********\n";
	cout << "******   1. play  ******\n";
	cout << "******   0. exit  ******\n";
	cout << "*************************\n";
}

2.在主函数中使用菜单

(1)用switch case来找到选项
(2)用do while来实现一局又一局游戏的菜单弹出

int main()
{
	int input = 0;
	do
	{
		menu();
		cout << "请输入选项>";
		cin>>input;
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			cout << "退出游戏";
			break;
		default:
			cout << "输入错误,请重新输入";
			break;
		}
	} while (input);
	return 0;
}

三.方式:面向对象的思想

1.Mine(扫雷)类的创建

面向对象的设计提供了一种更加结构化的思维方式,使得代码更加清晰、可读和可维护。它能够提高代码的可重用性和可扩展性,同时也能够增强代码的灵活性和可靠性。

class Mine
{
public:
	//初始化棋盘
	void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)//打印棋盘
	void DisplayBoard(char board[ROWS][COLS], int row, int col)//布置雷
	void SetMine(char board[ROWS][COLS], int row, int col)//排查雷
	void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//找周围有多少雷 
	int GetMineCount(char mine[ROWS][COLS], int x, int y)};

并创建一个扫雷对象mine1

Mine mine1;

四.核心内容及其实现

1.棋盘的初始化

以二维数组的形式展现棋盘
1.其中’0’元素为安全格
2.'1’元素为雷区

char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };

mine棋盘为被初始化且被埋雷的棋盘
show棋盘为用户每次操作棋盘时可看到的界面

包含的元素:雷的个数,棋盘大小

#define ROW 5//元素所在区域大小
#define COL 5
#define ROWS ROW + 2//棋盘大小偏大防止越界
#define COLS COL + 2
#define EASY_COUNT 5//雷的个数
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
	{
		int i = 0;
		int j = 0;
		for (i = 0; i < rows; i++)
		{
			for (j = 0; j < cols; j++)
			{
				board[i][j] = set;
			}
		}
	}

对于mine棋盘和show棋盘的初始化

mine1.InitBoard(mine, ROWS, COLS, '0');
mine1.InitBoard(show, ROWS, COLS, '*');

2.打印棋盘

代码实现

void DisplayBoard(char board[ROWS][COLS], int row, int col)
	{
		int i = 0;
		int j = 0;
		cout << "------------扫雷------------\n";
		for (i = 0; i <= row; i++)
		{
			cout << i<<" ";
		}
		cout << "\n";
		for (i = 1; i <= row; i++)
		{
			cout << i<<" ";
			for (j = 1; j <= col; j++)
			{
				cout << board[i][j]<<" ";
			}
			cout << "\n";
		}
		cout << "------------扫雷------------\n";
	}

在这里插入图片描述

上图即为向用户展示的棋盘

3.在棋盘中埋雷

在棋盘中埋雷采用横纵坐标随机取值的方法
其中要调用rand()函数//其头文件为cstdlib
而对于x,y随机取值不能越界可使用如下方法

int x = rand() % row + 1;
int y = rand() % col + 1;

并且每次埋完一个雷就要减去一次总计雷的个数并再次进入循环

代码实现

void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
		}
		count--;
	}
}

4.统计周围雷的个数

由于用’1’表示的雷,用’0’表示的安全格,则可以直接 返回其周围元素的值之和再减去8个’0’即可

代码实现

int GetMineCount(char mine[ROWS][COLS], int x, int y)
	{
		return mine[x + 1][y] + mine[x - 1][y] +
			mine[x][y + 1] + mine[x][y - 1] +
			mine[x + 1][y + 1] + mine[x - 1][y + 1] +
			mine[x - 1][y - 1] + mine[x + 1][y - 1] - 8 * '0';
	}

5.排查雷

排查雷一共分三种情况
1.第一种是排查到show中的当前元素 不是*时,说明已经翻过此格子,需要重新排查
2.第二种是排查到mine中的当前元素是’1’时,那就是找到了炸弹,游戏结束
3.第三种就是排查到mine中的当前元素是’0’时,找到他周围有多少个雷,并在show中的此位置返回个数值。

要定义一个 count2来进行计数,如果count2的个数达到安全格的个数时,则说明游戏胜利
注意:在每次翻完格子或者在游戏结束时,都要添加打印函数来向用户展示实时情况

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
		{
	int x = 0;
	int y = 0;
	int count2 = 0;
	while (count2 < row * col - EASY_COUNT)
	{
		cout << "请输入横坐标>";
		cin>>x;
		cout << "请输入纵坐标>";
		cin >> y;
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				cout << "输入坐标重复,请重新输入\n";
			}
			else if (mine[x][y] == '1')
			{
				cout << "笨猪你被炸死了\n";
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				//不是雷,就统计x,y坐标周围有几个雷
				int c = GetMineCount(mine, x, y);
				show[x][y] = c + '0';
				DisplayBoard(show, ROW, COL);
				count2++;
			}
		}
		else
		{
			cout<<"输入坐标错误,请重新输入\n";
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		cout << "排雷成功\n";
		DisplayBoard(mine, ROW, COL);
	}
}

五.完整代码

类中代码的实现

#include<iostream>
#include<cstdlib>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define EASY_COUNT 10
using namespace std;
class Mine
{
public:
	//初始化棋盘
	void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
	{
		int i = 0;
		int j = 0;
		for (i = 0; i < rows; i++)
		{
			for (j = 0; j < cols; j++)
			{
				board[i][j] = set;
			}
		}
	}
	//打印棋盘
	void DisplayBoard(char board[ROWS][COLS], int row, int col)
	{
		int i = 0;
		int j = 0;
		cout << "------------扫雷------------\n";
		for (i = 0; i <= row; i++)
		{
			cout << i<<" ";
		}
		cout << "\n";
		for (i = 1; i <= row; i++)
		{
			cout << i<<" ";
			for (j = 1; j <= col; j++)
			{
				cout << board[i][j]<<" ";
			}
			cout << "\n";
		}
		cout << "------------扫雷------------\n";
	}
	//布置雷
	void SetMine(char board[ROWS][COLS], int row, int col)
		{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
		}
		count--;
	}
		}
	//排查雷
	void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
		{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - EASY_COUNT)
	{
		cout << "请输入横坐标>";
		cin>>x;
		cout << "请输入纵坐标>";
		cin >> y;
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				cout << "输入坐标重复,请重新输入\n";
			}
			else if (mine[x][y] == '1')
			{
				cout << "笨猪你被炸死了\n";
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				//不是雷,就统计x,y坐标周围有几个雷
				int c = GetMineCount(mine, x, y);
				show[x][y] = c + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			cout<<"输入坐标错误,请重新输入\n";
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		cout << "排雷成功\n";
		DisplayBoard(mine, ROW, COL);
	}
}
	//找周围有多少雷 
	int GetMineCount(char mine[ROWS][COLS], int x, int y)
	{
		return mine[x + 1][y] + mine[x - 1][y] +
			mine[x][y + 1] + mine[x][y - 1] +
			mine[x + 1][y + 1] + mine[x - 1][y + 1] +
			mine[x - 1][y - 1] + mine[x + 1][y - 1] - 8 * '0';
	}
};

把棋盘的实现步骤按顺序存放进新的函数game()中,便于 菜单的调用。
其中包含对象的创建,和对象函数的按序调用。

void game()
{
	Mine mine1;
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	mine1.InitBoard(mine, ROWS, COLS, '0');
	mine1.InitBoard(show, ROWS, COLS, '*');
	mine1.DisplayBoard(show, ROW, COL);
	mine1.SetMine(mine, ROW, COL);
	mine1.FindMine(mine, show, ROW, COL);
}

菜单及主函数的实现

int main()
{
	//srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		cout << "请输入选项>";
		cin>>input;
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			cout << "退出游戏";
			break;
		default:
			cout << "输入错误,请重新输入";
			break;
		}
	} while (input);
	return 0;
}

💘此扫雷小游戏是一个较简单的实现,读者可参考后根据自身写出符合需求的更高阶的制作。

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
以下是使用 C 语言编写的扫雷小游戏代码: #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 9 #define COL 9 #define MINE_NUM 10 void init_board(char board[ROW][COL], int row, int col, char ch); void print_board(char board[ROW][COL], int row, int col); void set_mine(char board[ROW][COL], int row, int col, int num); int get_mine_count(char board[ROW][COL], int row, int col, int x, int y); int main() { char board[ROW][COL]; int x, y, count = 0; srand((unsigned int)time(NULL)); // 初始化随机数种子 init_board(board, ROW, COL, ' '); set_mine(board, ROW, COL, MINE_NUM); printf("扫雷小游戏开始!\n"); print_board(board, ROW, COL); while (1) { printf("请输入要扫描的坐标(x,y):"); scanf("%d,%d", &x, &y); if (x < 1 || x > ROW || y < 1 || y > COL) { printf("坐标输入有误,请重新输入!\n"); continue; } if (board[x - 1][y - 1] == '*') { printf("很遗憾,你踩到了地雷,游戏结束!\n"); break; } count = get_mine_count(board, ROW, COL, x - 1, y - 1); board[x - 1][y - 1] = count + '0'; if (count == 0) { int i, j; for (i = x - 2; i <= x; i++) { for (j = y - 2; j <= y; j++) { if (i >= 0 && i < ROW && j >= 0 && j < COL && board[i][j] == ' ') { count = get_mine_count(board, ROW, COL, i, j); board[i][j] = count + '0'; } } } } print_board(board, ROW, COL); int i, j, win = 1; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (board[i][j] == ' ') { win = 0; break; } } } if (win) { printf("恭喜你,扫雷成功!\n"); break; } } return 0; } void init_board(char board[ROW][COL], int row, int col, char ch) { int i, j; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ch; } } } void print_board(char board[ROW][COL], int row, int col) { int i, j; printf(" "); for (i = 1; i <= col; i++) { printf("%d ", i); } printf("\n"); for (i = 0; i < row; i++) { printf("%d ", i + 1); for (j = 0; j < col; j++) { printf("%c ", board[i][j]); } printf("\n"); } } void set_mine(char board[ROW][COL], int row, int col, int num) { int i, j, count =

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马户一口吞不下又鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值