C语言 | 扫雷小游戏(可自动展开)

目录

一.代码分配

二.实现思路

1.磨刀

(1)创建棋盘

 (2)初始化棋盘

(3)棋盘打印函数

(4)布置雷

2.砍柴

(1)玩家扫雷

(2)扫雷展开

 三.具体实现流程与代码

1.游戏的外围框架

 2.创建棋盘

3.棋盘的初始化

4.棋盘的打印

5.设置炸弹

5.玩家排雷

(1)判断玩家输入坐标与做出相应响应

 (2)实现拓展雷区

 四.总结


        在我小时候的记忆里,每台电脑总会有那么几款经典的游戏,今天给大家带来实现的这款游戏相信大家会油然而生出一种熟悉感,这款游戏叫扫雷,相信大家大部分都有接触过这款游戏,今天我就给大家带来该游戏的实现思路和代码。

一.代码分配

        我始终认为一段代码需要学习的并不是他的过程,更需要学习的是一种思路,如果理解代码思路,才叫真正的学习这段代码。

        我还是以项目的思路向大家介绍我的代码,首先我将我的代码分为三个文件撰写,分别为以下文件(test.c、game.c、game.h)。

         test.c文件主要用来写游戏的外围框架,比如游戏的菜单、如何让用户选择决定是否玩或退出游戏等功能。

        game.h文件主要写在实现这个游戏中,我们所有的声明和一些宏的定义,声明定义大家应该可以理解,宏的定义主要是为了方便再后期修改数据时,我们可以只通过改变宏的数据,而将整个游戏的数据进行改变。

        game.c文件则主要用在撰写整个游戏的实现逻辑,该段的代码则是整个游戏程序的核心,用于实现游戏功能的各种函数。

