「C语言」扫雷

先上代码(main函数在测试.c)


头文件 游戏.h

#pragma once

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

//显示的行列
#define HANG 9
#define LIE 9

//真实的行列
#define HANG_JIA HANG + 2
#define LIE_JIA LIE + 2

//雷数
#define LEI_SHU 5

//菜单
void cai_dan(void);

//扫雷
void sao_lei(void);

//初始化
void chu_shi_hua(char shu_zu[HANG_JIA][LIE_JIA], int hang_jia, int lie_jia, char zi_fu);

//显示
void xian_shi(char shu_zu[HANG_JIA][LIE_JIA], int hang, int lie);

//布雷
void bu_lei(char an[HANG_JIA][LIE_JIA], int hang, int lie);

//排雷
void pai_lei(char ming[HANG_JIA][LIE_JIA], char an[HANG_JIA][LIE_JIA], int hang, int lie);

//探雷
void tan_lei(char ming[HANG_JIA][LIE_JIA], char an[HANG_JIA][LIE_JIA], int x, int y, int hang, int lie, int* z);

//周围雷的个数
int zhou_wei(char an[HANG_JIA][LIE_JIA], int x, int y);

源文件 游戏.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "游戏.h"

void cai_dan()
{
	printf("\n");
	printf("    输入1开始游戏\n");
	printf("    输入0退出游戏\n");
	printf("\n");
}

void sao_lei()
{
	//两个棋盘,一明一暗
	char ming[HANG_JIA][LIE_JIA] = { 0 };
	char an[HANG_JIA][LIE_JIA] = { 0 };

	chu_shi_hua(ming, HANG_JIA, LIE_JIA, '*');
	chu_shi_hua(an, HANG_JIA, LIE_JIA, '0');

	xian_shi(ming, HANG, LIE);
	//xian_shi(an, HANG, LIE);

	bu_lei(an, HANG, LIE);
	//xian_shi(an, HANG, LIE);

	pai_lei(ming, an, HANG, LIE);
}

//初始化
void chu_shi_hua(char shu_zu[HANG_JIA][LIE_JIA], int hang_jia, int lie_jia, char zi_fu)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < hang_jia; i++)
	{
		for (j = 0; j < lie_jia; j++)
		{
			shu_zu[i][j] = zi_fu;
		}
	}
}

//显示
void xian_shi(char shu_zu[HANG_JIA][LIE_JIA], int hang, int lie)
{
	int i = 0;
	int j = 0;

	//行号
	for (j = 0; j <= lie; j++)
	{
		printf("%d ", j);
	}
	printf("\n");

	for (i = 1; i <= hang; i++)
	{
		//列号
		printf("%d ", i);

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

//布雷
void bu_lei(char an[HANG_JIA][LIE_JIA], int hang, int lie)
{
	int lei_shu = LEI_SHU;

	while (lei_shu)
	{
		int x = rand() % hang + 1;
		int y = rand() % lie + 1;

		if (an[x][y] == '0')
		{
			an[x][y] = '1';
			lei_shu--;
		}
	}
}

//排雷
void pai_lei(char ming[HANG_JIA][LIE_JIA], char an[HANG_JIA][LIE_JIA], int hang, int lie)
{
	int x = 0;
	int y = 0;
	//成功排雷的个数z
	int z = 0;

	while (1)
	{
		printf("请输入需排查的坐标:");
		scanf("%d %d", &x, &y);

		if (x >= 1 && x <= hang && y >= 1 && y <= lie)
		{
			if (ming[x][y] == '*')
			{
				if (an[x][y] == '0')
				{
					tan_lei(ming, an, x, y, hang, lie, &z);
					xian_shi(ming, HANG, LIE);
					printf("扫除成功\n");
				}
				else
				{
					printf("不幸踩雷,扫雷失败\n");
					xian_shi(an, HANG, LIE);
					break;
				}
			}
			else
			{
				printf("坐标已排查过,请换一个坐标\n");
			}
		}
		else
		{
			printf("坐标错误,请重新输入\n");
		}

		if (z == HANG * LIE - LEI_SHU)
		{
			printf("所有雷均已扫除!\n");
			break;
		}
	}
}

//探雷
	void tan_lei(char ming[HANG_JIA][LIE_JIA], char an[HANG_JIA][LIE_JIA], int x, int y, int hang, int lie, int* z)
	{
		while (1)
		{
			if (x >= 1 && x <= hang && y >= 1 && y <= lie && ming[x][y] == '*' && an[x][y] == '0')
			{
				*z = *z + 1;

				if (zhou_wei(an, x, y) == 0)
				{
					ming[x][y] = ' ';
					tan_lei(ming, an, x - 1, y - 1, hang, lie, z);
					tan_lei(ming, an, x - 1, y, hang, lie, z);
					tan_lei(ming, an, x - 1, y + 1, hang, lie, z);
					tan_lei(ming, an, x, y - 1, hang, lie, z);
					tan_lei(ming, an, x, y + 1, hang, lie, z);
					tan_lei(ming, an, x + 1, y - 1, hang, lie, z);
					tan_lei(ming, an, x + 1, y, hang, lie, z);
					tan_lei(ming, an, x + 1, y + 1, hang, lie, z);
				}
				else
				{
					//数字加'0' = 对应的数字字符
					ming[x][y] = zhou_wei(an, x, y) + '0';
				}
			}

			break;
		}
	}

//周围雷的个数
int zhou_wei(char an[HANG_JIA][LIE_JIA], int x, int y)
{
	int i = 0;

	if (an[x - 1][y - 1] == '1')
		i++;
	if (an[x - 1][y] == '1')
		i++;
	if (an[x - 1][y + 1] == '1')
		i++;
	if (an[x][y - 1] == '1')
		i++;
	if (an[x][y + 1] == '1')
		i++;
	if (an[x + 1][y - 1] == '1')
		i++;
	if (an[x + 1][y] == '1')
		i++;
	if (an[x + 1][y + 1] == '1')
		i++;

	return i;
}

源文件 测试.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "游戏.h"

int main()
{
	srand((unsigned int)time(NULL));

	while (1)
	{
		cai_dan();

		int i = 0;
		printf("请选择:");
		scanf("%d", &i);

		if (i == 1)
		{
			sao_lei();
		}
		else if (i == 0)
		{
			printf("退出游戏成功\n");
			break;
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	}

	return 0;
}

运行截图


思路

三个文件,一个头文件,两个源文件,自定义头文件里放各种C语言自带的头文件(套娃)和自定义函数的声明。测试.c的源文件里就放了个main,游戏.c放各种自定义函数。 

1、开始菜单,很简单,直接打印就行了。

2、设置棋盘,为了之后计算周围雷的个数的时候数组不越界,数组设置的时候要大一圈。之后初始化,打印数组。

3、布雷,使用随机数随机布雷,注意对应数组下标。

4、排雷,根据输入坐标的不同,可以分为超出棋盘、已排查、踩雷、未踩雷几种情况,用if语句对应判断即可。

5、探雷,我是通过直接枚举周围8个数组元素,然后递归实现的,递归的时候要注意探查过的坐标就不要再探查了,不然会死递归。

好了,大概就这些。


总结 (・ ᴗ ・)

代码实现的效果已经和真实的扫雷非常接近了,但不足的地方还是有的,就是第一步可能会踩雷,而实际扫雷游戏中是不会的,日后可以改进。(但愿)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值