C语言实现简单的扫雷小程序


前言

扫雷作为一个童年经典小游戏,还是比较有意思的。今天我们就用C语言来实现一个简易版的扫雷小程序,难度也不高,也是一个可以拿来当做前期学习C语言的练手小项目。


一、游戏规则

1、扫雷棋盘由一个方格网格组成,每个方格可能包含雷或数字。
2、每一次选择一个方格,方格即被打开并显示出方格中的数字,方格中数字则表示其周围的8个方格隐藏了几颗雷。例如数字是1,就代表黑色方框中的其他8个方格中有1颗雷。同理,如果数字是3,就表示周围的8个方格隐藏了3颗雷。
3、玩家依次进行选择,当玩家选择到的位置是雷时,即是踩雷,游戏失败;而当玩家选择出了不是雷的所有数字方格后,则是排雷成功,游戏胜利。

二、所需技术

本次我们将使用C语言来实现这个简易版的扫雷游戏,对于C语言的要求不是很高,跟之前的三子棋难度相近,只需熟练掌握循坏与分支、二维数组、函数编写和调用相关知识,同时运用分文件模式进行编写,这也是一个前期C语言学习的练手小项目,而且程序编写出来后可玩性比三子棋强,还可以给自己或者朋友玩一玩,趣味性较高。

三、编写菜单目录

头文件部分

在正式编写程序前,我们先进行头文件的编写,先将要用到的头文件用#include进行包含。本次我们就实现一个简单版的扫雷游戏,所以棋盘大小我们就只设定为9*9的大小,后面如果想要增加难度,就只需在头文件这里的#define宏定义位置改变大小即可改变棋盘大小,这样可以使程序的可维护性变高。而后面的函数声明部分是当你后面每次要写一个函数时,就在头文件这里多加一份函数的声明,这样就可以实现函数的声明和定义的分离,进而实现了分文件的编写

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

#define X 9
#define Y 9

void chu(char arr[X][Y], char brr[X][Y],int x, int y);
void pan(char arr[X][Y], int x, int y);
void lei(char brr[X][Y], int x, int y);
int play(char arr[X][Y], char brr[X][Y], int x, int y);
char suan(char brr[X][Y], int x, int y, int a, int b);

顺带一提,变量的命名和函数的命名建议用英文取一些更有意义的名字,这样更加规范。

菜单目录部分

void menu()
{
	printf("**********************\n");
	printf("*********扫雷*********\n");
	printf("******1.开始游戏******\n");
	printf("******0.退出游戏******\n");
	printf("**********************\n");
}
int main()
{
	srand((unsigned)time(NULL));
	int n = 0;
	do
	{
		menu();
		scanf("%d", &n);
		switch (n)
		{
		case 1:
			game();
			break;
		case 0:
		    printf("退出游戏\n");
		    break;
		default:
			printf("输入错误,请重新输入:\n");
		}
	} while (n);
    return 0;
}

srand((unsigned)time(NULL)); --这一语句是初始化随机数,为后面程序使用rand()函数获得随机数做铺垫。

然后是一个do…while语句嵌套switch语句做一个开始的菜单目录(这是一个简单的模版,后面的很多开始菜单目录都可以这样实现)。然后可以设置一个menu()函数,里面就可以编写程序自定义打印菜单目录的内容。这里的这段程序当我们输入1时,就会调用game()函数,进入我们的游戏内容部分。

四、游戏内容部分

1、游戏运行部分

void game()
{
	char arr[X][Y] = { 0 };
	char brr[X][Y] = { 0 };
	chu(arr,brr, X, Y);
	pan(arr, X, Y);
	lei(brr, X, Y);
	while (1)
	{
		int s = play(arr, brr, X, Y);
		if (s == 0)
		{
			pan(brr, X, Y);
			printf("你被炸死了,游戏失败!\n");
			break;
		}
		else if (s == 1)
		{
			pan(arr, X, Y);
            continue;
		}
		else if (s == 2)
		{
			pan(brr, X, Y);
			printf("扫雷成功,游戏胜利!\n");
			break;
		}
	}
}

首先我们要定义两个二维数组arr,brr(建议取一些更有意义的名字,后面的函数命名也是),一个数组(arr)主要是为了打印出来给我们看的,另一个数组(brr)主要是用来存储每个方格位置的具体内容(雷或者数字)。然后使用chu()函数对两个数组棋盘进行初始化,全部初始化为’ '(空格字符)。pan()函数就是一个打印棋盘的函数。lei()函数就是对棋盘的雷进行初始化,即埋雷。然后用一个死循环来让游戏持续进行,通过play()函数的返回值来判断游戏状态,然后决定是否跳出循环结束游戏。

2、游戏内容部分

chu()函数,用来对两个棋盘进行初始化,将每个位置都初始化为’ '(空白字符)

void chu(char arr[X][Y], char brr[X][Y], int x, int y)
{
	int i = 0;
	for (i = 0; i < x; i++)
	{
		int j = 0;
		for (j = 0; j < Y; j++)
		{
			arr[i][j] = ' ';
			brr[i][j] = ' ';
		}
	}
}