二.实现思路

        我们需要制作这款游戏我们首先得了解这款游戏,以下是我在网页中找到得一款扫雷小游戏,大家可以先玩一玩,然后再观看该文章后面部分。(游戏链接:扫雷(网页版)

1.磨刀

        俗话说的好,磨刀不误砍柴功,我们把刀磨锋利了,我们砍柴的速度自然不会慢,编程也是如此,我们把所有需要准备的函数准备好了,完成整个程序的进度自然也不会慢。

         这是网址版扫雷游戏得的一张截图(基础难度),我们仔细观察该游戏盘是由一个9*9的格子组成,这与我们前面将的三子棋的棋盘极其类似,同理,我们会想到可以用数组来保存我们的棋子数据。

(1)创建棋盘

        我们这里大概思路是创建两个棋盘(数组),第一个棋盘conceal(数组)里存字符1和字符0,其中1代表炸弹,第二个棋盘show(数组)里全部存放字符*来表示未被玩家排查的区域,第一个数组不展示给玩家,玩家真正看到的是第二个数组。实现效果如下图。

 

 关于数组创建的大小问题:

        我们玩网页版扫雷可以观察到,我们点一个位置,如果不是地雷,有的格子上会出现一个数字,如下图。

        图中圈的数值1的意思是周围九宫格内有一个炸弹的意思,那么我们想一想,如果用户排查的第一排第一个格子的时候,我们怎么计算雷的总数呢?因此我们通常会创建比棋盘大的数组,比如,我们今天要实现的是9*9的棋盘,因此我们应该创建的一个11*11的棋盘,保证上下左右都多出一个格子。

 (2)初始化棋盘

        所谓初始化棋盘即指将棋盘初始化成指定的数据,我们的思路是一开始将conceal棋盘上的数据初始化为字符0,show棋盘上的数据初始化为字符*。因此我们需要准备一个初始化棋盘的函数,这个函数的具体后面也会讲,这里只是提及以下整体思路。

(3)棋盘打印函数

        每次当玩家排查一个坐标时,我们都要将棋盘再次打印出来供玩家参考,另一方面,我们在测试游戏逻辑时,也会通过这个函数来检测我们游戏的逻辑是否正确,因此这个函数的实现也是十分必要的。

(4)布置雷

        棋盘初始化完成后,我们需要再棋盘上布置炸弹,我们前面也讲过,我们将在conceal数组中,存放字符1和字符0,这时字符1代表炸弹,0代表非炸弹,我们需要设计一个随机设置炸弹的函数;show数组是我们给用户展现的数组,我们仅仅需要在用户输入数据时,改变棋盘上数据,这个内容我们后面也会详细介绍该数组的使用。

2.砍柴

(1)玩家扫雷

        前面的准备工作做好了,我们现在就是进入正题,通过玩家的输入情况进行排雷即判断,这里我们设计一个排雷函数,根据玩家的输入将玩家输入信息分类,然后做出相应的操作,这个函数的设计可能稍微需要考虑一些细节上的问题,比如玩家输入的坐标是否有效,玩家输入的坐标是否重复等判断,因此需要特别小心注意。

(2)扫雷展开

        我们通过玩网页版扫雷时注意到,我们排除一个坐标,并不只是显示那一块坐标周围的雷,他还会往下拓展,如下图

        如上图,绿色圈圈是我鼠标点击排查的区域,而扫雷却展开一片,这是为什么呢,原来当我们排查某个区域时,他首先会排查我们排查的区域是否是炸弹,如果排查区域不是炸弹且周围八个格子范围内没有炸弹,他会依次将他周围的八个格子中的每个格子都依次再进行判断,判断他扩展的格子周围是否有炸弹,如果没有炸弹,则继续扩展,如果有炸弹则只用显示周围雷的个数。

        我们的思路是运用递归,如果玩家输入坐标不是炸弹且周围有炸弹则将该坐标的数据赋值为炸弹个数,如果玩家输入坐标不是炸弹且周围没有炸弹则将该坐标的数据赋值为空格字符,然后通过递归将周围坐标递归调用该函数。(这里理解可能有一点困难,后面会详细讲解并贴上代码)。

 三.具体实现流程与代码

1.游戏的外围框架

        游戏的外围框架很简单,通过循环和输入来对用户的选择进行分层。如果输入1后,屏幕打印“扫雷游戏”那么这个逻辑差不多就是正确的了,建议你们也可以用这种方法,写一层就测试一次,这为我们以后代码出现bug以后的修改bug工作提供了极大的便利。

//test.c文件
//菜单
void menu()
{
	printf("******************************\n");
	printf("**********  1.play  **********\n");
	printf("**********  0.exit  **********\n");
	printf("******************************\n");
}

//游戏函数(简略测试)
void game()
{
    printf("扫雷游戏");
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1: 
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("这不是一个有效的数字,请重新输入\n");
			break;
		}
	} while (input);
    return 0;
}

 2.创建棋盘

        创建棋盘这里我们在game.h文件中定义他的行列数据,这为我们修改数据提供了极大的便利,如下代码。

game.h文件

//game.h
#define _CRT_SECURE_NO_WARNINGS 1

//引入头文件
#include <stdio.h>
//这两个头文件在后面设置地雷时需要用到,这里就提前写上去了
#include <stdlib.h>
#include <time.h>

//定义棋盘行和列,这里有两组,需要哪组用哪组

#define ROW 9
#define COL 9

#define ROWS 11
#define COLS 11

test.c文件

//test.c

//注意这里无须引用stdio.h文件,我们直接引用game.h文件,以后在game.h文件中添加头文件,
//我们引用game.h文件后,test.c文件就不用重复引用了
//引用我们自己定义的头文件用双引号,不用尖括号

#include "game.h"
void game()
{
    //1.创建两个游戏棋盘
	char conceal[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
}

3.棋盘的初始化

        这一步只是做准备工作,我们将两个棋盘的数据初始化为特定的字符,我们需要在game.h文件中先声明这个函数,然后再game.c文件中设计这个函数,最后再test.c文件中测试调用这个函数,代码和实现方法如下。

game.h文件

//game.h文件添加以下代码

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

game.c文件

//game.c文件添加以下代码

//头文件引用
#include "game.h"

//初始化棋盘(set_value为设置的值,这样设计可以增加这个函数的通用性)
void init_board(char board[ROWS][COLS], int rows, int cols, char set_value)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set_value;
		}
	}
}

