C语言扫雷详解

使用工具:vs2022

实现C语言扫雷,需要创三个文件:tese.c  game .c  game.h

test.c   程序的入口,主函数

game.c  函数的具体实现

game.h  头文件的引用和函数的声明

test.c  代码如下:

#define _CRT_SECURE_NO_WARNINGS
//声明头文件
#include"game.h"

int main()
{
	int input = 0;
	do
	{
		//打印游戏菜单
		game_menu();
		//提示用户输入
		printf("请根据菜单提示输入 1 / 0>:\n");
		//获取用户输入
		scanf("%d",&input);

		//switch 进入用户选择
		switch (input)
		{
		case 1:
            //游戏函数
			game_play();
			break;
		case 0:
			printf("退出成功!\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	
	return 0;
}

效果如下:

输入1,开始游戏

C语言扫雷详解_第1张图片

 输入0,退出游戏

C语言扫雷详解_第2张图片

 输入其他数,选择错误,重新输入

C语言扫雷详解_第3张图片

game_menu ,game_play等函数均在game.c中实现,头文件的声明和函数的引用均在game.h中。

game.c   游戏函数的具体实现分为以下几步

1,初始化二维数组(game_init函数)

我们这里已经创建了两个二维数组,show数组用来打印在屏幕上,mine数组用来存储雷。shou数组从1 1 到 9 9的元素我们全部初始化成 * 号,mine数组  1 1到 9 9 全部初始化成字符'0'

创建数组:

//创建两个 11 * 11二维数组,mine(用于存放地雷),show(用于打印棋盘)
	char show[ROWS][COLS]; //ROWS和COLS在game.h中声明,用于今后升级和改造
	char mine[ROWS][COLS];

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

初始化函数:

//初始化二维数组
void game_init(char arr[ROWS][COLS],int rows,int cols,char ch)
{
	int i = 0;
	int j = 0;

	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = ch;
		}
	}
}

2,打印扫雷棋盘(game_menu函数)

这里需要创建两个11 * 11 的二维数组,但是实际打印出来的是 9 * 9 的效果,因为,扫雷在扫到边界的时候,会出现越界的情况,例如,用户输入 11 11,但是,11 * 11 的二维数组下标最大是 10 10,因为玩游戏的不一定都是懂编程的人,所以用户输入我们让他从 1行1列开始,如果让用户从0行0列开始,大部分人都很难习惯。所以在 9 * 9 二维数组的基础上,我们在往上扩大两位数,这样用户输入不需要按照程序员的逻辑来输入坐标,也不会导致越界。

//打印棋盘
void game_che(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	
	//在第一行打印0 - 9作为提示
	for (i = 0; i <= row; i++)
	{
		printf("%d ",i);
	}
	printf("\n");

	for (i = 1; i <= row;i++)
	{
		//在每一列分别打印1 - 9 作为提示
		printf("%d ",i);

		for (j = 1; j <= col; j++)
		{
			printf("%c ",arr[i][j]);
		}

		//换行
		printf("\n");
	}

	printf("\n");
}

打印棋盘效果

C语言扫雷详解_第4张图片

3,让电脑随机生成地雷(game_npc函数)

这里由于打印出来的是9 * 9 棋盘的效果,所以我们随机生成10个雷,C语言中生成随机数需要使用rand函数,但是如果使用rand函数,你会发现,每次启动程序生成的随机数都是一样的,为了避免这种情况,我们在使用rand函数之前,需要使用srand函数,在srand函数中用time时间戳来更新,类型转换成unsigned int 。srand函数在程序中只需要使用一次即可,所以我们在test.c的main函数中使用一次即可。随机生成的地雷放在mine数组中,我们用1代表地雷,0表示无雷。

//电脑生成雷
void game_npc(char arr[ROWS][COLS], int row, int col)
{
	//总共生成10个雷
	int x = 10;

	while (x)
	{
		//随机产生的数 % 上 9,以后只会得到 0 - 8的数,所以我们加上1
		//这样就能得到 1 - 9的数了,这样雷才会存到 9 * 9 的棋盘中
		int i = rand() % row + 1;
		int j = rand() % col + 1;

		//判断随机生成的坐标是否已经有雷
		if (arr[i][j] == '0')
		{
			arr[i][j] = '1';
			//每次成功生成一个雷,x--,直到x等于0,循环终止
			x--;
		}
	}
}

埋完雷后的mine数组打印,1表示雷,0表示无雷

C语言扫雷详解_第5张图片

4,扫雷(ganme_clean函数)

使用两个变量接收用户输入的坐标,1,首先判断用户输入是否越界 2,使用变量作为二维数组的下标判断是否为 '1',如果是'1',说明扫到雷了,终止游戏,如果是'0',没有扫到 雷,计算出坐标周围8个雷的数量,以此循环,直到扫完全部的雷。

//排雷
void game_clean(char show[ROWS][COLS],char mine[ROWS][COLS],int row,int col)
{
	int y = 0;
	int x = 0;

	int c = 0;

	//总共埋了10个,而棋盘是 9 * 9 的,也就是说,棋盘有81个格子
	//那么在一直不踩到雷的情况下,扫71次,就把所有的雷都排查完了
	while (c < 71)
	{
		//提示用户输入坐标
		printf("请输入坐标:>");
		scanf("%d %d",&x,&y);

		//判断坐标是否越界
		if (x > 0 && x <= row && y > 0 && y <= col)
		{
			//判断坐标是否已经被排查过
			if (show[x][y] == '*')
			{
				//判断坐标是否为雷
				if (mine[x][y] == '1')
				{
					//如果是输入的坐标是雷,直接退出游戏
					printf("您踩到了雷!游戏结束!\n");
					break;
					//退出前打印棋盘,让用户看见所有雷的位置
					game_che(mine,row,col);
				}
				else
				{
					//如果没有踩到雷
					//计算坐标周围雷的数量
					int cont = 0;
					//计算完的结果放入cont变量
					cont = game_qua(mine,x,y);

					//将用户输入的做坐标更改成雷的数量
					show[x][y] = cont + '0';
					//打印棋盘,刷新屏幕
					game_che(show,row,col);
					//每次扫完雷,c++
					c++;

				}

			}
			else
			{
				printf("此坐标已经排查过,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}

计算雷的数量:game_qua函数

计算出用户输入的坐标周围8个格子有几个雷,首先我们知道,存储雷的二维数组是char类型的,但是返回值是int类型的,但是,在设计的时候,雷是 '1',非雷是'0',在ascll表中,0是48,1是49,如

过用1 去 减 0,也就等于 49 减 48 ,得到的值还是1,那么我们使用加法,把坐标周围的8个元素全部加起来,再减去 8 * '0',就得到了坐标周围雷的总数,这个时候雷的总数返回去,再加上'0'

C语言扫雷详解_第6张图片

 此时就可以把cont赋值给二维数组了。

​
int game_qua(char mine[ROWS][COLS] ,int x, int y)
{
	return(
        //这三个计算出坐标上一行的数量
		mine[x - 1][y - 1] + 
		mine[x - 1][y]	   +
		mine[x - 1][y + 1] +
        
        //计算出坐标左右两边的数量
		mine[x][y - 1]	   +
		mine[x][y + 1]     +

        //就算出坐标下一行的数量
		mine[x + 1][y - 1] +
		mine[x + 1][y]     +
		mine[x + 1][y + 1]
		) - 8 * '0';
}

​

game.h(函数的声明和头文件的引用)

#define _CRT_SECURE_NO_WARNINGS
#include

//生成随机数使用的头文件
#include
#include


//数组大小
#define ROW 9
#define COL 9

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

//打印菜单
void game_menu();

//游戏主函数
void game_play();

//初始化数组
void game_init(char arr[ROWS][COLS], int rows, int cols, char ch);

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

//判断坐标是否为雷
int game_qua(char mine[ROWS][COLS], int x, int y);

//计算雷的数量
int game_qua(char mine[ROWS][COLS], int x, int y);

//电脑生成雷
void game_npc(char arr[ROWS][COLS], int row, int col);

扫雷游戏效果:

C语言扫雷详解_第7张图片

我们把雷的数量改成 78,也就是说只有三个位置没有雷,只要排查完三个坐标,游戏就胜利。

展示一下扫完雷,游戏胜利的效果:

C语言扫雷详解_第8张图片

 

以上就是扫雷的逻辑和具体代码,欢迎大家评论和研究 

你可能感兴趣的:(c语言,c++,开发语言)