资讯专栏INFORMATION COLUMN

【C语言/入门游戏】扫雷完整版(包含标记,安全保护及展开)

0x584a / 581人阅读

摘要:有雷则返回雷数难度设置其实实现思路比较简单,可以再设置和。

知识提要(自主编写游戏所需要的知识):

1.函数的基本实现;

2.二维数组;

目录

扫雷

1.基本界面的实现

2.初始化棋盘(二维数组)

3.棋盘的打印

4.布置雷

5.安全保护

6.雷数显示

7.排查雷

8.标记雷

9.展开

10.难度设置

11.全局代码


扫雷

效果图:

 从以上效果图中可见,我们需要实现的功能有:

1.随机埋雷

2.显示雷数

3.展开

4.标记

5.判定输赢

如果将雷,数字,和*同时放在一个数组里是不现实的,因为如果一个格子中已经放了雷,就不可能将其变为星号显示,所以我们得到一个大体思路,要用两个数组,一个埋雷,一个显示。

还是老规矩,创建3个文件

game.h先引用和定义必要的数据

# define _CRT_SECURE_NO_WARNINGS#include #include #include #define ROW 9#define COL 9#define ROWS ROW+2#define COLS COL+2#define EASY_COUNT 10

这次我们用"*"当作未知量,"#"为标记,"1"为雷,"0"为非雷(此处为一个伏笔)

1.基本界面的实现

这一部分比较简单,所以就只简单提一句