test.c文件

//test.c文件添加以下代码

void game()
{
    //1.创建两个游戏棋盘
	char conceal[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

    /2.棋盘初始化
	//自己看的棋盘全部初始化为字符0
	init_board(conceal, ROWS, COLS, '0');
	//展示给玩家看的棋盘全部初始化为字符*
	init_board(show, ROWS, COLS, '*');
}

4.棋盘的打印

        棋盘的打印也没有什么技巧,利用我们前面学过的循环就可以实现,这里特别要注意的是我们可以打印出棋盘的行坐标和列坐标,优化用户的游戏体验。

game.h文件

//game.h文件中需要添加的代码

//棋盘的打印
void print_board(char board[ROWS][COLS], int row, int col);

game.c文件

//game.c文件中需要添加的代码

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

test.c文件

//test.c文件中需要添加的代码

void game()
{
    //1.创建两个游戏棋盘
	char conceal[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

    //2.棋盘初始化
	//自己看的棋盘全部初始化为字符0
	init_board(conceal, ROWS, COLS, '0');
	//展示给玩家看的棋盘全部初始化为字符*
	init_board(show, ROWS, COLS, '*');

    //3.棋盘的打印(这里仅仅为测试,后期会删除)
	//棋盘只需要看9*9的空间,因此用ROW即可
	print_board(conceal, ROW, COL);
	print_board(show, ROW, COL);
}

5.设置炸弹

        这里为了方便修改数据,我们将炸弹数用宏定义,如果后期需要修改炸弹数,仅仅只要修改宏定义的数据即可。炸弹坐标的生成,我们是通过rand函数生成,而rand函数使用前需要设置一个种子,也可以理解为起始点,我们用srand函数设置这个种子,我们要生成随机数,因此需要放入一个变化的参数才可,我们生活中时间就是每时每刻发生变化的,因此我们将时间戳作为srand函数的参数,时间戳生成的函数时time,以上函数分别需要引用头文件stdlib.h和time.h,也就是我们前面提前引进的头文件,具体详情,请看以下代码。

game.h文件

//game.h文件中需要添加的代码

//定义炸弹数
#define BOMB 10

//设置炸弹
void set_bomb(char board[ROWS][COLS], int row, int col);


game.c文件

//game.c文件中需要添加的代码

//设置炸弹
//思路:随机生成1到9的数组,让这些数字作为坐标随机生成炸弹
void set_bomb(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	//炸弹数
	int count = BOMB;
	//设置随机种子
	srand((unsigned int)time(NULL));
	while (count)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		//随机生成的一对坐标不能重复
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}

	}
}

test.c文件

//test.c文件中需要添加的代码

