博客
关于我
扫雷小游戏——简单易懂
阅读量:331 次
发布时间:2019-03-04

本文共 4543 字,大约阅读时间需要 15 分钟。

文章目录

前言

在初期版本扫雷的基础上上添加了展开,标记,防首次炸死功能;
效果展示:
在这里插入图片描述

显示与雷区设立

扫雷首先需要两个大小相等的棋盘,一个如图1用来向外界展示,一个如图2用来埋雷。

在这里插入图片描述

初始化显示棋盘和雷区棋盘

棋盘有行和列,于是乎用二维数组来进行数据统计

char board[ROW][LINE];	memset(board, '*', sizeof(board));//显示的没点开之前为*	char mineboard[ROW][LINE];	memset(mineboard, '0', sizeof(board));//雷的统计初始化为0	Mineset(mineboard);//设置雷区

棋盘显示函数

将显示棋盘进行初始化为 * 后,用显示函数将其显示出来;

static void Showboard(char board[][LINE], int row, int line) //棋盘显示{   	printf("    ");	for (int i = 0; i <row-2; i++)	{   		printf(" %2d |", i+1);	}	printf("\n------------------------------------------------------\n");	for (int i = 1; i < row - 1; i++)	{   		printf(" %2d|", i);		for (int j = 1; j < line - 1; j++)		{   			printf(" %2c |", board[i][j]);		}		printf("\n------------------------------------------------------\n");	}}

显示效果图如下

在这里插入图片描述

雷区的设立

很显然,雷区棋盘需与显示棋盘同等大小,同时在其中分布一定数目的雷,定义一个宏MINE,将其赋值给count,每成功设立一颗雷,count就减一,设定的宏的大小就是雷的数目;

static void Mineset(char mineboard[][LINE])//随机分布雷{   	int x = 0;	int y = 0;	int count = MINE;	while (count)	{   		x = (rand() % (ROW - 2)) + 1;		y = (rand() % (LINE - 2)) + 1;		if (mineboard[x][y] == '0')		{   			mineboard[x][y] = '1';			count--;		}	}}

扫雷统计功能

上面提到两个棋盘,但是是独立分开的,那么是怎么联系在一起的呢?这个统计功能就是将两个棋盘联系在一起,当输入扫雷坐标后,通过雷区棋盘判定是否有雷,再将这个信息赋值给显示棋盘;

static char Detect(char mineboard[][LINE], int x, int y)//进行扫雷时,如果不是雷,则显示周围雷数{   	if (mineboard[x][y] == '0')	{   		return mineboard[x][y - 1] + mineboard[x][y + 1] \			+ mineboard[x - 1][y - 1] + mineboard[x - 1][y] \			+ mineboard[x - 1][y + 1] + mineboard[x + 1][y - 1]\			+ mineboard[x + 1][y] + mineboard[x + 1][y + 1]-7*'0';	}	if (mineboard[x][y] =='1')	{   		return OVER;	}}

防第一次炸死功能

设定一个函数,当我们进行第一次输入坐标的时候,如果判定是雷,就将这颗雷挪走,再随机设置一颗雷;

static void Firstmine(char mineboard[][LINE], int x, int y)//避免第一次被炸死{   	if (mineboard[x][y] == '1')	{   		mineboard[x][y] = '0';	}	while (1)	{   		x = (rand() % (ROW - 2)) + 1;		y = (rand() % (LINE - 2)) + 1;		if (mineboard[x][y] == '0')		{   			mineboard[x][y] = '1';			break;		}	}}

平铺函数

如下图,黑色是坐标点,该函数统计的是分别以黄色为中心点统计其周围雷的数目;
在这里插入图片描述

static void Openmine(char board[][LINE], char mineboard[][LINE], int x, int y)//平铺展开函数{   		board[x][y - 1] = Detect(mineboard,x,y-1);		board[x][y + 1] = Detect(mineboard, x, y + 1);		board[x - 1][y - 1] = Detect(mineboard, x-1, y - 1);				board[x - 1][y] = Detect(mineboard, x-1, y );			board[x - 1][y + 1] = Detect(mineboard, x-1, y + 1);			board[x + 1][y - 1] = Detect(mineboard, x+1, y - 1);				board[x + 1][y] = Detect(mineboard, x+1, y );					board[x + 1][y + 1] = Detect(mineboard, x + 1, y + 1);}

