扫雷(升级版)附全代码

     上次我写了简单版本的扫雷(建议看一下扫雷【C语言】-CSDN博客),但是有些功能并没有实现。比如:

  1. 没有如果排查位置不是雷,可以展开周围的功能。
  2. 没有标记的功能。

     在这篇中这些功能都会被实现。

文章目录

展开

标记

适配

扫雷全代码

game.h

game.c

test.c


展开

     展开是用递归解决的。

     当传入一个非雷坐标时,检查周围8个格子包括它。在让xing数组的该位置等于First_difference函数的返回值。如果函数的返回值存在0那么就再次调用展开函数。如果不存在则不调用。

在完成该函数中有几个要注意的条件。

  1. 检查坐标是否在有效范围内。
  2. 不要把*后的雷给替换。
  3. 不要出现死递归(当i==x,j==y时可能会出现)。
//展开
void unfold(char digital[lines][columns], char xing[lines][columns], int x, int y)
{
	for(int i = x - 1; i <= x + 1; i++)
	{
		for (int j = y - 1; j <= y + 1; j++)
		{
			if ((i <= line && i >= 1) && (j <= column && j >= 1))//检查是否是有效范围
			{
				char r = First_difference(digital, i, j);//检查周围雷数
				if (digital[i][j] != '!')//防止把*后是雷给替换
				{
					if (r == 0 && xing[i][j] != '0')//是0继续排查周围且防止出现死递归
					{
						xing[i][j] = r + 48;//+48变成字符数字
						unfold(digital, xing, i, j);//递归
					}
					else
					{
						xing[i][j] = r + 48;
					}	
				}
			}
		}
	}
}

标记

     标记就比较简单了。

     要先判断是否要标记,在Minesweeping函数的else中加入下面这段代码。

char b = 0;
printf("是否要标记(Y/N):");
getchar();//用来消除缓冲区中的'\n',防止b的输入发生问题。 
scanf("%c", &b);
mark(xing, b);

     这里我的标记是用' + '作为标记字符。取消标记的代码和标记的代码一样,只不过取消标记是把' + '变成' * '。

//标记
int key = 0;//这里key是全局变量
void mark(char xing[lines][columns], int n)
{
    char s = 0;
	int i = 0;
	int j = 0;
	//标记
	if (n == 89 || n == 121)//Y,y都行
	{
		key++;
		printf("请选择你要标记的坐标:");
        getchar();
		scanf("%d %d", &i, &j);
		xing[i][j] = '+';
	}
	//取消标记
	if (key > 0 && key--)//确保标记次数和取消标记次数统一
	{
		printf("是否要取消标记d(Y/N):");
		getchar();
		scanf("%c", &s);
		if (s == 89 || s == 121)
		{
			printf("请选择你要取消标记的坐标:");
            getchar();
			scanf("%d %d", &i, &j);
			xing[i][j] = '*';
		}
	}
}

适配

     新添加函数后原来的Minesweeping函数就会有一些不合理的地方需要改。不过在此之前展开函数需要改改。在标记一个位置后展开的过程中可能会把标记给替换。怎么改呢?

     其实只要在检查周围雷数后加上 xing[i][j] != ' + ' 即可。

//展开
void unfold(char digital[lines][columns], char xing[lines][columns], int x, int y)
{
	for(int i = x - 1; i <= x + 1; i++)
	{
		for (int j = y - 1; j <= y + 1; j++)
		{
			if ((i <= line && i >= 1) && (j <= column && j >= 1))
			{
				char r = First_difference(digital, i, j);
				if (xing[i][j] != '+')//新加的
				{
					if (digital[i][j] != '!')
					{
						if (r == 0 && xing[i][j] != '0')
						{
							xing[i][j] = r + 48;
							unfold(digital, xing, i, j);
						}
						else
						{
							xing[i][j] = r + 48;
						}
					}
					
				}
			}
		}
	}
}

     现在我们就改改Minesweeping函数。以前的循环结束条件不能用了,直接写一个死循环因为我们并不知道什么时候循环结束。失败以前的可以用,那该怎么判断成功呢?

     其实只要遍历一遍xing数组看看有几个' * '和' + '。如果它们等于雷数就跳出。

