经典扫雷游戏的简单实现

本文介绍如何使用编程实现一个简单的扫雷游戏,重温童年回忆。通过设置棋盘、布置雷区、排查雷等步骤,详细阐述了扫雷游戏的逻辑和代码实现。读者将了解到游戏规则、数据结构设计以及关键函数的实现,包括初始化棋盘、打印棋盘、布置雷和排查雷的过程。

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

如果要盘点曾经深藏在电脑里的经典游戏,“扫雷”可以说是首当其冲,儿时之回忆,经典中经典。

所以,在学习编程打怪升级的过程中,有谁不想自己亲自实现一下扫雷游戏,重温童年回忆,致敬儿时经典呢!

扫雷游戏的规则,我相信大家都十分熟悉,所以就不必多费口舌啦!(如果真的有没玩过扫雷游戏的hxd,但也想尝试的话,现在就赶紧关掉这篇博客,先去玩上几局游戏再回来)

好啦,我们言归正传,下面我们一起来看看,怎样去亲自实现一个我们自己的扫雷游戏!

扫雷游戏简单实现的逻辑

  • 首先,在游戏中布置一定数量的雷
  • 然后,通过输入坐标的方式,进行扫雷
  • 根据坐标,和雷的坐标进行判断:如果该坐标的位置是雷就爆炸,扫雷失败;如果该坐标的位置不是雷,就在该位置显示该坐标附近雷的数量,直到所有的雷被扫完,扫雷成功,游戏结束。

下面,我们就按照这个逻辑,对扫雷游戏进行简单的实现。

游戏菜单的实现

void menu()//简单的打印操作
{
	printf("******************************************\n");
	printf("**************  1 .play  *****************\n");
	printf("**************  0. exit  *****************\n");
	printf("******************************************\n");
}

为实现游戏所需的数据结构

假设我们简单实现一个9*9的棋盘,来进行我们的游戏;但在之后,如果输入的坐标位置不是雷,我们就需要排查周围雷的个数,并显示出来。

char arr[9][9] = { 0 };//定义一个9*9的数组来实现棋盘

 这是为了在排查坐标周围雷的个数的时候,不产生越界问题,我们的数组,需要增减两行两列,进行扩充,所以最后我们定义的二维数组是一个11*11的数组。

char arr[11][11] = { 0 };//分别扩增两行两列,以此来避免数组的越界问题

雷的表示: 我们用‘1’(字符1)来表示该坐标位置有雷,用‘0’(字符0)来表示该坐标位置没有雷。(为什么选用‘1’和‘0’,来进行表示,而不选用其它的字符呢,比如用‘*’,这里我们涉及了一个编程技巧,如果想知道为什么,我们一起看下去吧!)

为了在以后,我们可以方便地改变棋盘的大小,和雷的数量,我们可以直接使用全局变量

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

//使用全局变量,使代码的灵活性更高

在游戏开始之后,在棋盘中布置好一定数量的雷,这是我们就需要用一个二维数组来存储布置的雷的信息。

char mine[ROWS][COLS] = { 0 }//定义mine数组来存储布置好的雷的位置信息

在游戏开始进行之后,我们输入坐标,与mine数组内的坐标进行配对,来判断是否遇到雷;这时,我们便需要一个二维数组,来表示棋盘中,各个坐标是否已配排查,或被排查之后附近雷的个数。

char show[ROWS][COLS] = { 0 }//定义show数组来存放排查出的雷的位置信息

初始化棋盘

对于mine数组,前面我们已经提到选用‘1’‘0’字符,来表示雷的有无;对show数组,我们选用‘*’来表示该坐标是否已经被排查过。

此时我们需要一个方法对两个数组进行初始化操作。

void init_board(char arr[ROWS][COLS], int rows, int cols, char set);//初始化棋盘
  • void :函数的返回类型
  • init_board:函数命名
  • char arr[ROWS][COLS] :需要被初始化的数组
  • int rows:棋盘的行数
  • int cols:棋盘的列数
  • char set:数组所需初始化的内容

初始化的具体实现

void init_board(char arr[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++)
		{
			arr[i][j] = set;

		}
	}
}//使用一个嵌套for循环

此时初始化之后,我们可以尝试一下打印棋盘

//打印棋盘
void show_board(char arr[ROWS][COLS], int row  , int col)
{
	printf("-------------扫雷---------------\n");
	int i, j;
	for (int j = 0; j <= col; j++)
	{
		printf("%d ", j);//打印每一列的列数
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);//打印每一行的行号
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
		
	}
	printf("-------------扫雷---------------\n");
}//同样的嵌套for循环

