C语言扫雷小游戏(超详解)-创新互联

目录

成都创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于成都网站制作、网站建设、通江网络推广、小程序设计、通江网络营销、通江企业策划、通江品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们大的嘉奖;成都创新互联公司为所有大学生创业者提供通江建站搭建服务,24小时服务热线:18982081108,官方网址:www.cdcxhl.com

前言

一,游戏构思

二,游戏实现

2.1 游戏框架

2.2 game.h头文件

2.3 game()的实现

2.4 每个函数的实现

2.5 周围雷的数目(around_num)

三,游戏总代码



前言

这次我们练习一个扫雷小游戏,这次涉及的知识主要是二维数组(当然如果对数组不熟悉的话可以看我之前写的有关数组的文章)扫雷游戏相信我们大家都很熟悉吧,多练习这样的小游戏,小项目都有助于提高我们的代码能力。话不多说,先来张美图,直接开始!

一,游戏构思

  我们需要两个棋盘,一个用来存放雷,一个向我们展示雷的数量。每个棋盘我们可以用二数维组实现,也就是需要两个二维数组。这个游戏我们还分为三个文件,test.c里放游戏框架,game.c里放函数的实现过程,game.h里放头文件和函数声明。游戏效果如下:

二,游戏实现 2.1 游戏框架

游戏框架我们还是采用之前的do while 结构,再加上switch分支语句。菜单我们用printf打印实现,代码如下

//test.c文件里  
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"    //把#include放在game.h中
void menu()
{
	printf("************************************************\n");
	printf("********************** 1.play ******************\n");
	printf("********************** 0.exit ******************\n");
	printf("************************************************\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();        //菜单
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();    //游戏实现放在这这函数里
			break;
		case 0:
			break;
		default:
			printf("选择错误,重新选择\n");
		}
	} while (input);
	return 0;
}
2.2 game.h头文件

我们创建一个头文件,将所用到的库函数和全局变量放在里面,这个扫雷的棋盘的大小我们用9*9,但是创建的时候我们得用11*11。因为我们扫雷游戏时输入坐标后,如果那个坐标不是雷,它会进行一个周围坐标的计算,如果输入的坐标是棋盘最外面的一圈,它会越界访问。所以我们创建11*11,但打印的时候我们可以打印成9*9(最外圈不打印)。创建一个全局变量row用来表示行,col用来表示列,用#define将row,col定义为9,ROW,COL定义为11。用mine_num表示雷的数量,暂且为10个雷。用头文件创建全局变量还有一个实用的好处,就是想改变行和列和累的数量时可以直接在game.h头文件中改。代码如下:

//game.h
#define _CRT_SECURE_NO_WARNINGS 1
//row 行
//col 列
#include#define row 9    //row = 9
#define col 9    //col = 9
#define ROW row+2    //ROW = row + 2 = 11
#define COL col+2    //COL = 11
#define mine_num 10    //雷的数量
2.3 game()的实现

  将游戏的主要实现过程放在game()中,这里面我们首先创建两个二维数组,一个用来防雷(mine),一个用来展示(show)。然后我们再初始化(init_board)这两个数组,数组mine我们把它全部初始化为0,在mine中放置雷的时候,我们用字符 '1' 表示雷,这样到时候利用加法方便计算雷的数量,数组show我们全部初始化为 ‘ * ’,到时候输入坐标的位置用mine计算出的数字代替 ‘ * ’。接下来我们在mine中放置雷(set_mine),做完这一切后我们就开始排雷,(函数的具体实现在下面讲)最将排雷的实现放在clear_mine中,代码如下:

//test.c
void game()
{
	char show[ROW][COL] = { 0 };		//show 展示的棋盘
	char mine[ROW][COL] = { 0 };		//mine 放雷的棋盘

	init_board(show, ROW, COL, '*');	//初始化棋盘show
	init_board(mine, ROW, COL, '0');    //初始化棋盘mine
	
	set_mine(mine,ROW,COL,mine_num);    //放置雷
	clear_mine(show,mine,ROW,COL);      //排雷
}
2.4 每个函数的实现

我们把每个游戏过程的函数放在game.c中讲,我们先把函数一一在game.h头文件中进行声明,然后在game.c中也包含game.c中,这样就能将game.c和test.c里建立联系。

//game.h
#define _CRT_SECURE_NO_WARNINGS 1
//row 行
//col 列
#include#define row 9
#define col 9
#define ROW row+2
#define COL col+2
#define mine_num 10

void init_board(char board[ROW][COL], int rows, int cols, char ret);    //初始化函数
void prin_board(char board[ROW][COL], int rows, int cols);                //打印函数
void set_mine(char board[ROW][COL], int rows, int cols, int num);        //随机放置雷的函数
void clear_mine(char show[ROW][COL], char mine[ROW][COL], int rows, int cols);//扫雷的函数