//排查雷
void Minesweeping(char digital[lines][columns], char xing[lines][columns], int Line, int Column)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请选择你要排查的坐标:");
		scanf("%d %d", &x, &y);
		if (digital[x][y] == '!')
		{
			printf("很遗憾你死了,雷分布如下。注:!是雷\n");
			Print(digital, line, column);
			break;
		}
		else
		{
			char b = 0;
			unfold(digital, xing, x, y);
			printf("是否要标记(Y/N):");
			getchar();
			scanf("%c", &b);
			mark(xing, b);
			Print(xing, line, column);
		}
        //判断成功条件
		int num = 0;
		for (int m = 1; m <= Line; m++)
		{
			for (int n = 1; n <= Column; n++)
			{
				if (xing[m][n] == '*' || xing[m][n] == '+')
				{
					num++;
				}
			}
		}
		if (thunder == num)
		{
			printf("恭喜你通过了!!!\n");
			break;
		}
	}	
}

扫雷全代码

game.h

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

//行
#define line 9
//列
#define column 9

#define lines line + 2
#define columns column + 2

//雷
#define thunder 10

//初始化棋盘
void Initialize(char function[lines][columns], int Lines , int Columns, char n);		

//打印棋盘
void Print(char function[lines][columns], int Line, int Column);

//埋雷
void Bury(char function[lines][columns], int Line, int Column);

//周围雷数
char First_difference(char digital[lines][columns], int x, int y);

//展开
void unfold(char digital[lines][columns], char xing[lines][columns], int x, int y);

//标记
void mark(char xing[lines][columns], int n);

//排查雷
void Minesweeping(char digital[lines][columns], char xing[lines][columns], int Line, int Column);

game.c

#include "game.h"

//初始化棋盘
void Initialize(char function[lines][columns], int Lines, int Columns, char n)
{
	for (int i = 0; i < Lines; i++)
	{
		for (int j = 0; j < Columns; j++)
		{
			function[i][j] = n;
		}
	}
	
}

//打印棋盘
void Print(char function[lines][columns], int Line, int Column)
{
	printf("--------扫雷-------\n");
	int b = 1;
	for (int k = 0; k <= Line; k++)
	{
		printf("%d ", k);
	}
	printf("\n");
	for (int i = 1; i <= Line ; i++)
	{
		printf("%d ", b);
		for (int j = 1; j <= Column ; j++)
		{
			printf("%c ", function[i][j]);
		}
		b++;
		printf("\n");
	}
}

//埋雷
void Bury(char function[lines][columns], int Line, int Column)
{
	int num = thunder;
	while (num)
	{
		int x = rand() % line + 1;
		int y = rand() % column + 1;
		if (function[x][y] == '"')
		{
			function[x][y] = '!';
			num--;
		}
	}
}

//周围雷数
char First_difference(char digital[lines][columns], int x, int y)
{
	return (digital[x - 1][y - 1] + digital[x - 1][y] + 
			digital[x - 1][y + 1] + digital[x][y - 1] + 
			digital[x][y + 1] + digital[x + 1][y - 1] + 
			digital[x + 1][y] + digital[x + 1][y + 1] - 34 * 8) * -1;
}

//展开
void unfold(char digital[lines][columns], char xing[lines][columns], int x, int y)
{
	for(int i = x - 1; i <= x + 1; i++)
	{
		for (int j = y - 1; j <= y + 1; j++)
		{
			if ((i <= line && i >= 1) && (j <= column && j >= 1))
			{
				char r = First_difference(digital, i, j);
				if (xing[i][j] != '+')
				{
					if (digital[i][j] != '!')
					{
						if (r == 0 && xing[i][j] != '0')
						{
							xing[i][j] = r + 48;
							unfold(digital, xing, i, j);
						}
						else
						{
							xing[i][j] = r + 48;
						}
					}
					
				}
			}
		}
	}
}

//标记
int key = 0;
void mark(char xing[lines][columns], int n)
{
	char s = 0;
	int i = 0;
	int j = 0;
	if (n == 89 || n == 121)
	{
		key++;
		printf("请选择你要标记的坐标:");
		getchar();
		scanf("%d %d", &i, &j);
		xing[i][j] = '+';
	}
	if (key > 0 && key--)
	{
		printf("是否要取消标记d(Y/N):");
		getchar();
		scanf("%c", &s);
		if (s == 89 || s == 121)
		{
			printf("请选择你要取消标记的坐标:");
			getchar();
			scanf("%d %d", &i, &j);
			xing[i][j] = '*';
		}
	}
}