标记功能

标记功能是每进行一次输入就提示一次是否需要进行标记,标记的地方会显示为‘#’,如图所示
在这里插入图片描述

static void Lable(char board[][LINE])//标记坐标{   	int x = 0;	int y = 0;	int quit = 0;	int select = 0;	while (!quit)	{   		printf("请输入是否需要进行标记#1.yes#2.no\n");		scanf("%d", &select);		switch (select)		{   		case 1:			printf("请输入你的标记坐标\n");			scanf("%d %d", &x, &y);			board[x][y] = '#';			system("cls");			Showboard(board, ROW, LINE);			break;		case 2:			quit = 1;			break;		default:			printf("输入有误,请从新输入\n");		}	}}

判断胜负统计

通过统计显示棋盘剩余的空白处和标记数与设定的雷区数目进行比较,如果想等则玩家胜利;

static int Blank(char board[][LINE], int row, int line)//判断棋盘剩余的空白处{   	int count = 0;	for (int i = 1; i < row - 1; i++)	{   		for (int j = 1; j < line - 1; j++)		{   			if (board[i][j] == '*' || board[i][j] == '#')			{   				count++;			}		}	}	return count;}

主体函数逻辑

将上述函数进行整体连接;

void Game(){   	srand((unsigned)time(NULL));	char board[ROW][LINE];	memset(board, '*', sizeof(board));//显示的没点开之前为*	char mineboard[ROW][LINE];	memset(mineboard, '0', sizeof(board));//雷的统计初始化为0	Mineset(mineboard);//设置雷区	int n = 1;//防炸死次数;	while (1) //	{   		system("cls");		Showboard(board, ROW, LINE);//展示棋盘		while (1)//判断是否需要进行标记;		{   			Lable(board);			break;		}		int quit = 0;		int x = 0;		int y = 0;		while (!quit)//循环输入坐标扫雷		{   			printf("请输入你的坐标\n");			scanf("%d %d", &x, &y);			if (x<0 || x>ROW - 2 || y<0 || y>LINE - 2)			{   				printf("输入越界,请从新输入\n");				continue;			}			if (board[x][y] != '*' && board[x][y] != '#')			{   				printf("此处已经排除,请从新输入\n");				continue;			}			quit = 1;		}		while (n)//排除第一次被炸死		{   			Firstmine(mineboard, x, y);			n--;			break;		}		int result = Detect(mineboard, x, y);//判断是否被炸死		if (result == OVER)//炸死了		{   			system("cls");			board[x][y] = OVER;			Showboard(board, ROW, LINE);			printf("很遗憾,你被炸死了\n");			printf("雷区分布如下\n");			Showboard(mineboard, ROW, LINE);			break;		}		else//没炸死		{   			if (result == '0')//如果该扫雷处周围8个都是安全的,就将周围8个的周围8个的雷数显示出来;			{   				Openmine(board, mineboard, x, y);			}			board[x][y] = result;		}		int Win = Blank(board, ROW, LINE);		if (Win == MINE)		{   			printf("恭喜你,你赢了\n");			break;		}	}}

转载地址:http://lose.baihongyu.com/

你可能感兴趣的文章
判断字符是否出现
查看>>
C 语言restrict 关键字的使用浅谈
查看>>
深入理解数组指针与指针数组的区别
查看>>
iOS客户端与PHP服务端的简单交互
查看>>
图像Exif Orientation
查看>>
Python的异常处理
查看>>
Kubernetes(k8s)的调度器详细介绍
查看>>
Linux的网络参数设置
查看>>
权限修饰符protected和default的区别
查看>>
紫书——蛇形填数
查看>>
吐泡泡(栈)
查看>>
刷题计划1——poj1753
查看>>
Specialized Four-Digit Numbers——进制转换
查看>>
第一场
查看>>
蓝桥杯备战——刷题(2019)
查看>>
kuangbin题单 进阶搜素 深度优先搜索 哈密顿绕行世界问题 HDU2181
查看>>
谷歌最新提出无需卷积、注意力 ,纯MLP构成的视觉架构
查看>>
ArcMap|栅格计算器报错
查看>>
批量把多个csv/txt合成一个csv/txt
查看>>
《小石潭记》古文鉴赏
查看>>