【C语言初阶】7 扫雷小游戏的思路与代码实现

可以在此处参考代码:gitee仓库代码提交
扫雷游戏实现大致思路:
在9*9的二维数组当中,找到隐藏的10个雷(EASY 版本的实现)
就需要两个二维数组1个存放随机生成的雷,1个存放需要排查雷的棋盘(显示在控制台,用户所看到的)
用户通过排查坐标,来判断雷所在的位置,那么就应该在用户选择坐标显示出周围8格存在雷的个数
选择的坐标若是雷,被炸死,若不是雷,继续排查(循环)全部排查完毕游戏结束

1.菜单环节

打印菜单,判断用户是否要进行游戏
用户至少进来1次,选择do while循环
代码如下:

#include 
void menu()
{
	printf("********************************\n");
	printf("***********  1.play   **********\n");
	printf("***********  0.exit   **********\n");
	printf("********************************\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch(input)
		{
		case 1:
			printf("扫雷游戏\n");
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

【C语言初阶】7 扫雷小游戏的思路与代码实现_第1张图片
基本菜单打印逻辑实现,选择1将让用户进入游戏
那么控制台上应该显示出来所要排雷的99二维数组进行排雷
==重点:>当我们在检测坐标周围8个坐标时,位于边缘的坐标的检测十分不方便。
于是我们构建一个11
11的二维数组,方便我们排查边缘坐标的雷,
而放置雷任然存放在99的二维数组当中,控制台显示的也只是99的二维数组==
多说无益,上代码实现

2.游戏实现环节

2.1 初始化二维数组

存放雷的二维数组,放置的雷用字符1表示,无雷的位置用字符0表示
在控制台上显示的二维数组,未排查的坐标用字符显示,以表示神秘,排查出来的坐标显示出周围8格的雷数总和(1111)
(显示出来99)
DisplayBoard打印棋盘,传参为ROW,COL 只打印9
9
但是board[ ][ ]里面还是ROWS,COLS,因为在创建board的时候就是ROWS和COLS
test.c 中game代码如下:

void game()
{
	//分别创建11*11的雷和排查雷的二维数组 mine  和 show
	char mine[ROWS][COLS] = { 0 };
	//雷棋盘
	InitBoard(mine, ROWS, COLS,'0');
	//显示雷棋盘
	// 放置雷 同样的传参传的是row,col(在9*9的棋盘中放雷)
	DisplayBoard(mine, ROW, COL);
	//扫描棋盘
	char show[ROWS][COLS] = { 0 };
	InitBoard(show, ROWS, COLS, '*');
	//显示扫描棋盘
	DisplayBoard(show, ROW, COL);
}

game.c中 初始化与显示代码

#include "game.h"
//初始化11*11的二维数组
 void InitBoard(char board[ROWS][COLS], int rows, int cols , char set)
{
	 int i = 0, j = 0;
	 for (i = 0; i < rows; i++)
	 {
		 for (j = 0; j < cols; j++)
		 {
			 //雷棋盘   初始化全为0  
			 //扫描棋盘 全初始化为*
			 // 设置set 将要初始化的字符传过来
			 board[i][j] = set;
		 }
	 }
}
 // 打印出来9*9 传过来的参数是row*col 下标是从1开始
 void DisplayBoard(char board[ROWS][COLS], int row, int col)
 {
	 int i = 0, j = 0;
	 for (i = 1; i <= row; i++)
	 {
		 for (j = 1; j < col; j++)
		 {
			 printf("%c ", board[i][j]);
		 }
		 printf("\n");
	 }
 }

【C语言初阶】7 扫雷小游戏的思路与代码实现_第2张图片
全0,雷,全* 扫描 (9*9)

2.2 放置雷

放雷就涉及到rand函数生成随机数的问题

 // 放雷
 void SetMine(char board[ROWS][COLS], int row, int col)
 {
	 int count = EASY_COUNT;
	 //需要循环不断地生成随机雷  用while循环
	 while (count)
	 {
		 //rand 生成的随机数%上row是0~8,所以需要+1
		 int x = rand() % row + 1;
		 int y = rand() % col + 1;
		 //可放置雷的情况
		 if (board[x][y] == '0')
		 {
			 //字符1表示放置了雷
			 board[x][y] = '1';
			 count--;
		 }
	 }
 }

【C语言初阶】7 扫雷小游戏的思路与代码实现_第3张图片
十个雷就在棋盘中放置好了,接下来就是找到这十个雷,当然在排雷之前先对控制台的界面进行优化

2.3 优化界面

1、雷的信息不能被用户看到,也就是不打印雷
2、把坐标标出来方便用户找到所要排查的坐标(优化Display函数)
优化过后的DisplayBoard代码:

 // 打印出来9*9 传过来的参数是row*col 下标是从1开始
 void DisplayBoard(char board[ROWS][COLS], int row, int col)
 {
	 int i = 0, j = 0;
	 //  这里加入列号
	 for (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 ", board[i][j]);
		 }
		 printf("\n");
	 }
 }

【C语言初阶】7 扫雷小游戏的思路与代码实现_第4张图片
只显示出要排雷的二维数组9*9,优化完成。下面就是用户排雷的实现

2.3 排雷

排雷基本思路,判断坐标处是不是雷,不是雷返回周围雷的个数

 //返回周围雷的个数 用int返回个数  这里面的mine[x][y]都是字符,在内存中存储的是对应的ASCII码值 ,所以要减去8个字符0,来确定个数
 int MineCount(char mine[ROWS][COLS], int x, int y)
 {
	 return mine[x - 1][y - 1] +
		 mine[x][y - 1] +
		 mine[x + 1][y - 1] +
		 mine[x - 1][y] +
		 mine[x + 1][y] +
		 mine[x - 1][y + 1] +
		 mine[x][y + 1] +
		 mine[x + 1][y + 1] - 8 * '0';
 }
 // 找雷
 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
 {
	 int x = 0, y = 0;
	 // 通过win判断循环次数,若棋盘上可以排查的位置都已经找到,那么循环结束
	 int win = 0;
	 while (win<row*col-EASY_COUNT)
	 {	 
		 // 通过坐标确定排查位置
		 printf("请选择坐标:>");
		 scanf("%d %d", &x, &y);
		 // 判断坐标合法性
		 if (x >= 1 && x <= row && y >= 1 && y <= col)
		 {
			 // 判断该坐标是否排查过
			 if (show[x][y] == '*')
			 {
				 // 雷
				 if (mine[x][y] == '1')
				 {
					 printf("很遗憾,你被炸死了\n");
					 break;
				 }
				 else
				 {
					 // 没踩到雷,返回周围雷的个数
					 int ret = MineCount(mine, x, y);
					 show[x][y] = ret + '0';
					 DisplayBoard(show, ROW, COL);
					 win++;
				 }
			 }
			 else
			 {
				 printf("不可重复排查,请重新输入\n");
			 }
		 }
		 else
		 {
			 printf("输入坐标不合法,请重新输入\n");
		 }
	 }
	 // 通过win判断循环次数,若棋盘上可以排查的位置都已经找到,那么排雷成功
	 if (win == row * col - EASY_COUNT)
	 {
		 printf("恭喜你,排雷成功\n");
	 }
 }

总结:

扫雷的难点1:
初始化board是1111的二维数组(为了方便处理边界的坐标周围雷的情况),这个点想不到
扫雷的难点2:
也正是因为11
11和9*9 所以在函数传参的过程中,需要想清楚该传ROW还是ROWS
数组传参拿数组接收 board[ROW][COL]
扫雷的难点3:
返回坐标周围的雷的个数 居然只需要return 坐标周围的字符减去8个’0’字符就行,没有采用if…else…这种结构(这样太麻烦了)

你可能感兴趣的:(C语言初阶,游戏,c语言,git)