void game()
{
    //1.创建两个游戏棋盘
	char conceal[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

    //2.棋盘初始化
	//自己看的棋盘全部初始化为字符0
	init_board(conceal, ROWS, COLS, '0');
	//展示给玩家看的棋盘全部初始化为字符*
	init_board(show, ROWS, COLS, '*');

    //3.棋盘的打印(这里仅仅为测试,后期会删除)
	//棋盘只需要看9*9的空间,因此用ROW即可
	print_board(conceal, ROW, COL);
	print_board(show, ROW, COL);

    //4.在棋盘上设置炸弹
	set_bomb(conceal, ROW, COL);
	//测试是否成功生成了10个炸弹
	//print_board(conceal, ROW, COL);

}

5.玩家排雷

        这里是本程序的难点了,因为不仅考虑到玩家输入的多种情况,根据玩家不同的输入情况做出相应的响应,还需要判断玩家是否成功排雷,以及数周围的地雷和扩展。

(1)判断玩家输入坐标与做出相应响应

大体思路:让玩家输入坐标,根据玩家输入坐标进行如下判断

        a.玩家输入的坐标是否再棋盘范围内

        b.玩家输入坐标是否重复

        c.玩家是否踩雷

        d.玩家是否获得游戏胜利

game.h文件

//game.h文件中需要添加代码

//玩家排雷
void find_bomb(char conceal[ROWS][COLS], char show[ROWS][COLS], int row, int col);


game.c文件 

//game.c文件中需要添加代码

//玩家排雷
//思路:玩家排雷,让玩家输入坐标,然后通过坐标数该坐标周围雷的个数
//注:
//1.玩家输入坐标必须在棋盘内
//2.玩家不能输入同样的坐标
//3.当show棋盘只有十个雷的时候游戏结束,玩家胜利
//4.玩家踩雷也会结束游戏
void find_bomb(char conceal[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	//判断玩家是否踩雷,如踩雷则改为1
	int flat = 0;
	//3.当show棋盘只有十个雷的时候游戏结束,玩家胜利
	while (is_win(show, ROW, COL) != BOMB)
	{
		printf("请输入您要排查的坐标:");
		scanf("%d %d", &x, &y);
		//1.玩家输入坐标必须在棋盘内
		if (x >= 1 && y >= 1 && x <= row && y <= col)
		{
			//2.玩家不能输入同样的坐标
			if (show[x][y] == '*')
			{
				if (conceal[x][y] == '1')
				{
					//4.1 踩雷
					//踩雷则将玩家踩的雷改为#,并打印出来
					flat = 1;
					show[x][y] = '#';
					print_board(show, row, col);
					break;
				}
				else
				{
					//扩展函数			
					expand_board(conceal, show, x, y);
					//测试游戏逻辑是否正确(程序真正运行起来后将注释该代码)
					//print_board(conceal, ROW, COL);
					print_board(show, ROW, COL);
				}
			}
			else
			{
				printf("输入重复,请重新输入");
			}
		}
		else
		{
			printf("您输入的坐标不合法\n");
		}
	}


	//出循环只有两种方式,踩雷和排除所有地雷
	if (flat == 1)
	{
		printf("很遗憾,您踩雷了,游戏结束\n");
	}
	else
	{
		printf("恭喜您,排雷成功\n");
	}
}

//判断是否输赢
//思路:遍历show数组,数炸弹数
int is_win(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
				count++;
		}
	}
	return count;
}

test.c文件

//test.c文件中需要添加的代码


void game()
{
    //1.创建两个游戏棋盘
	char conceal[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

    //2.棋盘初始化
	//自己看的棋盘全部初始化为字符0
	init_board(conceal, ROWS, COLS, '0');
	//展示给玩家看的棋盘全部初始化为字符*
	init_board(show, ROWS, COLS, '*');

    //3.棋盘的打印(这里仅仅为测试,后期会删除)
	//棋盘只需要看9*9的空间,因此用ROW即可
	print_board(conceal, ROW, COL);
	print_board(show, ROW, COL);

    //4.在棋盘上设置炸弹
	set_bomb(conceal, ROW, COL);
	//测试是否成功生成了10个炸弹
	//print_board(conceal, ROW, COL);

    //5.玩家排雷
	find_bomb(conceal, show, ROW, COL);

}

 (2)实现拓展雷区

        思路如下:当玩家点开一个区域并且周围九宫格内有炸弹,则将炸弹数的字符打印到该坐标的位置,若玩家点开一个区域并且周围九宫格内没有炸弹,我们则将空格字符打印到该坐标,并且又会展开另外一块区域,这里我们通过递归的方式来实现,在展开区域的时候,需要注意如下三点。

a.该坐标没有被排查过

b.该坐标不是地雷

c.该坐标没有被排查过

game.c文件

//game.c文件中还需要额外添加的代码
//计算周围的地雷数(使用时注意该函数不会考虑坐标是否合法)
int get_bomb_num(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y - 1] +
		board[x - 1][y] +
		board[x - 1][y + 1] +
		board[x][y - 1] +
		board[x][y + 1] +
		board[x + 1][y - 1] +
		board[x + 1][y] +
		board[x + 1][y + 1] - 8 * '0');
}


//展开棋盘

