【c语言】扫雷

 前言:

扫雷是一款经典的单人益智游戏,它的目标是在一个方格矩阵中找出所有的地雷,而不触碰到任何一颗地雷。在计算机编程领域,扫雷也是一个非常受欢迎的项目,因为它涉及到许多重要的编程概念,如数组、循环、条件语句和函数等。

C语言是一种广泛使用的编程语言,它具有高效、灵活和可移植等特点,非常适合编写各种类型的应用程序。因此,使用C语言编写一个扫雷游戏是一个很好的学习编程的项目。

在这篇博客中,我们将介绍如何使用C语言编写一个简单的扫雷游戏。我们将从基本的编程概念开始讲解,逐步深入到更复杂的程序设计技术。我们还将提供完整的代码示例和详细的注释,以帮助读者更好地理解和掌握这个项目。

无论您是初学者还是有一定编程经验的开发者,相信通过阅读本篇博客,您都能够学到一些有用的知识和技巧。让我们一起来探索如何使用C语言编写一个令人兴奋的扫雷游戏吧!

前期准备:

先开一个test.c文件用来游戏的逻辑测试,在分别开一个game.c文件和game.h头文件用来实现游戏的逻辑

1. 主要步骤:

1.1 游戏规则:

输入1(0)开始(结束)游戏,输入一个坐标,如果该坐标不是雷则会显示该坐标周围有几个雷

1.2 打印菜单:

void menu()
{printf("----------------扫雷----------------\n");printf("|                                  |\n");printf("|              1.play              |\n");printf("|              0.exit              |\n");printf("|                                  |\n");printf("------------------------------------\n");
}
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");}} while (input);return 0;
}

1.3 打印棋盘:

写两个数组一个是用来打印给玩家看的棋盘,一个是用来放置炸弹的隐藏棋盘,等到游戏结束我们才会打印这个棋盘。然后我们给数组初始化,用*来初始化我们给玩家看的棋盘,用字符‘0’初始化隐藏棋盘。

   char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//初始化棋盘InitBoard(show, ROWS, COLS, '*');InitBoard(mine, ROWS, COLS, '0');//打印棋盘DisPalyBoard(show, ROW, COL);//DisPalyBoard(mine, ROW, COL);

1.4 打印行列:

因为我们是用坐标来选择排雷的,所以我们需要在棋盘的周围打印出行列才可以让玩家更好的去选择。

首先在打印棋盘for循环上方加上一个打印0~9的for循环就可以打印出棋盘的行了,然后用打印列的for循环套在打印棋盘的for循环上就可以打印出棋盘的列了。

​
void DisPalyBoard(char arr[ROWS][COLS], int row, int col)
{printf("------扫雷游戏------\n");​int i = 0;//打印行的for循环for (i = 0; i <= col; i++){printf("%d ", i);}printf("\n");//打印列的for循环for ( i = 1; i <= row; i++)  {printf("%d ", i);//打印棋盘的for循环for (int j = 1; j <= col; j++){printf("%c ", arr[i][j]);}printf("\n");}
}​

1.5 放置炸弹:

要想棋盘上随机分布十个炸弹(炸弹我们用字符‘1’定义),我们就需要生成随机数使数组的随机十个元素等于字符‘1’,而生成随机数就需要调用到前面我写猜数字游戏时讲过的rand函数、srand函数、time函数了。

void SetMine(char arr[ROWS][COLS], int row, int col)
{int count = EsayCount;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (arr[x][y] == '0')//防止生成相同随机数时,使多个炸弹放置在同一位置{arr[x][y] = '1';count--;}}
}

1.6 排查炸弹:

当我们输入一个坐标后如果时炸弹结束游戏,如果不是炸弹则需要显示炸弹的数量。

判断是否是炸弹只需写一个if语句判断该坐标中数组所对应的元素是否等于‘1’就行了。

显示周围有几个雷,我们就需要将所选坐标的周围的数加起来就可以了,这些加起来的数的和替换所选坐标的元素就可以了。

int GetMineCount(char mine[ROWS][COLS],int x,int y)
{return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1]+ mine[x + 1][y + 1] + mine[x - 1][y + 1] + mine[x - 1][y + 1] + mine[x][y + 1] - 8 * '0');
}

也可以用for循环统计

