扫雷游戏的实现和实现思路

本文介绍了用C语言实现扫雷游戏的方法。先阐述游戏原理,玩家需在棋盘避开地雷通关。接着说明实现思路,用两个数组分别存放雷和排查信息,扩大棋盘解决越界问题。最后给出代码实现,创建三个文件,介绍各函数功能,完成扫雷游戏基本开发。

目录

一、前言

二、游戏原理

 三、游戏实现思路

四、游戏代码的实现 

InitBoard:初始化棋盘

DisplayBoard:打印棋盘

Setmine:布置雷

get_mine_count(mine, x, y)是用来计算已排除的方格周围的埋雷数

五、参考代码 



一、前言

扫雷游戏几乎能称得上是家喻户晓了,小的时候也有那么一段时间对此无比着迷。学了C语言后,慢慢的就想着能不能用编程语言来实现这样的游戏。今天呢,就让我们亲手实现扫雷游戏,再次体验下儿时那简单纯粹的快乐!!

二、游戏原理

想要实现扫雷游戏,第一步就是要清楚扫雷游戏的原理

这里我就简单的阐述一下扫雷游戏的原理

1.游戏在一个棋盘中进行,比如9*9棋盘

2.棋盘中存在着若干个地雷,玩家需要在系统的提示下避开这些地雷,排除所有埋雷的方格(即不能踩到雷!!),才算通关!!

3.玩家每排一个没有雷的方格,方格就会显示周围所有方格中藏有地雷的数目,如果踩到有雷的方格,就被炸死,游戏结束。

 三、游戏实现思路

扫雷的过程中,布置的雷和排查出的雷的信息都需要存储,所以我们需要⼀定的数据结构来存储这些 信息。 因为我们需要在9*9的棋盘上布置雷的信息和排查雷,我们⾸先想到的就是创建⼀个9*9的数组来存放 信息

那如果这个位置布置雷,我们就存放1,没有布置雷就存放0.

我们也需要注意到这样的问题,每排一个雷,我们就要周围方格雷的数目,这里我们可以将需统计的区域涂为黄色,当我们排到周边的方格时,就可能出现越界的问题

为了解决这样的问题,我们可以将棋盘扩大一圈,如将原本的9*9棋盘扩大为11*11棋盘(以此类推) 

只要在扩大的区域不布雷就好了!! (绿色区域不放雷

再继续分析,我们在棋盘上布置了雷,棋盘上雷的信息(1)和⾮雷的信息(0),假设我们排查了某 ⼀个位置后,这个坐标处不是雷,这个坐标的周围有1个雷,那我们需要将排查出的雷的数量信息记录 存储,并打印出来,作为排雷的重要参考信息的。那这个雷的个数信息存放在哪⾥呢?如果存放在布 置雷的数组中,这样雷的信息和雷的个数信息就可能或产⽣混淆和打印上的困难。

这⾥我们肯定有办法解决,⽐如:雷和⾮雷的信息不要使⽤数字,使⽤某些字符就⾏,这样就避免冲 突了,但是这样做棋盘上有雷和⾮雷的信息,还有排查出的雷的个数信息,就⽐较混杂,不够⽅便。 这⾥我们采⽤另外⼀种⽅案,我们专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。这样就互不⼲扰了,把雷布置到 mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期 排查参考。

同时为了保持神秘,show数组开始时初始化为字符 '*',为了保持两个数组的类型⼀致,可以使⽤同⼀ 套函数处理,mine数组最开始也初始化为字符'0',布置雷改成'1'。如下如:

四、游戏代码的实现 

 这里我们可以使用创建多个文件的方法来实现这样的代码

这里我们就创建三个文件,两个.c文件,一个.h文件:

game.c :文件中写游戏的测试逻辑

 test.c   :文件中写游戏中函数的实现

   game.h:文件中写游戏需要的数据类型和函数声明

1.test.c

首先还是先写我们的主函数

int main()
{

	test();
	return 0;
}

在这里我们直接将定义的test 函数放入使用,游戏的所有逻辑实现均汇集在其中。

void test()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请输入您想进入的模式\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始!!\n");
			game();
			break;
		case 0:
			printf("您已退出游戏!!\n");
			break;
		default:
			printf("输入错误请重新输入!!!\n");
			break;

		}
	} while (input);
}

如果说游戏是一棵枝繁叶茂的打树那么,这里的test函数就是树的主干了

menu函数是菜单界面的显示 

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

game函数就是游戏逻辑实现的全部,这里我们就主要介绍game函数的实现逻辑

void game()
{
 char mine[rows][cols];//存放类的信息
 char show[rows][cols];//存放排查出雷的信息


 //初始化棋盘
 InitBoard(mine, rows, cols, '0');
 InitBoard(show, rows, cols, '*');
 //打印棋盘
 DisplayBoard(show, row, col);
 //DisplayBoard(mine, row, col);
 //布置雷
 Setmine(mine, row, col);
 
 //排雷环节
 Findmine(mine,show, row, col);
	 
}