我们先实现初始化函数init_board。用两个for循环将数组一一赋值。代码如下:

//game.c
void init_board(char board[ROW][COL], int rows, int cols, char ret)	//初始化棋盘
{
	int i = 0;
	for (i = 0; i< rows; i++)
	{
		int j = 0;
		for (j = 0; j< cols; j++)
		{
			board[i][j] = ret;
		}
	}
}

     接着实现打印函数prin_board。这里先将列数打印出来,然后用两个for打印棋盘,在第一个for中先打印行的数字,然后打印这一行的棋盘。代码如下:

//game.c
void prin_board(char board[ROW][COL], int rows, int cols)	//打印棋盘
{
	int i = 0;
	printf("----------扫雷———————\n");
	for (i = 0; i< cols + 1; i++)			//打印列数0,1,2,3...
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i<= rows; i++)				//只把11*11棋盘中间的9*9打印出来,因为要把雷随机放在这中间9*9中
	{
		int j = 0;
		printf("%d ", i);		//打印行数1,2,3...
		for (j = 1; j<= cols; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("----------扫雷———————-\n");
}

效果如下:

接着我们实现放雷的函数set_mine,这里因为需要随机放置雷的数量,所以需要随机函数rand(),随机的起点我们用上时间戳放在test.c中的main中,时间戳所需要的库函数放在game.h头文件中,不了解随机值可以看这篇文章:C语言猜数字游戏(超级详解)_无限修bug的博客-博客_c语言猜数字游戏

代码如下:

//game.c
void set_mine(char board[ROW][COL], int rows, int cols, int num)	//放雷
{
	while (num)
	{
		int x = rand() % 9 + 1;		//随机坐标1 - 9,最外层不放雷,这样计算周围一圈雷不会数组越界
		int y = rand() % 9 + 1;		//rand()得到的值余9+1可以得到1—9的数
		if (board[x][y] == '0')
		{
			board[x][y] = '1';		//在mine棋盘中 雷 用 ‘1’表示,方便计算周围雷的数量
			num--;
		}
	}
}

最后是排雷函数clear_mine,我们用while循环,如果没踩到雷,需要循环展现的棋盘数量减去雷的数量(9*9 - 10),然后打印棋盘,输入排雷的坐标,然后用两个if语句进行坐标筛选,是否合法?是否没被排过?如果坐标都满足,进入最后一个if进行判断坐标是否为雷,如果为雷,游戏结束,跳出循环,如果非雷,将坐标周围雷的数量(around_num)替换掉那个坐标的 ‘ * ’(赋值在show[i][j])代码如下:

//game.h
void clear_mine(char show[ROW][COL], char mine[ROW][COL], int rows, int cols)	//扫雷
{
	int input = row*col - mine_num;		//如果每次都没踩到雷,需要排9*9-10个坐标。
	while (input)
	{
		int i = 0;
		int j = 0;
		prin_board(show, row, col);			//打印棋盘
		printf("请输入坐标:\n");            //输入排雷的坐标
		scanf("%d %d", &i, &j);
		if (i >0 && i<= 9 && j >0 && j<= 9)    //坐标的范围必须在1到9(包含9和1)之间
		{
			if (show[i][j] == '*')
			{
				if (mine[i][j] == '0')
				{
			
					show[i][j] = around_num(mine, i, j) + '0';		//周围雷的数量赋值到所选的坐标中
					prin_board(show, row, col);
					input--;
				}
				else
				{
					prin_board(mine, row, col);
					printf("很遗憾,你被炸死了\n");
					break;
				}
			}
			else
			{
				printf("该坐标已排过雷,请重新输入\n");
			}

		}
		else
		{
			printf("坐标非法,请重新输入\n");
			int i = 0;
			while ((i = getchar()) != '\n')	//清楚缓存区
			{
				;
			}
		}
	}
}

这里面的

show[i][j] = around_num(mine, i, j) + '0';        //周围雷的数量赋值到所选的坐标中 

around_num返回值是 int 型,所以加上字符 ‘ 0 ’,在赋值给char型棋盘show中,它也随之转化为char型。

2.5 周围雷的数目(around_num)

实现过程如下:

//game.c
static int around_num(char board[ROW][COL], int i, int j)	//周围雷的数目
{
	return (board[i - 1][j - 1] + board[i - 1][j] + board[i - 1][j + 1] + board[i][j - 1] + board[i][j + 1] + board[i + 1][j - 1] + board[i + 1][j] + board[i + 1][j + 1] - 8 * '0');
}

该函数实现过程是将输入坐标周围一圈的字符 ‘ 1 ’相加(正如前面所讲的mine棋盘初始化为字符 ‘ 0 ’,雷用 字符‘ 1 ’表示,这也是用 ‘1’表示雷的好处,方便计算),然后作为函数的返回值。

这里static作用是将around_num变为静态函数,静态函数只能在声明它的文件可见,其他文件不能引用该函数。意思是该函数只有在game.c可用,其他文件不可用。

around_num返回值是 int 型,因为数组board为char型,所以要减去字符‘ 0 ’(由ASCII表可以看出字符任意数字减去字符0的值为十进制的该任意字符的值),总共有8个char值,最后要减去8个字符‘0’。

三,游戏总代码

//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()
{
	char show[ROW][COL] = { 0 };		//show 展示的棋盘
	char mine[ROW][COL] = { 0 };		//mine 放雷的棋盘
	init_board(show, ROW, COL, '*');	//初始化棋盘
	init_board(mine, ROW, COL, '0');    
	set_mine(mine,ROW,COL,mine_num);    //放雷
	clear_mine(show,mine,ROW,COL);      //扫雷
}
int main()
{
	int input = 0;
	srand((unsigned)time(NULL));          //随机值的起点
	do
	{
		menu();                            //游戏菜单
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("选择错误,重新选择\n");
		}
	} while (input);
	return 0;
}