int GetMineCount(char mine[ROWS][COLS], int x, int y)
{int a = 0;for (int i = x - 1; i <= x + 1; i++){for (int j = y - 1; j <= y + 1; j++){a += mine[i][j];}}return a - '0' * 9;
}

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0, y = 0;int win = 0;while (win < row*col - EsayCount){printf("请输入要排查的坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisPalyBoard(mine, ROW, COL);break;}else{//该坐标不是雷,就得统计该坐标的周围有几个雷int count = GetMineCount(mine, x, y);show[x][y] = count + '0';DisPalyBoard(show, ROW, COL);win++;}}else{printf("坐标非法,请重新输入\n");}}if (win == row * col - EsayCount){printf("恭喜你,排雷成功\n");DisPalyBoard(mine, ROW, COL);}
}

1.7 周围没有雷就展开一片

首先需要判断所选坐标的周围是否有雷,即判断count是否等于0,如果所选坐标周围没有雷的话,就将此坐标的周围的坐标都调用显示雷的数量的函数。当然还需要判断一下坐标是否为‘*’,如果没有这个判断它就会重复的调用函数,从而进入了死循环。

void arr(char mine[ROWS][COLS], char show[ROWS][COLS], int x,int y)
{if (show[x][y] == '*'){int count = GetMineCount(mine, x, y);show[x][y] = count + '0';if (x >= 1 && x <= ROW && y >= 1 && y <= ROW){if (count == 0){arr(mine, show, x - 1, y);arr(mine, show, x - 1, y - 1);arr(mine, show, x - 1, y + 1);arr(mine, show, x, y - 1);arr(mine, show, x, y + 1);arr(mine, show, x + 1, y - 1);arr(mine, show, x + 1, y + 1);arr(mine, show, x + 1, y);}}}
}

1.8 计算游戏时间

time函数可以返回一个时间戳,我们可以利用这个函数计算游戏的时间。

int y = time(NULL);
while (1)
{system("cls");int x = time(NULL) - y;printf("%d", x);Sleep(1000);
}

1.9 游戏可改性

因为在写这个程序时需要输入很多的数字,如果我们想修改这些数时就要一个一个改,这样非常的麻烦。为了避免这些麻烦我们只需要在头文件定义某字符等于某个数字就可以了,这样我们想改游戏参数的时候在头文件game.h改就行了。

#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2
#define EsayCount 10

比如当我们想改行和列改为16炸弹数量改为40的时候,我们只需要在头文件将ROW 与 COL定义为16就可以了。

#define ROW 16
#define COL 16#define ROWS ROW+2
#define COLS COL+2
#define EsayCount 40

 

 1.10 控制台颜色的修改

使用system("color attr");函数可以修改控制台颜色,这个函数需要使用#include<windonws.h>调用。颜色可以参考下面这张图:

  例:
 

2. 完整代码

2.1 game.h头文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2
#define EsayCount 10//声明函数
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char test);
//
void DisPalyBoard(char arr[ROW][COL], int row, int col, int o);
//布置雷的信息
void SetMine(char arr[ROWS][COLS], int row, int col, int o);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int o);

 2.2 game.c文件

#include"game.h"
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){for (int j = 0; j < cols; j++){arr[i][j] = set;}}
}
void DisPalyBoard(char arr[ROWS][COLS], int row, int col,int o)
{//清屏system("cls");printf("-----------扫雷游戏----------\n");//计算时间printf("已用时间:%ds\n", time(NULL) - o);int i = 0;for (i = 0; i <= col; i++){printf("%2d ", i);}printf("\n");for (i = 1; i <= row; i++){printf("%2d ", i);for (int j = 1; j <= col; j++){printf("%2c ", arr[i][j]);}printf("\n");}
}void SetMine(char arr[ROWS][COLS], int row, int col)
{int count = EsayCount;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (arr[x][y] == '0'){arr[x][y] = '1';count--;}}
}int GetMineCount(char mine[ROWS][COLS], int x, int y)
{//return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] //	+ mine[x + 1][y + 1] + mine[x - 1][y + 1] + mine[x + 1][y] + mine[x][y + 1] - 8 * '0');int a = 0;for (int i = x - 1; i <= x + 1; i++){for (int j = y - 1; j <= y + 1; j++){a += mine[i][j];}}return a - '0' * 9;
}int win = 0;
void arr(char mine[ROWS][COLS], char show[ROWS][COLS], int x,int y)
{if (show[x][y] == '*'&& x >= 1 && x <= ROW && y >= 1 && y <= ROW){int count = GetMineCount(mine, x, y);show[x][y] = count + '0';win++;if (count == 0){arr(mine, show, x - 1, y);arr(mine, show, x - 1, y - 1);arr(mine, show, x - 1, y + 1);arr(mine, show, x, y - 1);arr(mine, show, x, y + 1);arr(mine, show, x + 1, y - 1);arr(mine, show, x + 1, y + 1);arr(mine, show, x + 1, y);}}
}void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int o)
{int x = 0, y = 0;while (win < row * col - EsayCount){printf("请输入要排查的坐标(0 0重开):>");scanf("%d %d", &y, &x);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){DisPalyBoard(mine, ROW, COL, o);printf("你被炸死了!!!\n");break;}else{//该坐标不是雷,就得统计该坐标的周围有几个雷arr(mine, show, x, y);DisPalyBoard(show, ROW, COL, o);}}else if (x == 0 && y == 0){printf("重新开始游戏。\n");break;}else{printf("坐标非法,请重新输入\a\n");}}if (win == row * col - EsayCount){DisPalyBoard(mine, ROW, COL, o);printf("恭喜你,排雷成功\n");}
}

2.3 test.c文件

#include"game.h"void menu()
{printf("----------------扫雷----------------\n");printf("|                                  |\n");printf("|              1.play              |\n");printf("|              0.exit              |\n");printf("|                                  |\n");printf("------------------------------------\n");
}void game()
{int o = time(NULL);//存放布置好雷的信息char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };InitBoard(show, ROWS, COLS, '*');InitBoard(mine, ROWS, COLS, '0');//随机布置10个雷SetMine(mine, ROW, COL, o);//打印棋盘/*DisPalyBoard(mine, ROW, COL,o);*/DisPalyBoard(show, ROW, COL, o);//排查雷FindMine(mine, show, ROW, COL, o);
}
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("输入错误请重新输入\a\n");}} while (input);return 0;
}