pan()函数,负责进行打印棋盘的操作。

void pan(char arr[X][Y], int x, int y)
{
	int i = 0;
	for (i = 0; i < X; i++)
	{
		int j = 0;
		for (j = 0; j < Y; j++)
		{
			printf("---");
		}
		printf("\n");
		for (j = 0; j < Y; j++)
		{
			printf("| %c", arr[i][j]);
			if (j == Y - 1)
			{
				printf("|");
			}
		}
		printf("\n");
		if (i == X - 1)
		{
			for (j = 0; j < Y; j++)
			{
				printf("---");
			}
			printf("\n");
		}
	}
}

通过for循环的嵌套来打印棋盘,这里使用的是打印"—“和”|"配合打印数组来生成棋盘,你可以根据自己的想象和实践打印一个更好看的棋盘也可。
棋盘样式

lei()函数,进行生成随机位置的雷,进行埋雷操作。这里考虑到棋盘大小为9*9,所以这里通过rand()函数随机在不同设置了10个雷,这里用 * 字符来表示雷,即将brr数组相应的位置设置为 * 字符。

void lei(char brr[X][Y], int x, int y)
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
	int a = rand() % x;
	int b = rand() % y;
	   if (brr[a][b] == ' ')
	   {
		   brr[a][b] = '*';
	   }
	   else
	   {
		   i--;
	   }
    }
}

play()函数,实现游戏内容的主要函数。当玩家输入一个位置时,要先要判断是否越界,以及是否已经下过(已有数字)。当都不满足时,才算是输入了合理的坐标,然后进行判断,通过返回值来控制游戏状态
当该位置为雷时,即踩雷,返回0,游戏失败;若不为雷,则调用一个suan()函数进行计算该位置周围有多少个雷。这里需要注意的是字符数字和整形数字的区别,因为棋盘是char类型的二维数组,所以赋值给两个数组具体位置时一定要用字符数字,不然在打印棋盘时以"%c"的格式打印会出现问题,而将int类型的数字转换为char类型的字符数字只需加一个’0’或48即可。之后对brr数组进行遍历,一旦还有’ '(空格字符),说明还没有完成排雷,则返回1,游戏继续;而当遍历完brr数组后’ '(空格字符)数量n仍然为0的话,说明brr数组中不是雷就是数字,即已经排雷完成,返回2,游戏胜利。

char suan(char brr[X][Y], int x, int y,int a,int b)
{
	char c = 0;
	int i = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		int j = 0;
		for (j = y - 1; j <= y + 1; j++)
		{
			if (brr[i][j] == '*' && i >= 0 && i <= a - 1 && j >= 0 && j <= b - 1)
			{
				c = c + 1;
			}
		}
	}
	return c;
}
int play(char arr[X][Y], char brr[X][Y], int x, int y)
{
	int a = 0;
	int b = 0;
	while (1)
	{
		printf("请输入坐标:");
		scanf("%d %d", &a, &b);
		if (a >= 1 && a <= x && b >= 1 && b <= y)
		{
			if (brr[a-1][b-1] == '*')
			{
				return 0;
			}
			else if (brr[a-1][b-1] == ' ')
			{
				char z = (char)suan(brr,a-1,b-1,x,y);
				brr[a - 1][b - 1] = 48 + z;
				arr[a - 1][b - 1] = 48 + z;
				int n = 0;
				int i = 0;
				for (i = 0; i < x; i++)
				{
				  int j = 0;
					for (j = 0; j < Y; j++)
					{
						if (brr[i][j] == ' ')
						{
							n++;
						}
						if (n)
						{
							return 1;
						}
					}
				}
				return 2;
			}
			else
			{
				printf("坐标重复,请重新输入!\n");
			}
		}
		else
		{
			printf("输入错误,请重新输入!\n");
		}
	}
}

这是完成后的大致效果
大致效果

总结

本次扫雷游戏的简易实现分享就到这里了,该版本比较基础,适合C语言初学者练手巩固基础。
在这里我给出以下几个可以改进提升的地方:
1、可以在棋盘外边多打一圈坐标数字,这样选择位置时就能一目了然,不用再去数坐标位置。
2、可以多增设几个游戏难度,即可以扩大棋盘的大小和雷的数量等,让玩家有更灵活的选择。
3、该版本只能一个坐标一个坐标地推进游戏,有点慢。我们都知道当选择的位置为数字0时,周围一圈肯定是没有雷的,但我们还需一次一次地下周围那一圈,很麻烦,所以当我们选择位置为0时,可以让电脑自动帮我们把周围的一圈下了。这里提供一个很常规的思路就是使用递归来解决这个问题,而且递归对于初学者可能还是有一定难度的,所以如果你能用递归解决这个问题应该能有很大的收获。

这里我只是列举了几个可以改进的地方,当然你还可以根据你的需求来让这个程序更加丰满。

如需源码,可在我的gitee上找到,下面是链接。
扫雷源码

如对您有所帮助,可以来个三连,感谢大家的支持。

每文推荐

林宥嘉–背影
司南–冬眠
周传雄–冬天的秘密

学技术学累了时可以听歌放松一下

  • 29
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值