void menu(){	printf("*********************************/n");	printf("*********    1. Play    *********/n");	printf("*********    0. Exit    *********/n");	printf("*********************************/n");	}void game(){	char mine[ROWS][COLS] = { 0 };//存放雷的信息	char show[ROWS][COLS] = { 0 };//展示给玩家的棋盘	intialize(mine,ROWS ,COLS,"0");	intialize(show,ROWS ,COLS,"*");	//展示棋盘	print(show, ROW, COL);		//布置雷	setmine(mine, ROW, COL);		//排查	search(mine, show, ROW, COL,0);}int main(){	int input = 0;	srand((unsigned int)time(NULL));	do	{		menu();		printf("请选择>:");		scanf("%d", &input);		switch (input)		{		case 1:			printf("game start/n");			game();			break;		case 0:			printf("已退出游戏/n");			break;		default:			printf("选择错误,请重新选择/n");			break;		}	} while (input);	return 0;}

这里可能有人要问,为什么要创建11*11的数组呢?

如果我们要在9*9的棋盘中找寻雷的个数,那么就得找寻周围8个元素,但是如果要找边边角角的格子附件雷的个数,就涉及到数组越界的问题,不太好办。所以我们将数组做大一圈,保证数组访问不会越界

2.初始化棋盘(二维数组)

现在我们要考虑一个问题,这次我们有两个二维数组要初始化,而且其中内容也不同,那该怎么办呢?

其实也比较简单,只需要让初始化函数多接受一个需要初始化的量就可以了

void intialize(char board[ROWS][COLS], int row, int col, char target){	int i = 0;	for (i = 0; i < row; i++)	{		int j = 0;		for (j = 0; j < col; j++)		{			board[i][j] = target;		}	}}

这样就可以完成不同的初始化了

3.棋盘的打印

由于扫雷需要的棋盘比较大,为了方便游玩,这次还需要打印行列号

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

效果图:

4.布置雷

布置雷就牵扯到随机数的问题,要保证雷不会重复布置且只在9*9的棋盘中布置

void setmine(char board[ROWS][COLS], int row, int col){	int x = 0;	int y = 0;	int count = 0;	while (1)//未布置满就一直循环	{		x = rand() % row + 1;//使x,y在1~9间,保证数组不越界布置		y = rand() % col + 1;		if (board[x][y] != "1")//保证布置的雷不重复		{			board[x][y] = "1";			count++;		}		if (count == EASY_COUNT)//布置满所有不重复的雷后才可跳出循环			break;	}}

5.安全保护

为了防止第一次排查就猝死,提高游戏体验所以我们需要设计一下,让玩家如果第一次就踩雷,棋盘会重置,直到此处没有雷

first_die++;if (first_die == 1 && mine[x][y] == "1")//first_die在test中创建,默认传递0进入		{			while (mine[x][y] == "1")			{				intialize(mine, ROWS, COLS, "0");//必须先初始化棋盘,不然会导致原本的雷依然在				setmine(mine, ROW, COL);			}					}

6.雷数显示

int search_show(char mine[ROWS][COLS], int x, int y){	return (mine[x - 1][y] +		mine[x - 1][y - 1] +		mine[x][y - 1] +		mine[x + 1][y - 1] +		mine[x + 1][y] +		mine[x + 1][y + 1] +		mine[x][y + 1] +		mine[x - 1][y + 1] - 8 * "0");}

"0"的ASCII值为48,我们将雷设计为"1"就是为了方便相加以后减去8个"0",直接就可以得到雷的数量

7.排查雷

下面就是本文章的重点之一,雷的排查,其实实现思路也比较简单,如果踩到雷,游戏结束;如果没有,继续游戏,同时显示附近雷的个数

	int x = 0;	int y = 0;			while (1)	{		printf("请输入需要排查的坐标,如:1 1/n");		scanf("%d%d", &x, &y);		first_die++;				if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入的行列号是否在规定范围		{			if (mine[x][y] == "1")			{				printf("你死了,请再接再厉/n");				print(mine, ROW, COL);				break;			}			else			{				show[x][y] = search_show(mine, ROW, COL)+"0";//显示周围的雷数				open(mine,show, x, y,row,col);				print(show, ROW, COL);							}		}		else		{			printf("输入错误,请重新输入/n");		}

8.标记雷

我们可以在排查以后加入一个标记功能,我们规定用"#"标记,同时只能标记未知量

//标记地雷		int input1 = 0;		int input2 = 0;		if (x >= 1 && x <= row && y >= 1 && y <= col)		{			do//至少要运行一次			{				printf("请输入标记坐标,输入0 0退出标记/n");				scanf("%d%d", &input1, &input2);				if (input1 >= 1 && input1 <= row && input2 >= 1 && input2 <= col)				{					if (show[input1][input2] == "*")//只标记未知量					{						show[input1][input2] = "#";						print(show, ROW, COL);					}					else					{						printf("标记失败,请重新标记/n");					}				}				else if (input1 == 0 && input2 == 0)//输入0 0退出标记					break;				else				{					printf("标记错误,请重新标记/n");				}			} while (input1&&input2);			printf("已退出标记/n");		}

9.展开

这应该是最难实现的一部分,这里我们用到递归的思想

void open(char mine[ROWS][COLS],char show[ROWS][COLS], int x, int y,int row ,int col){	int ret = 0;	ret =search_show(mine,x,y);		if (ret == 0)//如果周围无雷,判断展开	{		show[x][y] = " ";//防止死递归,如果不将show[x][y]变为" ",则下一次检测可能又会是*,再次进入递归,直至卡死。		if (x - 1 > 0 && y > 0 && show[x - 1][y] == "*"|| show[x - 1][y] == "#")			open(mine, show, x - 1, y, row, col);		if (x - 1 > 0 && y + 1 <= col && show[x - 1][y + 1] == "*"|| show[x - 1][y + 1] == "#")			open(mine, show, x - 1, y + 1, row, col);		if (x > 0 && y + 1 <= col && show[x][y + 1] == "*"|| show[x][y + 1] == "#")			open(mine, show, x, y + 1, row, col);		if (x + 1 <= row && y + 1 <= col && show[x + 1][y + 1] == "*"|| show[x + 1][y + 1] == "#")			open(mine, show, x + 1, y + 1, row, col);		if (x + 1 <= row && y > 0 && show[x + 1][y] == "*"|| show[x + 1][y] == "#")			open(mine, show, x + 1, y, row, col);		if (x + 1 <= row && y - 1 > 0 && show[x + 1][y - 1] == "*"|| show[x + 1][y - 1] == "#")			open(mine, show, x + 1, y - 1, row, col);		if (x > 0 && y - 1 > 0 && show[x][y - 1] == "*"|| show[x][y - 1] == "#")			open(mine, show, x, y - 1, row, col);		if (x - 1 > 0 && y - 1 > 0 && show[x - 1][y - 1] == "*"|| show[x - 1][y - 1] == "#")			open(mine, show, x - 1, y - 1, row, col);			}	else//有雷则返回雷数	{		return show[x][y]=search_show(mine, x, y)+"0";	}}

10.难度设置

其实实现思路比较简单,可以再设置MIDDLE_COUNT和HARD_COUNT。

传参时,将难度数字也传进去即可

这里交给大家去自行实现,不算难

11.全局代码

game.h# define _CRT_SECURE_NO_WARNINGS#include #include #include #define ROW 9#define COL 9#define ROWS ROW+2#define COLS COL+2#define EASY_COUNT 10//初始化void intialize(char board[ROWS][COLS], int row, int col, char target);//打印棋盘void print(char board[ROWS][COLS], int row, int col);//布置雷void setmine(char board[ROWS][COLS], int row, int col);//排查雷void search(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,intgame.c# define _CRT_SECURE_NO_WARNINGS# include "game.h"void intialize(char board[ROWS][COLS], int row, int col, char target){	int i = 0;	for (i = 0; i < row; i++)	{		int j = 0;		for (j = 0; j < col; j++)		{			board[i][j] = target;		}	}}void print(char board[ROWS][COLS], int row, int col){	int i = 0;	for (i = 0; i <= row; i++)	{		printf("%d ", i);	}	printf("/n");	for (i = 1; i <= row; i++)	{		int j = 0;		printf("%d ", i);		for (j = 1; j <= col; j++)		{			printf("%c ", board[i][j]);		}		printf("/n");	}}void setmine(char board[ROWS][COLS], int row, int col){	int x = 0;	int y = 0;	int count = 0;	while (1)	{		x = rand() % row + 1;		y = rand() % col + 1;		if (board[x][y] != "1")		{			board[x][y] = "1";			count++;		}		if (count == EASY_COUNT)			break;	}}int search_show(char mine[ROWS][COLS], int x, int y){	return (mine[x - 1][y] +		mine[x - 1][y - 1] +		mine[x][y - 1] +		mine[x + 1][y - 1] +		mine[x + 1][y] +		mine[x + 1][y + 1] +		mine[x][y + 1] +		mine[x - 1][y + 1] - 8 * "0");}void open(char mine[ROWS][COLS],char show[ROWS][COLS], int x, int y,int row ,int col){	int ret = 0;	ret =search_show(mine,x,y);		if (ret == 0)//如果周围无雷,判断展开	{		show[x][y] = " ";//防止死递归,如果不将show[x][y]变为" ",则下一次检测可能又会是*,再次进入递归,直至卡死。		if (x - 1 > 0 && y > 0 && show[x - 1][y] == "*"|| show[x - 1][y] == "#")			open(mine, show, x - 1, y, row, col);		if (x - 1 > 0 && y + 1 <= col && show[x - 1][y + 1] == "*"|| show[x - 1][y + 1] == "#")			open(mine, show, x - 1, y + 1, row, col);		if (x > 0 && y + 1 <= col && show[x][y + 1] == "*"|| show[x][y + 1] == "#")			open(mine, show, x, y + 1, row, col);		if (x + 1 <= row && y + 1 <= col && show[x + 1][y + 1] == "*"|| show[x + 1][y + 1] == "#")			open(mine, show, x + 1, y + 1, row, col);		if (x + 1 <= row && y > 0 && show[x + 1][y] == "*"|| show[x + 1][y] == "#")			open(mine, show, x + 1, y, row, col);		if (x + 1 <= row && y - 1 > 0 && show[x + 1][y - 1] == "*"|| show[x + 1][y - 1] == "#")			open(mine, show, x + 1, y - 1, row, col);		if (x > 0 && y - 1 > 0 && show[x][y - 1] == "*"|| show[x][y - 1] == "#")			open(mine, show, x, y - 1, row, col);		if (x - 1 > 0 && y - 1 > 0 && show[x - 1][y - 1] == "*"|| show[x - 1][y - 1] == "#")			open(mine, show, x - 1, y - 1, row, col);			}	else	{		return show[x][y]=search_show(mine, x, y)+"0";	}}int 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] == "*"||show[i][j]=="#")				count++;		}	}	if (count == EASY_COUNT)		return 1;	else		return 0;}void search(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int first_die){	int x = 0;	int y = 0;			while (1)	{		printf("请输入需要排查的坐标,如:1 1/n");		scanf("%d%d", &x, &y);		first_die++;				//防止第一次暴毙		if (first_die == 1 && mine[x][y] == "1")		{			while (mine[x][y] == "1")			{				intialize(mine, ROWS, COLS, "0");				setmine(mine, ROW, COL);			}					}		if (x >= 1 && x <= row && y >= 1 && y <= col)		{			if (mine[x][y] == "1")			{				printf("你死了,请再接再厉/n");				print(mine, ROW, COL);				break;			}			else			{				show[x][y] = search_show(mine, ROW, COL)+"0";//显示周围的雷数				open(mine,show, x, y,row,col);				print(show, ROW, COL);							}		}		else		{			printf("输入错误,请重新输入/n");		}				//判断输赢		int Win = win(show, row, col);		if (Win == 1)		{			printf("恭喜您,胜利了/n");			break;		}		//标记地雷		int input1 = 0;		int input2 = 0;		if (x >= 1 && x <= row && y >= 1 && y <= col)		{			do			{				printf("请输入标记坐标,输入0 0退出标记/n");				scanf("%d%d", &input1, &input2);				if (input1 >= 1 && input1 <= row && input2 >= 1 && input2 <= col)				{					if (show[input1][input2] == "*")					{						show[input1][input2] = "#";						print(show, ROW, COL);					}					else					{						printf("标记失败,请重新标记/n");					}				}				else if (input1 == 0 && input2 == 0)					break;				else				{					printf("标记错误,请重新标记/n");				}			} while (input1&&input2);			printf("已退出标记/n");		}	}}test.c# define _CRT_SECURE_NO_WARNINGS# include "game.h"void menu(){	printf("*********************************/n");	printf("*********    1. Play    *********/n");	printf("*********    0. Exit    *********/n");	printf("*********************************/n");	}void game(){	char mine[ROWS][COLS] = { 0 };//存放雷的信息	char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息	intialize(mine,ROWS ,COLS,"0");	intialize(show,ROWS ,COLS,"*");	//展示棋盘	print(show, ROW, COL);		//布置雷	setmine(mine, ROW, COL);		//排查	search(mine, show, ROW, COL,0);}int main(){	int input = 0;	srand((unsigned int)time(NULL));	do	{		menu();		printf("请选择>:");		scanf("%d", &input);		switch (input)		{		case 1:			printf("game start/n");			game();			break;		case 0:			printf("已退出游戏/n");			break;		default:			printf("选择错误,请重新选择/n");			break;		}	} while (input);	return 0;}

以上就是本次的分享内容了,喜欢我的分享的话,别忘了点赞加关注哟!

如果你对我的文章有任何看法,欢迎在下方评论留言或者私信我鸭!

我是白晨,我们下次分享见!!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/121852.html

相关文章

  • C语言初阶学习——扫雷游戏(递归)

    摘要:目录前言前言前期的准备前期的准备游戏代码的具体实现游戏代码的具体实现完整版的扫雷小游戏代码完整版的扫雷小游戏代码总结总结前言扫雷是一款大众类的益智小游戏,于年发行。 目录 前言 前期的准备 游戏代码的具体实现 1、text.c 2、game.h 3、game.c 完整版的扫雷小游戏代码: 1...

    zhonghanwen 评论0 收藏0
  • C语言入门扫雷游戏C语言实现

    摘要:条消息语言入门三子棋语言实现详细版的博客博客条消息语言入门三子棋语言实现详细版的博客博客我们将雷盘初始化为统一的符号。 目录 1.原理简介 2.分布目标及代码实现 3.总结 1.原理简介  首先我们需要一个空的雷盘,在其中随机埋入十枚雷,当我们排这颗雷时,若此位置为雷,则游戏失败,若不...

    caige 评论0 收藏0
  • C语言实现【扫雷游戏】拓展版

    摘要:作者时间网站地址摘要语言实现我们小时候玩过的扫雷游戏,最近看到了一些扫雷游戏的简单实现,但是总有功能上的缺失,玩起来不那么的原汁原味,因此我增加了一些新功能确保玩家首次排雷一定不会炸死。 ...

    JayChen 评论0 收藏0
  • C语言实现入门级小游戏——扫雷

    摘要:上一期咱们用语言实现了三子棋的小游戏语言实现三子棋今天我们再来写个扫雷的游戏,说起扫雷,相信大家都不陌生,可能许多朋友还是玩扫雷的高手。      上一期咱们用C语言实现了三子棋的小游戏  C语言实现三子棋       今天我们再来写个扫雷的游戏,说起扫雷,相信大家都不陌生,可能许多朋友还是...

    nevermind 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<