2.4 效果图:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Axios取消请求:AbortController

AbortController AbortController() 构造函数创建了一个新的 AbortController 实例。MDN官网给出了一个利用AbortController取消下载视频的例子。 核心逻辑是&#xff1a;利用AbortController接口的只读属性signal标记fetch请求&#xff1b;然后在需要取消请求的时候&#xff0…

php二次开发股票系统代码:腾讯股票数据接口地址、批量获取股票信息、转换为腾讯接口指定的股票格式

1、腾讯股票数据控制器 <?php namespace app\index\controller;use think\Model; use think\Db;const BASE_URL http://aaaaaa.aaaaa.com; //腾讯数据地址class TencentStocks extends Home { //里面具体的方法 }2、请求接口返回内容 function juhecurl($url, $params f…

蓝桥杯备战——2.矩阵键盘

1.分析原理图 由上图可以看到若J5跳线帽接地&#xff0c;就S4~S7就可以当做四路独立按键&#xff0c;若接到P44&#xff0c;则就是4*4的矩阵键盘。 2.独立按键处理 相对传统的按键延时消抖方案&#xff0c;这里我采用更高效&#xff0c;更经典&#xff0c;更偏向产品级应用的…

[bat]基于msg的弹窗提示

一、方案 1、定时自动消失的弹窗 代码&#xff1a; echo off echo method 1 msg * /time:5 "123456" REM echo method 2 REM msg * "123456"pause 效果&#xff1a; 立即弹窗在5秒后消失。 2、一直存在的弹窗 源码&#xff1a; echo off REM echo m…

Python基础之数据库操作

一、安装第三方库PyMySQL 1、在PyCharm中通过 【File】-【setting】-【Python Interpreter】搜索 PyMySQL进行安装 2、通过PyCharm中的 Terminal 命令行 输入: pip install PyMySQL 注&#xff1a;通过pip安装&#xff0c;可能会提示需要更新pip&#xff0c;这时可执行&#…

15- OpenCV:模板匹配(cv::matchTemplate)

目录 1、模板匹配介绍 2、cv::matchTemplate 3、模板匹配的方法&#xff08;算法&#xff09; 4、代码演示 1、模板匹配介绍 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。 它可以在一幅图像中寻找与给定模板最相似的部分。 模板匹配的步骤&#xff1a; &a…

Gradle学习笔记:Gradle的简介、下载与安装

文章目录 一、什么是Gradle二、为什么选择Gradle三、下载并安装Gradle四、Gradle的bin目录添加到环境变量五、测试Gradle是否安装正常 一、什么是Gradle Gradle是一个开源构建自动化工具&#xff0c;专为大型项目设计。它基于DSL&#xff08;领域特定语言&#xff09;编写&…

SpringCloud(二)

Spring Cloud 文章目录 Spring Cloud任务三&#xff1a;Spring Cloud与微服务架构1.Spring Cloud课程内容介绍2.单体应用架构2.1 互联网应用架构演进2.2 单体应用架构 3.垂直应用架构4.SOA应用架构5.微服务应用架构介绍6.微服务架构核心思想及优缺点7.微服务架构的核心概念8.Sp…

