C语言---扫雷(Minesweeper)

news2024/12/29 13:18:41

扫雷

  • 1 了解扫雷游戏
    • 1.1 基本规则
    • 1.2 基础知识
      • 1.2.1字符相减
  • 2 实现过程
    • 1.1 棋盘设定
    • 1.2 初始化棋盘
    • 1.3 打印棋盘
    • 1.4 放置雷
    • 1.5 排查雷
    • 1.6 game()函数
  • 3 完整代码
    • 3.1 Minesweeper.h
    • 3.2 Minesweeper.c
    • 3.3 Test.c
  • 4 参考


1 了解扫雷游戏

点击右侧进入扫雷游戏网页版
在这里插入图片描述

1.1 基本规则

盘面上有许多方格,方格中随机分布着一些雷。你的目标是避开雷,打开其他所有格子。一个非雷格中的数字表示其相邻8格中的雷数,你可以利用这个信息推导出安全格和雷的位置。
例如,下图中“3”表示周围坐标8个坐标中有1个雷。“1”表示周围8个坐标有1个雷。
在这里插入图片描述

1.2 基础知识

C语言数组,函数封装,for循环,while循环

1.2.1字符相减

‘1’-‘0’–>1 ‘0’-‘0’–>0
字符1减去字符0,根据ASSIC码相加减,结果就是数字1

在这里插入图片描述
在这里插入图片描述

2 实现过程

1.1 棋盘设定

假设在一个99的方格,放10个雷。在棋盘的边界,为了简化代码逻辑,设置1111的方格,防止越界。
如下图,右下角这个必然是雷,两个边界的“1”依旧按照周围8方格来思考,实际上只要考虑5个方格,边界外3个方格必然不是雷。
在这里插入图片描述

//定义展示出来棋盘的大小
#define ROW 9
#define COL 9

//定义设置棋盘的大小
//处理边界问题
#define ROWS ROW+2
#define COLS COL+2

//定义难度
#define EASY_COUNT 10

1.2 初始化棋盘

创建9*9的数组,是布置好的雷的信息。假设是地雷,数组存放1,不是雷,存放0。边界防止越界,行列各自加2

char mine[ROWS][COLS];//放置雷的信息,初始化‘0’,mine 数组在没有布置雷的时候,都是'0'
char show[ROWS][COLS];//排查雷的信息,初始化‘*’,show 数组在没有排查雷的时候,都是'*',
//网页版扫雷是一个空白方块,这里设定成了"*"

我们准备了两份数组,一个放置雷的信息,一个排查雷的信息。
方格初始化成什么?是0还是*,所以说可以再添加一个参数,设定为set
初始化棋盘,就是在11*11的棋盘,填入设定好的set信息。

//1 初始化棋盘的函数
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}

1.3 打印棋盘

我们要展示出99的棋盘,而实际的棋盘是1111
传递数组,依旧是ROWS,不是ROW
打印九行九列,限制for起始值,
考虑到易找到行列号,打印的时候还要在第一行和第一列打印1-9

//2 打印棋盘的函数
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------扫雷游戏的上边界-----\n");
	for (j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------扫雷游戏的下边界-----\n");

}

在这里插入图片描述

1.4 放置雷

要设置地雷的个数,提前准备#define EASY_COUNT 10
填入地雷又需要随机数的生成,利用rand()实现。
我们约定,假设是地雷,数组存放1,不是雷,存放0。
SetMine(mine, ROW, COL);
实现这个函数,用while函数,找到合法坐标,在“0”上放置雷,然后雷的数目递减