前面提到mine和show是我们专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。

棋盘的初始化、棋盘的打印及其他更多的功能有不同的函数实现,在使用时,我们也需要将这些函数放在.h文件中进行声明,再到game,c文件中实现相应的功能

game.h:

这些是.h文件中声明的函数和变量

后面我会一一介绍其功能

#pragma once
# include<stdio.h>
# include<stdlib.h>
# include<time.h>
#define row 9
#define col 9
#define rows row+2
#define cols col+2
#define Easy_count 10
//初始化棋盘
void InitBoard(char board[rows][cols],
	int Rows, int Cols,char set);
//打印棋盘
void DisplayBoard(char board[rows][cols], int Row, int Col);
//布置雷
void Setmine(char mine[rows][cols], int Row,int Col);
//排雷环节
void Findmine(char mine[row][col], char show[row][col], int Row, int Col);

1.row和col就表示行和列为了能使整个程序的关联性更强(即在修改棋盘的参数的时候更加的方便),在表示棋盘的参数时尽量不要直接使用数字,再有前面考虑到的越界问题,棋盘的大小应为理想行列数+2!!(rows   cols)

InitBoard:初始化棋盘

前面说过,排雷我们在mine数组中进行,排雷信息在show数组中展示,为了表现神秘感,

show数组用“*”初始化,mine 数组用‘0’初始化,后面我们就用‘1‘表示雷

这样我们就能将mine和show分别初始化(初始化时需要以rows和cols的标准初始化才能有效地解决越界问题)

初始化函数的声明:

//初始化棋盘
void InitBoard(char board[rows][cols],
	int Rows, int Cols,char set);

 实现:

void InitBoard(char board[rows][cols],
	int Rows, int Cols,char set)
{
	int i = 0;
	for (i = 0; i < Rows; i++)
	{
		int j = 0;
		for (j = 0; j < Cols; j++)
		{
			board[i][j] = set;
		}
	}

}

 

DisplayBoard:打印棋盘

在打印棋盘时我们只要看可以布雷的区域就行了,这里我们就只显示9*9的范围。

(打印时的范围为board[1-9][1-9],初始化的范围是board[0-10][0-10])

打印函数的声明:

void DisplayBoard(char board[rows][cols], int Row, int Col);

实现: 

打印效果: 

Setmine:布置雷

接下来我们要在mine数组中布置雷 ,即在mine数组中随机选几个格子将’0‘-->’1‘

布雷函数传参:

Setmine(mine, row, col);

布雷函数的声明:

//布置雷
void Setmine(char mine[rows][cols], int Row,int Col);

布雷函数的实现:

////布置雷(随即布置雷)
void Setmine(char mine[rows][cols],
	int Row, int Col)
{
	int count = Easy_count;
	int x = 0;
	int y = 0;
	while (count)
	{
		x = rand() % Row + 1;
		y = rand() % Col + 1;
		if (mine[x][y]!='1')
		{
			mine[x][y] = '1';
			count--;
		}
	}

}

在实现布雷的过程中,我们可以考虑到

1.要布雷的数量:这里我们可以自己定义变量,来实现游戏难度的控制,这里的Easy_count

就是我定义的布雷数量,对应头文件中的

2.随机坐标的布置

 这里就会涉及到

srand、time函数的知识想要深入了解的uu们可一点开看看

 点击这里查看随机数字生成的原理

很明显这里我们要在9*9键盘中随机布雷所以

x的范围  1--9

y的范围1--9

布好雷后让我们来看看效果

这里我们看到在9*9键盘中刚好就生成了10个雷

Foundmine:排雷 

排雷函数的传参:

 //排雷环节
 Findmine(mine,show, row, col);

排雷函数的声明: 

//排雷环节
void Findmine(char mine[row][col], char show[row][col], int Row, int Col);

排雷函数的实现:

//输入坐标
    //判断是否越界
    //如果这个位置是雷就被炸死
    //否则统计周边雷的个数,显示

//排除所有的雷后,游戏结束玩家胜利!

void Findmine(char mine[rows][cols],
	char show[rows][cols] ,int Row, int Col)
{
	//输入坐标
	//判断是否越界
	//如果这个位置是雷就被炸死
	//否则统计周边雷的个数,显示
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row * col -Easy_count)
	{
		printf("请输入要排查的坐标\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= Row && y >= 1 && y <= Col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你踩雷了!!\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
				int count = get_mine_count(mine, x, y);
				show[x][y] = count + '0';
				//将数字转化为字符时+‘0’;
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
			printf("输入错误应该输入的范围为x(1-%d),y(1-%d)请重新输入!!!\n",Row,Col);
			
		}

	}
	if (win == row * col - Easy_count)
	{
		printf("恭喜您排雷成功!!!\n");
		DisplayBoard(mine, row, col);
	}
}

 get_mine_count(mine, x, y)是用来计算已排除的方格周围的埋雷数