//排查雷
void Minesweeping(char digital[lines][columns], char xing[lines][columns], int Line, int Column)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请选择你要排查的坐标:");
		scanf("%d %d", &x, &y);
		if (digital[x][y] == '!')
		{
			printf("\n");
			printf("很遗憾你死了,雷分布如下。注:!是雷\n");
			Print(digital, line, column);
			break;
		}
		else
		{
			char b = 0;
			unfold(digital, xing, x, y);

			printf("是否要标记(Y/N):");
			getchar();
			scanf("%c", &b);
			mark(xing, b);
			Print(xing, line, column);
		}
		int num = 0;
		for (int m = 1; m <= Line; m++)
		{
			for (int n = 1; n <= Column; n++)
			{
				if (xing[m][n] == '*')
				{
					num++;
				}
			}
		}
		if (thunder == num)
		{
			printf("恭喜你通过了!!!\n");
			break;
		}
	}	
}

test.c

#include "game.h"

void test()
{
	//创建数组
	char xing[lines][columns] = { 0 };
	char digital[lines][columns] = { 0 };
	//初始化
	Initialize(digital, lines, columns, '"');
	Initialize(xing, lines, columns, '*');
	//埋雷
	Bury(digital, line, column);
	//打印
	Print(xing, line, column);
	//排雷
	Minesweeping(digital, xing, line, column);
}

int main()
{
	srand((unsigned int)time(NULL));
	test();
	return 0;
}

     以上就是主要本篇内容,如果有什么不懂的可以私信我,如果有什么错误请你指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/593125.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

设计模式——行为型模式——策略模式

策略模式 定义 策略模式定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以相互替换&#xff0c;且算法的变化不会影响使用算法的客户。 策略模式属于对象行为模式&#xff0c;它通过对算法进行封装&#xff0c;把使用算法的责任和算法的实现分割开来&a…

【ARM Cortex-M3指南】3:Cortex-M3基础

文章目录 三、Cortex-M3基础3.1 寄存器3.1.1 通用目的寄存器 R0~R73.1.2 通用目的寄存器 R8~R123.1.3 栈指针 R133.1.4 链接寄存器 R143.1.5 程序计数器 R15 3.2 特殊寄存器3.2.1 程序状态寄存器3.2.2 PRIMASK、FAULTMASK和BASEPRI寄存器3.2.3 控制寄存器 3.3 操作模式3.4 异常…

# 在 Windows 命令提示符(cmd)中,可以通过以下方法设置长命令自动换行

在 Windows 命令提示符&#xff08;cmd&#xff09;中&#xff0c;可以通过以下方法设置长命令自动换行 1、点击 cmd 窗口左上角标题栏&#xff0c;选择【属性】。 2、在【属性】菜单中&#xff0c;依次点击【选项】&#xff0c;找到【编辑选项】下面的【自动换行】&#xff…

经纬度聚类:聚类算法比较

需求&#xff1a; 将经纬度数据&#xff0c;根据经纬度进行聚类 初始数据 data.csv K均值聚类 简介 K均值&#xff08;K-means&#xff09;聚类是一种常用的无监督学习算法&#xff0c;用于将数据集中的样本分成K个不同的簇&#xff08;cluster&#xff09;。其基本思想是…

OpenCV | 入门

OpenCV | 入门 安装 参考教程 基础知识 V G A 640 480 VGA 640 \times 480 VGA640480 H D 1280 720 HD 1280 \times 720 HD1280720 F H D 1920 1080 FHD 1920 \times 1080 FHD19201080 4 K 3840 2160 4K 3840 \times 2160 4K38402160 这些都表示了固定的像素…

AI-数学-高中52-离散型随机变量概念及其分布列、两点分布

原作者视频&#xff1a;【随机变量】【一数辞典】2离散型随机变量及其分布列_哔哩哔哩_bilibili 离散型随机变量分布列&#xff1a;X表示离散型随机变量可能在取值&#xff0c;P:对应分布在概率&#xff0c;P括号里X1表示事件的名称。 示例&#xff1a;

机器学习的指标评价

之前在学校的小发明制作中&#xff0c;在终期答辩的时候&#xff0c;虽然整个项目的流程都答的很流畅。 在老师提问的过程中&#xff0c;当老师问我recall,precision,accuracy等指标是如何计算的&#xff0c;又能够表示模型的哪方面指标做得好。我听到这个问题的时候&#xff…