//3 放置雷的函数
void SetMine(char board[ROWS][COLS], int row, int col)
{
	//放置10个雷
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

确定三次随机生成的雷位置不同

1.5 排查雷

输入排查雷的坐标注意越界问题,输入错误,重新输入,采用while循环
‘1’-‘0’–>1 ‘0’-‘0’–>0 字符1减去字符0,根据ASSIC码相加减,结果就是数字1
排查过的坐标不再排查,未被排查再进行以下逻辑
如果是雷,展示排查雷的棋盘,游戏结束。
如果不是雷,记录周围地雷的个数
验证游戏通关的时候更改EASY_COUNT个数,验证排雷成功
统计mine数组中x,y坐标周围有几个雷,需要将数字转换成数字字符。

x-1,y-1x-1,yx-1,y+1
x,y-1x,yx,y+1
x+1,y-1x,y+1x+1,y+1
//4 排查雷的函数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y] 
		+ board[x - 1][y - 1] 
		+ board[x][y - 1] 
		+ board[x + 1][y - 1] 
		+ board[x + 1][y] 
		+ board[x + 1][y + 1] 
		+ board[x][y + 1] 
		+ board[x - 1][y + 1] 
		- 8 * '0');
}

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("请输入要排查的坐标:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				printf("该坐标被排查过了,不能重复排查\n");
			}
			else
			{
				//如果是雷
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了\n");
					DisplayBoard(mine, ROW, COL);
					break;
				}
				else//如果不是雷
				{
					win++;
					//统计mine数组中x,y坐标周围有几个雷
					int count = get_mine_count(mine, x, y);
					show[x][y] = count + '0';//转换成数字字符
					DisplayBoard(show, ROW, COL);
				}
			}
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

验证通关,只要把雷数目调整为80,再展示排查雷的信息的棋盘,就验证通过代码了。
在这里插入图片描述

1.6 game()函数

void game()
{
	char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
	//初始化数组的内容为指定的内容
	//mine 数组在没有布置雷的时候,都是'0'
	InitBoard(mine, ROWS, COLS, '0');
	//show 数组在没有排查雷的时候,都是'*'
	InitBoard(show, ROWS, COLS, '*');

	//设置雷
	SetMine(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);
	
	//玩游戏的时候注释下一行代码,测试的时候开启下一行代码
	DisplayBoard(mine, ROW, COL);

	//排查雷
	FindMine(mine, show, ROW, COL);
}

3 完整代码

3.1 Minesweeper.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS


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

//定义展示出来棋盘的大小
#define ROW 9
#define COL 9

//定义设置棋盘的大小
//处理边界问题
#define ROWS ROW+2
#define COLS COL+2

//定义难度
#define EASY_COUNT 10
#define MEDIUM_COUNT 30
#define TEXT_COUNT 50


//1 初始化棋盘的函数
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//2 打印棋盘的函数
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//3 放置雷的函数
void SetMine(char board[ROWS][COLS], int row, int col);
//4 排查雷的函数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);


3.2 Minesweeper.c

#include "Minesweeper.h"
//1 初始化棋盘的函数
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}

//2 打印棋盘的函数
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------扫雷游戏的上边界-----\n");
	for (j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------扫雷游戏的下边界-----\n");

}

//3 放置雷的函数
void SetMine(char board[ROWS][COLS], int row, int col)
{
	//放置10个雷
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;

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

//4 排查雷的函数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y] 
		+ board[x - 1][y - 1] 
		+ board[x][y - 1] 
		+ board[x + 1][y - 1] 
		+ board[x + 1][y] 
		+ board[x + 1][y + 1] 
		+ board[x][y + 1] 
		+ board[x - 1][y + 1] 
		- 8 * '0');
}

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("请输入要排查的坐标:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				printf("该坐标被排查过了,不能重复排查\n");
			}
			else
			{
				//如果是雷
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了\n");
					DisplayBoard(mine, ROW, COL);
					break;
				}
				else//如果不是雷
				{
					win++;
					//统计mine数组中x,y坐标周围有几个雷
					int count = get_mine_count(mine, x, y);
					show[x][y] = count + '0';//转换成数字字符
					DisplayBoard(show, ROW, COL);
				}
			}
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

3.3 Test.c

#include "Minesweeper.h"

void menu()
{
	printf("*************************\n");
	printf("*****   1. 开始游戏   ****\n");
	printf("*****   0. 退出游戏   ****\n");
	printf("*************************\n");
}

