c语言:初步实现扫雷游戏

发布于:2022-12-29 ⋅ 阅读:(552) ⋅ 点赞:(0)

简单介绍:

       最基本的规则:你点到一个数字,如果是3,那就说明最靠近他它周围的8个格里有3个雷。.然后通过相邻或者相间的数字之间的交集来判断哪些是雷,若点击猜中了雷,则游戏结束。

(在一些版本的扫雷游戏当中还有着时间的限制与要求 )

长话短说,接下来我们用c语言和控制台来初步实现扫雷游戏。此次游戏的实现需要引用三个文件,分别是被包含在源文件当中的test.cgame.c,被分配在头文件当中的game.h

   这三个文件的作用分别如下:

 一、主题框架(不包含游戏函数的实现)

 此处引用game.h文件来实现游戏函数。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include "game.h"
void menu()
{
	printf("-----------------------------\n");
	printf("-  1.开始游戏   0.退出游戏  -\n");
	printf("-----------------------------\n");
}
void game()
{
	;
}
int main()
{
	int n;
	do
	{
		menu();
		printf("请选择:>");
		scanf_s("%d", &n);
		switch (n)
		{
		case 1:
			game();
			break;
		case 0:
			printf("已退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择-》\n\n");
			break;
		}
	} while (n);
	return 0;
}

n  用来判定是否n进行游戏,menu()函数则为游戏开始前的选项,game()函数用来实现游戏的运行。其中game()函数的书写是最重要的部分。 

 此处只包含选择是否开始游戏的界面,接下来实现游戏当中的game函数。

 二、game函数实现

1、识别雷,统计坐一格内标雷的个数。

现在就拿一个一个9*9的格子来讲,如果我们要知道这个雷放在哪里,就需要用一个二位数组把这个雷存起来。这样子才能判断是否踩雷。所以这里定义一个9*9的二维数组arr[ 9 ][ 9 ]来将这些雷存起来,具体雷的个数视情况而定。

接下来就是基本的棋盘构建了。同样也可以用9*9的二维数组arr[ 9 ][ 9 ]来封装棋盘。
在游戏刚开始,点击一个坐标,那么他就必须显示这个坐标周围一格内有多少个雷,如下:

这种情况比较好处理,但是如果这个坐标出现在边界位置,还是用原来的方法去遍历这个坐标周围的一格内的数据,就会形成数组越界的错误,如图:

可能遇到这种情况的第一种反应差不多都是增加一个判断条件,去识别是否为边界坐标,那这样就在时间和空间上造成了极大的浪费。反向思考,那我们就可以让边界的坐标在遍历计算雷的个数的时候不形成越界,也就是扩大原来棋盘二维数组的大小,将原来的arr[ 9 ][ 9 ]扩大为arr[ 11 ][ 11 ]

2、布置雷

此处我们将雷定义为‘ 1 ’,非雷就定义为‘ 0 ’ ;当我们排查雷的时候,去识别雷的时候就会形成歧异,无法分辨是我们排查出来的雷,还是下次输入的时候,他本身被当作为雷所以我们需要两个二维数组来进行区分,用一个二维数组l e i [11][11]来存放雷,
用另外一个二维数组 p a i c  h a [11][11]来存放排查雷的信息,这样子就不会形成歧异。

考虑到后面方便修改棋盘大小,这里在game.h使用宏定义来实现棋盘的大小。后面直接引用到test.c中。

 

二维数组lei布置雷的元素初始化为‘ 1 ’,其余的元素初始化为‘ 0 ’;
二维数组p a i c h a初始化为‘ * ’,排除雷后,具体位置改为具体数字字符; 

接下来初始化棋盘:将雷初始化为全0,将信息数组初始化为全*,创建函数进行初始化,并将其放入game.h进行声明,然后在game.c当中实现。 

char lei[hang][lie]={0};
	char paicha[hang][lie]={0};
	chushihua(paicha, hang, lie,'*');
	chushihua(lei,hang,lie,'0');
void chushihua(char arr[hang][lie], int h, int l,char set )
{
	for (int i = 0;i < h;i++)
	{
		for (int j = 0;j < l;j++)
		{
			arr[i][j] = set;
		}
   }
}