如何使用Jellyfin+cpolar搭建私人影音平台实现无公网ip远程访问

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

3d gaussian splatting介绍整理

3D 高斯分布是用于实时辐射场渲染的 3D 高斯分布中描述的一种光栅化技术&#xff0c;它允许实时渲染从小图像样本中学习到的逼真场景。 paper github 本文翻译整理自&#xff1a; blog: Introduction to 3D Gaussian Splatting DDPMs - Part 2 给出一些2D图片&#xff0c;用…

[实战]加密传输数据解密

前言 下面将分享一些实际的渗透测试经验&#xff0c;帮助你应对在测试中遇到的数据包内容加密的情况。我们将以实战为主&#xff0c;技巧为辅&#xff0c;进入逆向的大门。 技巧 开局先讲一下技巧&#xff0c;掌握好了技巧&#xff0c;方便逆向的时候可以更加快速的找到关键…

【iOS ARKit】人脸检测追踪基础

在计算机人工智能&#xff08;Artificial Inteligence,AI&#xff09;物体检测识别领域&#xff0c;最先研究的是人脸检测识别&#xff0c;目前技术发展最成熟的也是人脸检测识别。人脸检测识别已经广泛应用于安防、机场、车站、闸机、人流控制、安全支付等众多社会领域&#x…

Linux 一键部署grafana

grafana 前言 Grafana 是一款开源的数据可视化和监控仪表盘工具。它提供了丰富的数据查询、可视化和报警功能,可用于实时监控、数据分析和故障排除等领域。 通过 Grafana,您可以连接到各种不同的数据源,包括时序数据库(如 Prometheus、InfluxDB)和关系型数据库(如 MySQ…

UE创建数据资产 UDataAsset

UE创建数据资产 需要一个继承自UDataAsset的子类 在编辑器里创建后的效果 如果在子类中写多个集合 和 其它数据 所以数据资产在我觉得只是该子类的一个实例对象

C#用DateAndTime.DateDiff方法和TimeSpan分别计算时间间隔

目录 一、计算时间间隔的方法 1.用DateAndTime.DateDiff方法计算时间间隔 2.使用TimeSpan获取日期时间间隔 二、实例 1.示例一&#xff1a;用DateAndTime.DateDiff方法计算时间间隔 2.示例二&#xff1a;使用TimeSpan获取日期时间间隔 一、计算时间间隔的方法 1.用Date…

jar手动上传到Nexus私服

jar手动上传到Nexus私服 一简介二上传方法1.登录nexus,打开nexus控制台。upload---maven-release2.上传jar3.验证jar包是否上传成功4、注意事项 一简介 在maven项目中我们可以通过相关配置可以将项目打包成jar&#xff0c;然后deploy上传到私服中。要是别人提供的第三方jar&am…

图像处理------调整色调

什么是色调&#xff1f; 色调&#xff0c;在画面上表现思想、感情所使用的色彩和色彩的浓淡。分为暖色调和冷色调。 from cv2 import destroyAllWindows, imread, imshow, waitKey#创建棕褐色色调 def make_sepia(img, factor: int):pixel_h, pixel_v img.shape[0], img.shap…

【GitHub项目推荐--DiligentEngine: 一个开源跨平台的底层图形库和渲染框架】【转载】

Diligent Engine 一个现代的Cross-PlatformLow-Level三维图形库 Diligent引擎是一个轻量级的cross-platform图形API抽象库和呈现框架。它的设计充分利用了Direct3D12、Vulkan和Metal&#xff0c;同时通过Direct3D11、OpenGL和OpenGLES支持较旧的平台。Diligent引擎公开公共的f…

EtherNet/IP开发:C++开发CIP源代码

① 介绍一下CIP CIP是一种考虑到自动化行业而设计的通用协议。然而&#xff0c;由于其开放性&#xff0c;它可以并且已经应用于更多的领域。CIP网络库包含若干卷&#xff1a; 第1卷介绍了适用于所有网络自适应的CIP的常见方面。本卷包含通用对象库和设备配置文件库&#xff0…

数据采集与预处理01: 项目1 数据采集与预处理准备

数据采集与预处理01&#xff1a; 项目1 数据采集与预处理准备 任务1 认识数据采集技术&#xff0c;熟悉数据采集平台 数据采集&#xff1a;足够的数据量是企业大数据战略建设的基础&#xff0c;因此数据采集成为大数据分析的前站。数据采集是大数据价值挖掘中重要的一环&#…