在棋盘中布置一定数量的雷

在这里,我们可以使用rand()方法和取余产生随机值,进而产生随机坐标,起到了布置雷的作用

使用rand()方法的操作

#include <stdlib.h>
#include <time.h>
//头文件的引用

srand((unsigned int)time(NULL));
//在主函数中声明

如此,我们便可以在棋盘中布置雷啦。

#define EZ_COUNT 10
//事先定义一个全局变量,以便以后更改雷的个数

void set_mine(char arr[ROWS][COLS], int row, int col)
{
	int count = EZ_COUNT;

	while (count)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';//布置雷
			count--;
		}
	}
}
  • 使用while循环操作,满足雷的个数
  • 使用随机值取余操作,产生随机坐标

游戏开始之后排查雷

void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
  • 先让玩家输入坐标,去和mine数组中雷的信息进行配对来进行判断
  • 如果玩家输入的坐标是含有雷的坐标,则扫雷失败游戏结束,打印mine数组,不能让玩家“死不瞑目”
  • 如果玩家输入的坐标不是含有雷的坐标,则游戏继续,并统计该坐标附近雷的个数,打印show数组游戏继续
//排查雷
void find_mine(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 - EZ_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)//检查坐标输入的合法性
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,被炸死啦\n");
				show_board(mine, ROW, COL);
				break;
			}
			else
			{
				int count = get_mine_count(mine, x, y);
				show[x][y] = count + '0';
				show_board(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("非法坐标,重新输入\n");
		}
	}
	if (win == row * col - EZ_COUNT)
	{
		printf("恭喜你,排雷成功!\n");
	}
}

如果不是雷统计附近雷的个数

在我们的设计当中,用‘1’和‘0’去表示坐标位置是否有雷

//设计巧思
从ASCII码的角度

‘1’-‘0’=1
‘0’-‘0‘=0

我们以此来统计坐标周围雷的个数

int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	int i, j;
	int sum = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)
		{
			sum += mine[i][j];
		}
	}
	count = sum - 9 * '0';//根据ASCII码
	return count;
}

 

 主函数设计

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{
		menu();
		printf("请输入:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
}
  • 打印菜单 menu()
  • switch 语句,实现选择开始游戏退出游戏

整体代码实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

#define EZ_COUNT 10


//初始化棋盘
void init_board(char arr[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void show_board(char arr[ROWS][COLS], int row , int col);

//布置雷
void set_mine(char arr[ROWS][COLS], int row, int col);

//排查雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

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

void game()
{

	//游戏的实现;
	//mine数组是用来存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };//'0'
	//show数组是用来存放排查出的雷的信息
	char show[ROWS][COLS] = { 0 };//'*'

	//初始化棋盘
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');

	//打印棋盘
	//show_board(mine, ROW, COL);
	show_board(show, ROW, COL);

	//布置雷
	set_mine(mine, ROW, COL);
	//show_board(mine, ROW, COL);

	//排查雷
	find_mine(mine, show, ROW, COL);
	//show_board(mine, ROW, COL);
}


int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{
		menu();
		printf("请输入:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
}

//初始化棋盘
void init_board(char arr[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++)
		{
			arr[i][j] = set;

		}
	}
}

//打印棋盘
void show_board(char arr[ROWS][COLS], int row  , int col)
{
	printf("-------------扫雷---------------\n");
	int i, j;
	for (int j = 0; j <= col; j++)
	{
		printf("%d ", j);//打印每一列的列数
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);//打印每一行的行号
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
		
	}
	printf("-------------扫雷---------------\n");
}

//布置雷

void set_mine(char arr[ROWS][COLS], int row, int col)
{
	int count = EZ_COUNT;

	while (count)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';//布置雷
			count--;
		}
	}
}
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	int i, j;
	int sum = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)
		{
			sum += mine[i][j];
		}
	}
	count = sum - 9 * '0';
	return count;
}

//排查雷
void find_mine(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 - EZ_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)//检查坐标输入的合法性
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,被炸死啦\n");
				show_board(mine, ROW, COL);
				break;
			}
			else
			{
				int count = get_mine_count(mine, x, y);
				show[x][y] = count + '0';
				show_board(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("非法坐标,重新输入\n");
		}
	}
	if (win == row * col - EZ_COUNT)
	{
		printf("恭喜你,排雷成功!\n");
	}
}

运行结果

 

 好啦,言尽于此,快去实现一个自己的扫雷游戏把!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值