void expand_board(char conceal[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	if (show[x][y] == '*' && conceal[x][y] != '1')
	{
		int count = get_bomb_num(conceal, x, y);
		if (count == 0)
		{
			show[x][y] = ' ';
			if ((x - 1 >= 1) && (y - 1 >= 1) && (x - 1 <= ROW) && (y - 1 <= COL))
				expand_board(conceal, show, x - 1, y - 1);
			if ((x - 1 >= 1) && (y >= 1) && (x - 1 <= ROW) && (y <= COL))
				expand_board(conceal, show, x - 1, y);
			if ((x - 1 >= 1) && (y + 1 >= 1) && (x - 1 <= ROW) && (y + 1 <= COL))
				expand_board(conceal, show, x - 1, y + 1);
			if ((x >= 1) && (y - 1 >= 1) && (x <= ROW) && (y - 1 <= COL))
				expand_board(conceal, show, x, y - 1);
			if ((x >= 1) && (y + 1 >= 1) && (x <= ROW) && (y + 1 <= COL))
				expand_board(conceal, show, x, y + 1);
			if ((x + 1 >= 1) && (y - 1 >= 1) && (x + 1 <= ROW) && (y - 1 <= COL))
				expand_board(conceal, show, x + 1, y - 1);
			if (x + 1 >= 1 && y >= 1 && x + 1 <= ROW && y <= COL)
				expand_board(conceal, show, x -+1, y);
			if (x + 1 >= 1 && y + 1 >= 1 && x + 1 <= ROW && y + 1 <= COL)
				expand_board(conceal, show, x + 1, y + 1);
		}
		else
		{
			show[x][y] = '0' + count;
			return;
		}
	 }
}

 四.总结

         以下将本游戏的所有代码进行了整合,读者可先将源码执行体验一下,在自行来实现该游戏 。

game.h文件

//game.h文件
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 9
#define COL 9
#define ROWS 11
#define COLS 11

#define BOMB 10

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

//棋盘的打印
void print_board(char board[ROWS][COLS], int row, int col);

//设置炸弹
void set_bomb(char board[ROWS][COLS], int row, int col);

//玩家排雷
void find_bomb(char conceal[ROWS][COLS], char show[ROWS][COLS], int row, int col);

 game.c文件

//game.c文件#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

//初始化棋盘
void init_board(char board[ROWS][COLS], int rows, int cols, char set_value)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set_value;
		}
	}
}

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



//设置炸弹
//思路:随机生成1到9的数组,让这些数字作为坐标随机生成炸弹
void set_bomb(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	//炸弹数
	int count = BOMB;
	//设置随机种子
	srand((unsigned int)time(NULL));
	while (count)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		//随机生成的一对坐标不能重复
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
		                                        
	}
}

int is_win(char show[ROWS][COLS], int row, int col);
int get_bomb_num(char board[ROWS][COLS], int x, int y);
void expand_board(char conceal[ROWS][COLS], char show[ROWS][COLS], int x, int y);

//玩家排雷
//思路:玩家排雷,让玩家输入坐标,然后通过坐标数该坐标周围雷的个数
//注:
//1.玩家输入坐标必须在棋盘内
//2.玩家不能输入同样的坐标
//3.当show棋盘只有十个雷的时候游戏结束,玩家胜利
//4.玩家踩雷也会结束游戏
void find_bomb(char conceal[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	//判断玩家是否踩雷,如踩雷则改为1
	int flat = 0;
	//3.当show棋盘只有十个雷的时候游戏结束,玩家胜利
	while (is_win(show, ROW, COL) != BOMB)
	{
		printf("请输入您要排查的坐标:");
		scanf("%d %d", &x, &y);
		//1.玩家输入坐标必须在棋盘内
		if (x >= 1 && y >= 1 && x <= row && y <= col)
		{
			//2.玩家不能输入同样的坐标
			if (show[x][y] == '*')
			{
				if (conceal[x][y] == '1')
				{
					//4.1 踩雷
					//踩雷则将玩家踩的雷改为#,并打印出来
					flat = 1;
					show[x][y] = '#';
					print_board(show, row, col);
					break;
				}
				else
				{
					//扩展函数			
					expand_board(conceal, show, x, y);
					//测试游戏逻辑是否正确(程序真正运行起来后将注释该代码)
					//print_board(conceal, ROW, COL);
					print_board(show, ROW, COL);
				}
			}
			else
			{
				printf("输入重复,请重新输入");
			}
		}
		else
		{
			printf("您输入的坐标不合法\n");
		}
	}

	//出循环只有两种方式,踩雷和排除所有地雷
	if (flat == 1)
	{
		printf("很遗憾,您踩雷了,游戏结束\n");
	}
	else
	{
		printf("恭喜您,排雷成功\n");
	}
}

//判断是否输赢
//思路:遍历show数组,数炸弹数
int is_win(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
				count++;
		}
	}
	return count;
}