//game.h代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
//row 行
//col 列
#include#include#define row 9
#define col 9
#define ROW row+2
#define COL col+2
#define mine_num 10

void init_board(char board[ROW][COL], int rows, int cols, char ret);
void prin_board(char board[ROW][COL], int rows, int cols);
void set_mine(char board[ROW][COL], int rows, int cols, int num);
void clear_mine(char show[ROW][COL], char mine[ROW][COL], int rows, int cols);

//game.c代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

static int around_num(char board[ROW][COL], int i, int j)	//周围雷的数目
{
	return (board[i - 1][j - 1] + board[i - 1][j] + board[i - 1][j + 1] + board[i][j - 1] + board[i][j + 1] + board[i + 1][j - 1] +
		board[i + 1][j] + board[i + 1][j + 1] - 8 * '0');
}


void init_board(char board[ROW][COL], int rows, int cols, char ret)	//初始化棋盘
{
	int i = 0;
	for (i = 0; i< rows; i++)
	{
		int j = 0;
		for (j = 0; j< cols; j++)
		{
			board[i][j] = ret;
		}
	}
}
void prin_board(char board[ROW][COL], int rows, int cols)	//打印棋盘
{
	int i = 0;
	printf("----------扫雷———————\n");
	for (i = 0; i< cols + 1; i++)			//打印列数
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i<= rows; i++)				//只把11*11棋盘中间的9*9打印出来,因为要把雷随机放在这中间9*9中
	{
		int j = 0;
		printf("%d ", i);		//打印行数
		for (j = 1; j<= cols; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("----------扫雷———————-\n");
}
void set_mine(char board[ROW][COL], int rows, int cols, int num)	//放雷
{
	while (num)
	{
		int x = rand() % 9 + 1;		//随机坐标1 - 9,最外层不放雷,这样计算周围一圈雷不会数组越界
		int y = rand() % 9 + 1;		
		if (board[x][y] == '0')
		{
			board[x][y] = '1';		//在mine棋盘中 雷 用 ‘1’表示,方便计算周围雷的数量
			num--;
		}
	}
}

void clear_mine(char show[ROW][COL], char mine[ROW][COL], int rows, int cols)	//扫雷
{
	int input = row*col - mine_num;		
	while (input)
	{
		int i = 0;
		int j = 0;
		prin_board(show, row, col);			//打印棋盘
		printf("请输入坐标:\n");
		scanf("%d %d", &i, &j);
		if (i >0 && i<= 9 && j >0 && j<= 9)
		{
			if (show[i][j] == '*')
			{
				if (mine[i][j] == '0')
				{
			
					show[i][j] = around_num(mine, i, j) + '0';		//周围雷的数量赋值到所选的坐标中
					prin_board(show, row, col);
					input--;
				}
				else
				{
					prin_board(mine, row, col);
					printf("很遗憾,你被炸死了\n");
					break;
				}
			}
			else
			{
				printf("该坐标已排过雷,请重新输入\n");
			}

		}
		else
		{
			printf("坐标非法,请重新输入\n");
			int i = 0;
			while ((i = getchar()) != '\n')	//清楚缓存区
			{
				;
			}
		}
	}
}

如果不方便的话,源码还可以在gitee中获取:csdn-game3 · 雨天code/1 - 码云 - 开源中国 (gitee.com)

好了,到这里就结束了,如果对你有帮助,不如留个足迹再走。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


文章标题:C语言扫雷小游戏(超详解)-创新互联
文章URL:http://cdiso.cn/article/deigec.html

其他资讯