int get_mine_count(char mine[rows][cols],int x,int y)
{
	//想要将字符转化为数字可以用原来的字符减去’0‘
	//如’2‘-’0‘=2
	//’1‘-’0‘=1诸如此类!!!
	int i = 0;
	int j= 0;
	int count = 0;
	for (i = -1; i <= 1; i++)
	{
		for (j = -1; j <= 1;j++)
		{
			count += (mine[x+i][y+j] - '0');
			
		}
	}
	return count;

}

 注://想要将字符转化为数字可以用原来的字符减去’0‘
    //如’2‘-’0‘=2
    //’1‘-’0‘=1诸如此类!!!

//将数字转化为字符时+‘0’;

在计算周边的埋雷数时,我们可以将周围方格的字符转为数字,再相加,即可得到埋雷数。

五、参考代码 

然后扫雷游戏就算是基本完成了

这里我就在展示一下参考代码:

game.h

#pragma once
# include<stdio.h>
# include<stdlib.h>
# include<time.h>
#define row 9
#define col 9
#define rows row+2
#define cols col+2
#define Easy_count 10
//初始化棋盘
void InitBoard(char board[rows][cols],
	int Rows, int Cols,char set);
//打印棋盘
void DisplayBoard(char board[rows][cols], int Row, int Col);
//布置雷
void Setmine(char mine[rows][cols], int Row,int Col);
//排雷环节
void Findmine(char mine[row][col], char show[row][col], int Row, int Col);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
 void menu()
{
	 printf("****************************\n");
	 printf("******0.exit        ********\n");
	 printf("******1.play        ********\n");
	 printf("****************************\n");
	 printf("****************************\n");
}
 void game()
 {
	 char mine[rows][cols];//存放类的信息
	 char show[rows][cols];//存放排查出雷的信息


	 //初始化棋盘
	 InitBoard(mine, rows, cols, '0');
	 InitBoard(show, rows, cols, '*');
	 //打印棋盘
	 DisplayBoard(show, row, col);
	 //DisplayBoard(mine, row, col);
	 //布置雷
	Setmine(mine, row, col);
	// DisplayBoard(mine, row, col);
	 //排雷环节
	 Findmine(mine,show, row, col);
		 
 }
void test()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请输入您想进入的模式\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始!!\n");
			game();
			break;
		case 0:
			printf("您已退出游戏!!\n");
			break;
		default:
			printf("输入错误请重新输入!!!\n");
			break;

		}
	} while (input);
}
int main()
{

	test();
	return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[rows][cols],
	int Rows, int Cols,char set)
{
	int i = 0;
	for (i = 0; i < Rows; i++)
	{
		int j = 0;
		for (j = 0; j < Cols; j++)
		{
			board[i][j] = set;
		}
	}

}

void DisplayBoard(char board[rows][cols],
	int Row, int Col)
{
	int i = 0;
	int j = 0;
	printf("-------扫雷------\n");
	for (i = 0; i <= Row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= Col; i++)
	{
		printf("%d ", i);

		for (j = 1; j <=Col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

////布置雷(随即布置雷)
void Setmine(char mine[rows][cols],
	int Row, int Col)
{
	int count = Easy_count;
	int x = 0;
	int y = 0;
	while (count)
	{
		x = rand() % Row + 1;
		y = rand() % Col + 1;
		if (mine[x][y]!='1')
		{
			mine[x][y] = '1';
			count--;
		}
	}

}
int get_mine_count(char mine[rows][cols],int x,int y)
{
	//想要将字符转化为数字可以用原来的字符减去’0‘
	//如’2‘-’0‘=2
	//’1‘-’0‘=1诸如此类!!!
	int i = 0;
	int j= 0;
	int count = 0;
	for (i = -1; i <= 1; i++)
	{
		for (j = -1; j <= 1;j++)
		{
			count += (mine[x+i][y+j] - '0');
			
		}
	}
	return count;

}
//排查雷
void Findmine(char mine[rows][cols],
	char show[rows][cols] ,int Row, int Col)
{
	//输入坐标
	//判断是否越界
	//如果这个位置是雷就被炸死
	//否则统计周边雷的个数,显示
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row * col -Easy_count)
	{
		printf("请输入要排查的坐标\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= Row && y >= 1 && y <= Col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你踩雷了!!\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
				int count = get_mine_count(mine, x, y);
				show[x][y] = count + '0';
				//将数字转化为字符时+‘0’;
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
			printf("输入错误应该输入的范围为x(1-%d),y(1-%d)请重新输入!!!\n",Row,Col);
			
		}

	}
	if (win == row * col - Easy_count)
	{
		printf("恭喜您排雷成功!!!\n");
		DisplayBoard(mine, row, col);
	}
}

好,今天的的扫雷游戏就讲到这里,感谢大家的支持,拜拜!!

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值