//计算周围的地雷数(使用时注意该函数不会考虑坐标是否合法)
int get_bomb_num(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y - 1] +
		board[x - 1][y] +
		board[x - 1][y + 1] +
		board[x][y - 1] +
		board[x][y + 1] +
		board[x + 1][y - 1] +
		board[x + 1][y] +
		board[x + 1][y + 1] - 8 * '0');
}


//展开棋盘

void expand_board(char conceal[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	if (show[x][y] == '*' && conceal[x][y] != '1')
	{
		int count = get_bomb_num(conceal, x, y);
		if (count == 0)
		{
			show[x][y] = ' ';
			if ((x - 1 >= 1) && (y - 1 >= 1) && (x - 1 <= ROW) && (y - 1 <= COL))
				expand_board(conceal, show, x - 1, y - 1);
			if ((x - 1 >= 1) && (y >= 1) && (x - 1 <= ROW) && (y <= COL))
				expand_board(conceal, show, x - 1, y);
			if ((x - 1 >= 1) && (y + 1 >= 1) && (x - 1 <= ROW) && (y + 1 <= COL))
				expand_board(conceal, show, x - 1, y + 1);
			if ((x >= 1) && (y - 1 >= 1) && (x <= ROW) && (y - 1 <= COL))
				expand_board(conceal, show, x, y - 1);
			if ((x >= 1) && (y + 1 >= 1) && (x <= ROW) && (y + 1 <= COL))
				expand_board(conceal, show, x, y + 1);
			if ((x + 1 >= 1) && (y - 1 >= 1) && (x + 1 <= ROW) && (y - 1 <= COL))
				expand_board(conceal, show, x + 1, y - 1);
			if (x + 1 >= 1 && y >= 1 && x + 1 <= ROW && y <= COL)
				expand_board(conceal, show, x -+1, y);
			if (x + 1 >= 1 && y + 1 >= 1 && x + 1 <= ROW && y + 1 <= COL)
				expand_board(conceal, show, x + 1, y + 1);
		}
		else
		{
			show[x][y] = '0' + count;
			return;
		}
	 }
}

test.c文件

//test.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

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

void game()
{
	//1.创建两个游戏棋盘
	char conceal[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	//2.棋盘初始化
	//自己看的棋盘全部初始化为字符0
	init_board(conceal, ROWS, COLS, '0');
	//展示给玩家看的棋盘全部初始化为字符*
	init_board(show, ROWS, COLS, '*');

	//3.棋盘的打印
	//棋盘只需要看9*9的空间,因此用ROW即可
	//print_board(conceal, ROW, COL);
	//print_board(show, ROW, COL);

	//4.在棋盘上设置炸弹
	set_bomb(conceal, ROW, COL);
	//测试是否成功生成了10个炸弹
	//print_board(conceal, ROW, COL);

	print_board(show, ROW, COL);

	//5.玩家排雷
	find_bomb(conceal, show, ROW, COL);
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1: 
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("这不是一个有效的数字,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

        以上就是本文全部内容,如果有疑问或需要修改的代码可在评论区提出,小编看到了就会及时回复,码文不易,你们的三连是对小编最大的支持,感谢!

  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值