void game()
{
	char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
	//初始化数组的内容为指定的内容
	//mine 数组在没有布置雷的时候,都是'0'
	InitBoard(mine, ROWS, COLS, '0');
	//show 数组在没有排查雷的时候,都是'*'
	InitBoard(show, ROWS, COLS, '*');

	//设置雷
	SetMine(mine, ROW, COL);

	DisplayBoard(show, ROW, COL);

	//玩游戏的时候注释下一行代码
	//测试的时候开启下一行代码
	//DisplayBoard(mine, ROW, COL);

	//排查雷
	FindMine(mine, show, ROW, COL);
}

int main()
{
	int input = 0;
	//设置随机数的生成起点
	srand((unsigned int)time(NULL));

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);

	return 0;
}

4 参考

【比特鹏哥c语言2023完整版视频教程】P65 65.扫雷

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

性能测试能力提升 —— 线程、并发、吞吐量、TPS、QPS、响应时间

一、背景 接着上一篇的知识&#xff1a;性能测试能力提升-关于性能测试&#xff0c;本篇文章&#xff0c;我们将主要介绍以下几方面的知识&#xff1a; 线程数&并发用户数相对并发&绝对并发吞吐量TPS&QPS响应时间 二、线程数、并发用户数 线程数: 主流的性能测…

【ArcGIS微课1000例】0083:地震灾害图件制作之土壤类型分布图

本文基于1:400万矢量土壤图,制作甘肃积石山6.2级地震100km范围内土壤类型分布图。 文章目录 一、土壤分布图预览二、数据集来源及简介三、土壤分布图制作一、土壤分布图预览 二、数据集来源及简介 1. 数据来源 数据集为1:400万中国土壤图,1:400万中国土壤图(2000)由中国科…

dp专题7 分割等和子集

本题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目&#xff1a; 思路&#xff1a; 由题意&#xff0c;题目意思是给出 数组 nums 找出两个子集它们的元素和相等。 这里两个自己的元素和相等&#xff0c;说明需要 数组 nu…

PyQt5-控件之QDialog(UI-业务分离搭建自定义xDialog)

1.继承QtWidgets.QWidget自定义对话框 继承于QtWidgets.QWidget自定义一个对话框类&#xff1a;SelectingDlg class SelectingDlg(QtWidgets.QWidget): def __init__(self): super(SelectingDlg, self).__init__() self.initUI() def initUI(self):s…

上网行为管理系统丨上网行为管理一体化解决方案

随着互联网的普及和发展&#xff0c;企业的网络安全和员工的行为管理已经成为了一个重要的问题。为了解决这个问题&#xff0c;上网行为管理一体化解决方案应运而生。本文将深入探讨上网行为管理一体化解决方案的背景、概念、重要性、实现方式和未来发展等方面。 一、概念 上网…

守正出奇,穿越周期 - Bytebase 的 2023

前情提要&#xff1a;Bytebase 的 2022&#xff5c;埋头苦干&#xff0c;孕育希望 产品迭代 2023 年共发布了 25 个版本。这个数字和 2022 年一样&#xff0c;除开春节和一次全员疫情&#xff0c;做到了两周一次的更新。 版本号从 1.11.0 升级到了 2.13.0。其中在 5 月份&…

25W以下室内照明应用解决方案:SM2188EN符合新ERP认证标准

随着LED照明技术的不断发展&#xff0c;室内照明领域的需求也在不断增加。针对25W以下室内照明应用&#xff0c;LED驱动芯片SM2188EN是一款新型的解决方案&#xff0c;符合最新的ERP认证标准&#xff0c;能够满足用户对照明产品高效、节能、稳定的需求。 SM2188EN方案原理图 L…

TDD-LTE TAU流程

目录 1. TAU成功流程 1.1 空闲态TAU 1.2 连接态TAU 2. TAU失败流程 当UE进入一个小区&#xff0c;该小区所属TAI不在UE保存的TAI list内时&#xff0c;UE发起正常TAU流程&#xff0c;分为IDLE和CONNECTED&#xff08;即切换时&#xff09;下。如果TAU accept分配了一个新的…