然后在存放雷数据的二维数组中布置雷

//set_mine(lei,Hang,Lie);

void set_mine(char c[hang][lie], int h, int l)
{
	int count = 10;
	while(count)
	{
		int x = rand() % h + 1;
		int y = rand() % l + 1;

		if (c[x][y] == '0')
		{
			c[x][y] = '1';
			count--;
		}
	}
}

这里布置雷为随机布置,所以要使用rand()函数,而在rand函数使用之需使用srand时间戳
且需在game.h当中包含头文件stdlib.htime.h 。

我们之前用字符‘0’将雷所在数组初始化,现在用‘1’来布置雷,效果如下

 

 

3、打印棋盘。

创建函数来打印棋盘dayin();图中的*为未知的,也就是玩家所能看到的的棋盘,上面的只有‘0’与‘1’的棋盘是游戏内雷的位置,是玩家看不到的内容。

 

dayin(lei, Hang, Lie);
	dayin(paicha,Hang,Lie);
void dayin(char b[hang][lie], int h, int l)
{
	for (int tem = 0;tem <= l;tem++)
	{
		if (tem == l - 1)
			printf("-----");
		else
			printf("----");
	}printf("\n");
	for (int i = 0;i <=9;i++)
	{
		if (i != 9)
		{
			printf("| %d ", i);
		}
		else
			printf("| %d |", i);
	}printf("\n");
	for (int i = 1;i < hang-1;i++)
	{    
		for (int tem = 0;tem < l+1;tem++)
		{
			if (tem == l - 1)
				printf("-----");
			else
			printf("----");
		}printf("\n");
		printf("| %d ", i);
		for (int j = 1;j <= l;j++)
		{
			
			if (j == l)
				printf("| %c |", b[i][j]);
			else
			printf("| %c ", b[i][j]);

		}printf("\n");
	}
	for (int tem = 0;tem < l+1;tem++)
	{
		if (tem == l - 1)
			printf("-----");
		else
			printf("----");
	}printf("\n");
}

 4、排雷。

 在game()函数当中创建排雷函数:pai(lei,paicha);也就是将排查出来的雷放在paicha数组当中去;此处有10个雷,如果排查了71次没有失败,则是排雷成功,否则排雷失败。

//pai(lei, paicha, Hang, Lie);

void pai(char d[hang][lie], char e[hang][lie], int h, int l)
{
	int x, y;
	int win = 0;
	while (win<h*l-nums_mine)
	{
		printf("\n请输入要排查的坐标(中间用空格隔开)\n");
		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= h && y >= 1 && y <= l)
		{
			if (e[x][y] == '*')
			{
				if (d[x][y] == 1)
				{
					printf("\n您踩雷了,游戏结束\n");
					dayin(d, h, l);
				}
				else {
					int count = get_mine(d, x, y);
					e[x][y] = count + '0';
					dayin(e, Hang, Lie);
					win++;
				}
			}
		}
		else
			printf("坐标非法,请重新输入\n");
	}
	if (win == h * l - nums_mine)
	{
		printf("\nyou win\n");
		dayin(e, Hang, Lie);
	}
}

玩家输入坐标x,y,如果非法,则重新输入,如果合法,则排雷后跳出循环。

这里使用get_mine函数来使x,y坐标处显示周为一格内的雷的数量;

count为整形数据,+上一个字符‘ 0 ’让结果换算为对应字符形式。 

我们之前用字符‘0’来初始化lei数组,现在除了雷,其余元素全部为字符‘0’,在get_mine 当中,我们把x,y坐标周围一格内的雷加起来转化为对应数字,于是就得到了x,y周围雷的数量:

int  get_mine(char v[hang][lie], int x, int y)
{
	return (v[x - 1][y    ] + v[x - 1][y - 1] + v[x - 1][y + 1]
		  + v[x    ][y - 1] + v[x    ][y + 1]
		  + v[x + 1][y - 1] + v[x + 1][y    ] + v[x + 1][y + 1])-8*'0';
}

输入坐标2,3,结果如图; 

 

至此整个扫雷就初步完成了。 

 

 

 

 

 

 

 


网站公告

今日签到

点亮在社区的每一天
去签到