使用FPGA实现串-并型乘法器

介绍 其实我们知道&#xff0c;用FPGA实现乘法器并不是一件很简单的事&#xff0c;而且在FPGA中也有乘法器的IP核可以直接调用&#xff0c;我这里完全就是为了熟悉一些FPGA的语法然后写了这样一个电路。 串-并型乘法器模块 从字面上看&#xff0c;串-并乘法器就是其中一个乘数…

深入学习Redis(1):Redis内存模型

Redis的五个对象类型 字符串&#xff0c;哈希&#xff0c;列表&#xff0c;集合&#xff0c;有序集合 本节有关redis的内存模型 1.估算redis的内存使用情况 目前内存的价格比较的高&#xff0c;如果对于redis的内存使用情况能够进行计算&#xff0c;就可以选用合适的设备进…

初识webpack项目

新建一个空的工程 -> % mkdir webpack-project 为了方便追踪执行每一个命令&#xff0c;最终产生了哪些变更&#xff0c;将这个空工程初始化成git项目 -> % cd webpack-project/-> % git init Initialized empty Git repository in /Users/lixiang/frontworkspace/…

多级留言/评论的功能实现——SpringBoot3后端篇

目录 功能描述数据库表设计后端接口设计实体类entity 完整实体类dto 封装请求数据dto 封装分页请求数据vo 请求返回数据 Controller控制层Service层接口实现类 Mapper层Mybatis 操作数据库 补充&#xff1a;返回的数据结构自动创建实体类 最近毕设做完了&#xff0c;开始来梳理…

https自签名ssl证书生成流程

准备工作&#xff1a; 0.安装完整版的openssl openssl下载官网 安装到C:\OpenSSL32&#xff0c;也可以安装到其它盘&#xff0c;不要包含空格和中文 打开openssl.exe所在目录如:C:\OpenSSL32\bin&#xff0c;输入cmd.exe打开cmd控制台 1.创建ca文件夹 ,证书文件夹 mkdir …

二维泊松方程(三角形区域)Matlab有限元编程求解|案例源码+说明文本

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

【Linux 进程】 自定义shell

目录 关于shell 1.打印提示符&&获取用户命令字符​编辑 2.分割字符串 3.检查是否为内建命令 cd命令 export命令 echo命令 1.输出最后一个执行的命令的状态退出码&#xff08;返回码&#xff09; 2.输出指定环境变量 4.执行外部命令 关于shell Shell 是计算机操…

C语言数组介绍

文章目录 一、数组的概念二、一维数组1.一维数组的创建2.一维数组的初始化3.数组的类型4.一维数组的使用5.一维数组在内存中的存储6.sizeof计算数组元素个数 三、二维数组1.二维数组的概念2.二维数组的创建3.二维数组的初始化4.二维数组的使用5.二维数组的输入和输出6.二维数组…

【教学类-50-09】20240505“数一数”图片样式09:数一数(几何图案——透明颜色重叠+纯黑边框+黑框粗细)

背景需求&#xff1a; 【教学类-50-03】20240408“数一数”图片样式03&#xff1a;透明图形与边框不相交&#xff0c;透明图形和其他透明图形重叠-CSDN博客文章浏览阅读867次&#xff0c;点赞28次&#xff0c;收藏25次。【教学类-50-03】20240408“数一数”图片样式03&#xf…

银行ETL-监管报送

1104报表 1104报表主要包括&#xff1a;资产负债&#xff0c;表外业务、流动性风险、贷款质量、投向行业和地区、重点客户等。 1104报表分类 普通报表、机构特色类报表。 反洗钱 大额交易、可疑交易。标签分类&#xff1a;疑似犯罪、疑似毒品、疑似传销。 反洗钱—接口报…

tomcat+maven+java+mysql图书管理系统2-完善项目结构,添加相关依赖

1.创建java目录 接着选择java&#xff0c;回车&#xff0c;则创建成功&#xff0c;成功后在左侧栏能看见 2.修改pom.xml文件,(添加依赖) <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

pandas读取文件导致jupyter内核崩溃如何解决

读取execl文件出现以下问题: str_name "D:\\cao_use\\2017_2021(new).xlsx" train_df pd.read_excel(str_name, usecols[0])崩溃的指示图如下所示: bug原因:读入的文件太大&#xff0c;所需时间过长&#xff0c;在读取的过程中&#xff0c;使用中断按钮暂停会直…
最新文章