web自动化(5)——关键字驱动

PO 模型会增加测试脚本的编写复杂度&#xff0c;尤其是当测试项目规模较大或者业务逻辑较为复杂时&#xff0c;需要编写大量的 Page Object 类&#xff0c;或者一旦我们的项目发生变动甚至更换项目时&#xff0c;就需要大量修改原来的代码&#xff0c;增加了项目的维护成本。关…

合并数组或对象的几种方法

1.两个数组对象合入一起 const cc [{id: 1,age: 80岁,name: 444,},{id: 1,age: 804岁,name: 2,},{id: 1,age: 803岁,name: 3,},{id: 1,age: 830岁,name: 33,},{id: 1,age: 1022220岁,name: 白龙马111111111,}, ] const reslutList [{id: 1,age: age,name: 唐曾,},{id: 1,age…

windows无命令升级降级node版本

1. node最新版本下载链接 点击最新下载链接&#xff0c;找到对应版本下载并解压 2. 通过命令where node找到node.exe位置 3. 将该位置的node.exe替换为下载解压的最新node.exe 4. 重新执行node -v查看版本 --------------------------------------------------------------…

论文解读:A New CNN Building Block for Low-ResolutionImages and Small Objects

引言 之前通过stride和pooling这些下采样操作&#xff0c;但是这些操作都会或多或少丢失图像的信息&#xff0c;所以这不适用于具有低分辨率图像和小物体的更困难的任务上。像池化选择maxpooling或者是averagepooling、卷积的步长(太大的话会丢失信息)都是很头疼的问题&#x…

QT登录功能开发

登录功能 1选择无按钮的dialog 2登录函数 #include <QApplication> #include <QDialog> #include <QFormLayout> #include <QLineEdit> #include <QPushButton> #include <QMessageBox>class LoginDialog : public QDialog { public:Log…

Axure软件大全:原型设计下载与学习指南!

Axure可以有效地创建原型&#xff0c;包括绘制APP和网页的原型图、框架图、结构图等。Axure内置的小部件可以用来构建动态交互。即使新手设计师不懂程序代码&#xff0c;也可以在Axure中创建复杂、动态、功能丰富的原型。对于想要深入研究和花时间学习程序的设计师来说&#xf…

LeetCode74二分搜索优化:二维矩阵中的高效查找策略

题目描述 力扣地址 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&…

Android静态代码检查及自定义Lint实现

概述 在日常的项目开发迭代中&#xff0c;相信每个人对与代码质量都是有着高要求的。但是&#xff0c;在所有事情中&#xff0c;人往往就是其中最大的变量因素&#xff0c;个人各异&#xff0c;如何去保障代码质量以及统一规范呢&#xff1f;开发团队也许会严格要求Code-Review…

如何使用Node.js快速创建本地HTTP服务器并实现公网访问服务端

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

抖店新手该如何运营?

我是电商珠珠 在抖店开好之后&#xff0c;大部分新手都不知道怎么去运营&#xff0c;今天&#xff0c;我就来给大家详细的讲一下。 第一步&#xff0c;店铺基础设置 我一直跟我的学生讲&#xff0c;一定要懂基本流程&#xff0c;只有前期将流程跑通了后期才可以毫无压力。 …

css 保持元素宽高比 随页面宽度变化高度自适应

目录 1.效果展示 2.代码内容 3.代码解析 &#xff08;1&#xff09;分析inner类写法 &#xff08;2&#xff09;分析container类写法 1.效果展示 2.代码内容 <div class"item"><div class"inner"><di class"container">…

LED显示屏恒流驱动芯片的功能特点

LED显示屏恒流驱动芯片是一种电子器件&#xff0c;用于控制和驱动LED显示屏。由于LED显示屏通常由大量LED灯珠组成&#xff0c;因此需要使用恒流驱动芯片来确保每个LED灯珠都能够正常、均匀地发光&#xff0c;并且能够控制显示的色彩和亮度。 SM16380SF 恒流驱动芯片通常具有以…