当前位置: 首页 > news >正文

艾瑞网站建设/重庆网站seo建设哪家好

艾瑞网站建设,重庆网站seo建设哪家好,嵌入式软件开发怎么学,网站建设网址网站制作本篇博客会讲解,如何使用C语言实现扫雷小游戏。 0.思路及准备工作 使用2个二维数组mine和show,分别来存储雷的位置信息和排查出来的雷的信息,前者隐藏,后者展示给玩家。假设盘面大小是99,这2个二维数组都要开大一圈…

本篇博客会讲解,如何使用C语言实现扫雷小游戏。
扫雷

0.思路及准备工作

  1. 使用2个二维数组mine和show,分别来存储雷的位置信息和排查出来的雷的信息,前者隐藏,后者展示给玩家。假设盘面大小是9×9,这2个二维数组都要开大一圈,也就是大小是11×11,这是为了更加方便的数边角上雷的个数,防止越界。
  2. mine数组中用字符1表示雷,字符0表示非雷。show数组中用*表示该位置没有被排查过,数字字符表示周围一圈(8个位置)有几个雷,空格表示周围一圈没有雷,!表示该位置被标记了。
  3. 如果玩家排查的位置是雷,那么,游戏失败。当玩家把所有非雷的位置找出来后,扫雷成功。

先定义一些符号,后面会用。

// 扫雷盘面的有效区域大小
// 雷会在该区域中生成,玩家只能在该区域内排查或者标记雷
// 同时是实际展示的区域大小
#define ROW 9
#define COL 9// 实际的盘面大小
// 防止扫描周围8个坐标时出现越界访问
// 此时哪怕扫描有效区域的周围哪怕不进行判断也不会越界
// 因为最外面有一圈保护措施
#define ROWS   (ROW + 2)
#define COLS   (COL + 2)// 雷的个数
#define EASY_COUNT 10 // 简单难度

2个数组分别是:

// 存储雷的位置信息
// '1' - 雷
// '0' - 非雷
char mine[ROWS][COLS] = { 0 };// 展示给玩家的信息
// '*' - 未排查
// '1'~'9' - 该位置已被排查,且该位置周围有雷
// 数字字符表示周围雷的个数
// 空格 - 该位置已被排查,且该位置周围没有雷
// '!' - 该位置被玩家标记,可能是雷,也可能不是雷
// '!'所在位置并没有被排查,不算作已排查位置
char show[ROWS][COLS] = { 0 };

1.初始化

我们分别把mine和show数组初始化成全字符0和全*。可以利用二维数组在内存中连续存放的特点,使用memset函数来设置内存中的值。

void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{// board为二维数组,在内存中连续存放// 使用memset把rows*cols的空间初始化为setmemset(board, set, rows * cols * sizeof(char));
}

2.打印盘面

打印时使用2层循环来遍历二维数组,同时把行标和列标都打印出来。注意打印时,只需打印中间的9×9的位置,为了区分,我用rows和cols来表示多了一圈后的行和列,用row和col表示有效的盘面大小。

void PrintBoard(char board[ROWS][COLS], int row, int col)
{// 打印分割行printf("********* 扫雷 *********\n");// 打印列标,0是占位的for (int i = 0; i <= row; ++i){printf("%d ", i);}printf("\n");// 打印数据,每行前面打印行标for (int i = 1; i <= row; ++i){// 打印行标printf("%d ", i);// 打印数据for (int j = 1; j <= col; ++j){printf("%c ", board[i][j]);}printf("\n");}// 打印分割行printf("********* 扫雷 *********\n");
}

打印效果:
打印效果

3.设置雷

可以使用rand函数随机生成10个雷,注意如果该位置已经生成雷,就重新再生成坐标,不能重复。

void SetMine(char mine[ROWS][COLS], int row, int col)
{// 待放置的雷的个数int count = EASY_COUNT;// 布置雷while (count){// 产生随机坐标int x = rand() % row + 1; // 1~rowint y = rand() % col + 1; // 1~col// 该位置如果没有布置雷,则放雷if (mine[x][y] == '0'){mine[x][y] = '1';--count;}}
}

4.排查雷

排查雷的逻辑就相对复杂点了,这里我分以下几点来叙述。

  1. 使用GetMineCount函数来获取周围8个位置雷的个数。只需要把周围8个坐标的值加起来,由于都是字符’1’或字符’0’,还需要减去8个字符’0’,得到的就是字符’1’的个数。
  2. 使用如果满足递归条件,就递归展开。展开的思路是,如果该位置没有越界、自己不是雷、周围没有雷、且没有被排查过,则递归展开上下左右。
  3. 使用count变量来保存待排查的位置的个数,当count减到0,则排雷成功。
  4. 玩家输入排查的坐标后,需要分别检查是否合法、该位置是否被排查过、该位置是不是雷,如果检查过后不是雷,再进行正常的递归展开等。
  5. 如果玩家选择标记,若该位置未被排查过,可以切换标记状态。
// 获取x,y坐标周围8个位置的雷的个数
static int GetMineCount(char mine[ROWS][COLS], int x, int y)
{// 既然只有8个坐标,直接加起来就行了return mine[x - 1][y]    // 上+ mine[x - 1][y - 1] // 左上+ mine[x][y - 1]     // 左+ mine[x + 1][y - 1] // 左下+ mine[x + 1][y]     // 下+ mine[x + 1][y + 1] // 右下+ mine[x][y + 1]     // 右+ mine[x - 1][y + 1] // 右上- 8 * '0';
}// 我也不想设计这么多参数,但是似乎只能这样了,没想到更好的办法
// x,y为排查的坐标
// pcount指向count,count为玩家需要排查非雷位置的个数
// 当count减到0时,玩家扫雷成功
static void ShowMessage(char mine[ROWS][COLS], char show[ROWS][COLS],int row, int col, int x, int y, int* pcount)
{// 是否展开的判断if (x >= 1 && x <= row && y >= 1 && y <= col     // 坐标合法性判断&& mine[x][y] == '0'                         // 该坐标不是雷&& (show[x][y] == '*' || show[x][y] == '!')) // 该位置没有被排查过{// 获取周围8个坐标雷的个数int mineCount = GetMineCount(mine, x, y);// 判断周围有没有雷if (mineCount == 0) // 周围没有雷{show[x][y] = ' ';*pcount = *pcount - 1;// 递归展开ShowMessage(mine, show, row, col, x - 1, y, pcount); // 上ShowMessage(mine, show, row, col, x + 1, y, pcount); // 下ShowMessage(mine, show, row, col, x, y - 1, pcount); // 左ShowMessage(mine, show, row, col, x, y + 1, pcount); // 右}else // 周围有雷{show[x][y] = mineCount + '0';*pcount = *pcount - 1;}}
}// 若该位置未被排查,切换标记状态
// 若标记,则取消标记
// 若未标记,则标记
static void SignMine(char show[ROWS][COLS], int x, int y)
{if (show[x][y] == '!'){// 取消标记show[x][y] = '*';}else if (show[x][y] == '*'){// 标记show[x][y] = '!';}
}void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{// 坐标int x = 0;int y = 0;// 存储玩家输入的数据int input = 0;// 玩家需要排查的位置总数,即非雷的位置总数// 当count减到0时,玩家扫雷成功int count = row * col - EASY_COUNT;while (count){// 玩家输入坐标printf("请输入坐标:>");scanf("%d %d", &x, &y);// 判断坐标有效性if (x < 0 || x > row || y < 0 || y > col){printf("坐标非法,请重新输入\n");continue;}// 选择排查/标记while (1){printf("你想要排查(1)还是标记(0):>");scanf("%d", &input);// 判断输入有效性if (input == 0 || input == 1){break;}else{printf("选择错误,请重新选择\n");}}if (input == 1){// 排查// 检查该坐标是否已被排查过if (show[x][y] != '*' && show[x][y] != '!'){printf("该坐标已被排查过\n");}else if (mine[x][y] == '0') // 判断是否踩到雷{// 根据玩家排查的位置,显示雷的信息ShowMessage(mine, show, row, col, x, y, &count);PrintBoard(show, row, col);}else // 踩到雷了{printf("你踩到雷了,扫雷失败\n");break;}}else if (input == 0){// 标记SignMine(show, x, y);}}if (count == 0){printf("恭喜你,扫雷成功!\n");}
}

5.测试

// 打印菜单
void menu()
{printf("************************\n");printf("****** 1. play    ******\n");printf("****** 0. exit    ******\n");printf("************************\n");
}void game()
{// 存储雷的位置信息// '1' - 雷// '0' - 非雷char mine[ROWS][COLS] = { 0 };// 展示给玩家的信息// '*' - 未排查// '1'~'9' - 该位置已被排查,且该位置周围有雷// 数字字符表示周围雷的个数// 空格 - 该位置已被排查,且该位置周围没有雷// '!' - 该位置被玩家标记,可能是雷,也可能不是雷// '!'所在位置并没有被排查,不算作已排查位置char show[ROWS][COLS] = { 0 };// 初始化盘面InitBoard(mine, ROWS, COLS, '0'); // 初始化为全'0'InitBoard(show, ROWS, COLS, '*'); // 初始化为全'*'// 随机布置雷,只在有效区域内SetMine(mine, ROW, COL);// 打印盘面,只打印有效区域//PrintBoard(mine, ROW, COL);PrintBoard(show, ROW, COL);// 玩家排查雷FindMine(mine, show, ROW, COL);
}// 测试游戏的逻辑
void test()
{// 生成随机数生成器起点srand((unsigned int)time(NULL));int input = 0; // 存储玩家输入的数据do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:// 游戏的逻辑game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);
}int main()
{test();return 0;
}

总结

  1. 扫雷小游戏的实现,需要2个二维数组,需要了解二维数组的相关知识,比如在内存中的存储方式。
  2. 初始化盘面,利用二维数组在内存中连续存放的特点,使用memset一步到位。
  3. 打印盘面以及后面的一部分逻辑,遍历二维数组时使用2层for循环,是一个常见的思路。
  4. 设置雷的位置采用随机生成的方式,需要了解C语言如何生成随机数的知识点,我之前写过一篇博客讲解过。
  5. 排查雷时,需要通过反复的判断语句,防止玩家输入的坐标不满足需求。
  6. 尤其需要重点理解递归的思路,递归有限制条件,如该位置不是雷、周围没有雷、该位置没有越界、该位置没有被排查过等,同时不断趋近于限制条件,递归上下左右时一定会接近边界。
  7. 动手写!

感谢大家的阅读!

相关文章:

探秘C语言扫雷游戏实现技巧

本篇博客会讲解&#xff0c;如何使用C语言实现扫雷小游戏。 0.思路及准备工作 使用2个二维数组mine和show&#xff0c;分别来存储雷的位置信息和排查出来的雷的信息&#xff0c;前者隐藏&#xff0c;后者展示给玩家。假设盘面大小是99&#xff0c;这2个二维数组都要开大一圈…...

Leetcode112. 路径总和

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 t…...

生成12位短id,自增且不连续,永不重复,不依赖数据库

基本思路&#xff1a; 设计模式&#xff1a;单例模式 是否加锁&#xff1a;是 synchronized 获取最后一次生成的时间戳值T0 限定初始时间为2023-08-01 00:00:00,获取当前时间时间戳T1,T1与初始时间的毫秒差值T2,转为16进制&#xff0c;转为字符串为r1,获取该字符串的长度L1…...

Zip压缩文件夹php打包函数代码

Zip压缩文件夹php打包函数代码,Zip相关函数是PHP的扩展功能,此函数可以直接复制使用。 以下是代码: <?php # 将文件夹的文件压缩到文件里 class Zip {/*** 将目标文件夹下的内容压缩到zip中(zip包含文件夹目录)* @param $sourcePath *文件夹路径 例: /home/test* @p…...

RISC-V交叉工具链riscv-gnu-toolchain编译

文章目录 1、下载2、编译1. 依赖安装2. 编译 3、运行 1、下载 $ sudo apt-get install git wget build-essential $ git clone https://github.com/riscv-collab/riscv-gnu-toolchain $ git checkout 2023.06.02注意上面 clone 的仓库&#xff0c;我们称其为构建脚本仓库&…...

我能“C“——指针进阶(上)

目录 指针的概念 1. 字符指针 2. 指针数组 3. 数组指针 3.1 数组指针的定义 3.2 &数组名VS数组名 3.3 数组指针的使用 4. 数组参数、指针参数 4.1 一维数组传参 4.2 二维数组传参 4.3 一级指针传参 4.4 二级指针传参 5. 函数指针 阅读两段有趣的代码&…...

SQLServer2008数据库还原失败 恢复失败

源地址&#xff1a;http://www.taodudu.cc/news/show-1609349.html?actiononClick 还原数据库问题解决方案 在还原数据库“Dsideal_school_db”时&#xff0c;有时会遇见上图中的问题“因为数据库正在使用&#xff0c;所以无法获得对数据库的独占访问权”&#xff0c;此时我们…...

【微服务部署】04-ForwardedHeaders

文章目录 1. ForwardedHeaders1.1 场景1.2 关键的HTTP头1.3 核心处理要点 1. ForwardedHeaders 1.1 场景 获取用户IP获取用户请求的原始URL 1.2 关键的HTTP头 X-Forwarded-ForX-Forwarded-ProtoX-Forwarded-Host 1.3 核心处理要点 设置PathBase设置ForwardedHeaders中间件…...

JVM 垃圾收集器

重点&#xff1a;CMS&#xff0c;G1&#xff0c;ZGC 主要垃圾收集器如下&#xff0c;图中标出了它们的工作区域、垃圾收集算法&#xff0c;以及配合关系。 Serial 收集器 Serial 收集器是最基础、历史最悠久的收集器。 如同它的名字&#xff08;串行&#xff09;&#xff0c…...

CSS 样式使用link和@import有什么区别

在页面导入样式时&#xff0c;使用link和import有以下区别&#xff1a; 位置&#xff1a;link标签可以放置在HTML文档的head或body中的任何位置&#xff0c;而import规则必须出现在CSS样式表的顶部。 加载方式&#xff1a;当浏览器解析到link标签时&#xff0c;会立即请求并加…...

LeetCode-2511-最多可以摧毁的敌人城堡数目

题目链接 代码实现&#xff1a; class Solution {/** 找 1 -> -1 的时候&#xff0c;经过0的最大个数* 解题思路&#xff1a;双指针*/public int captureForts(int[] forts) {int len forts.length;if(len1){return 0;}int max Integer.MIN_VALUE;boolean flag false;boo…...

iOS开发Swift-2-图片视图、App图标-赏月App

1.创建新项目 点击File - New - Project。 选择Single View App&#xff0c;点击Next。 填写文件信息&#xff0c;点击Next。 选择文件位置&#xff0c;点击Create。 修改App显示名称为 “赏月”。 2.设置背景色 选择Main&#xff0c;点击View界面&#xff0c;选择右边属性&…...

node18 vue2启动报错 error:0308010C:digital envelope routines::unsupported

出现原因 貌似是因为是因为 node 17版本开始发布的OpenSSL3.0, 而OpenSSL3.0对允许算法和密钥大小增加了严格的限制&#xff0c;可能会对生态系统造成一些影响。 解决方法 第一种方法降低node版本 降低到17以下即可 &#xff0c;如项目不能降低版本 看后面的解决方式 第二…...

Java8实战-总结18

Java8实战-总结18 使用流筛选和切片用谓词筛选筛选各异的元素截短流跳过元素 使用流 流让你从外部迭代转向内部迭代。这样&#xff0c;就用不着写下面这样的代码来显式地管理数据集合的迭代(外部迭代)了&#xff1a; List<Dish> vegetarianDishes new ArrayList<>…...

ARM编程模型-指令流水线

流水线技术通过多个功能部件并行工作来缩短程序执行时间&#xff0c;提高处理器核的效率和吞吐率&#xff0c;从而成为微处理器设计中最为重要的技术之一。 1. 3级流水线 到ARM7为止的ARM处理器使用简单的3级流水线&#xff0c;它包括下列流水线级。 &#xff08;1&#xff0…...

邮件营销:高效的节日宣传方式

每个国家都有当地的传统节日&#xff0c;像是我国刚过去的端午节&#xff0c;即将迎来的中秋节、国庆节。我们除了会进行一些传统习俗外&#xff0c;各路商家还会趁这个机会开启促销活动。 对于公司来讲&#xff0c;抓住每一次营销活动都可能会带来更高的营销额&#xff0c;或…...

Leetcode109. 有序链表转换二叉搜索树

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给定一个单链表的头节点 head &#xff0c;其中的元素 按升序排序 &#xff0c;将其转换为高度平衡的二叉搜索树。 本题中&#xff0c;一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度…...

基于Googlenet深度学习网络的人脸身份识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ..................................................................... % 定义修改的范围 …...

vue2 生命周期,工程化开发入门

一、今日目标 1.生命周期 生命周期介绍生命周期的四个阶段生命周期钩子声明周期案例 2.工程化开发入门 工程化开发和脚手架项目运行流程组件化组件注册 二、Vue生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09;什么…...

Elasticsearch 分布式搜索——聚合

1.聚合的种类 聚合常见的有三类&#xff1a; **桶&#xff08;Bucket&#xff09;**聚合&#xff1a;用来对文档做分组 TermAggregation&#xff1a;按照文档字段值分组&#xff0c;例如按照品牌值分组、按照国家分组Date Histogram&#xff1a;按照日期阶梯分组&#xff0c;例…...

苹果将在iPhone16系列中引入微透镜阵列技术,亮度更高、功耗更低

根据韩国媒体The Elec的报道&#xff0c;苹果公司正与其主要供应商三星和LG展开合作&#xff0c;以评估并衡量是否有必要在明年的iPhone 16系列中引入微透镜&#xff08;micro-lens&#xff09;技术来升级屏幕。 这项方案集中在OLED屏幕架构上&#xff0c;计划采用微透镜阵列&…...

Window10 安装 Lua

1、下载地址&#xff1a;https://luabinaries.sourceforge.net/download.html 2、下载 3、解压后共有4个文件&#xff0c;这里我把这几个文件放到如下目录 D:\Program Files\lua-5.4.2\bin 4、定义环境变量 5、打开 powershell&#xff0c;运行 lua54 -v PS C:\Windows\syste…...

Centos替代方案分析(Ubuntu篇)

最受欢迎Linux操作系统 在上百个Linux版本中&#xff0c;Ubuntu和CentOS是最受欢迎的开源操作系统&#xff0c;以其稳定性、高性能和广泛的社区支持而闻名。Ubuntu以友好的用户界面和多样的应用程序生态系统吸引着广大用户&#xff0c;适用于桌面和服务器。而CentOS则因其与RH…...

关于计数以及Index返回订单号升级版可以控制年月日累计(不重复)(sqlite)

1数据库创建&#xff1a; RAGMA foreign_keys false;-- ---------------------------- -- Table structure for OrderSIndex -- ---------------------------- DROP TABLE IF EXISTS "OrderSIndex"; CREATE TABLE "OrderSIndex" ("Id" INTEGER…...

前端实现在线预览文件

一、实现word、xls、ppt文件的在线预览功能 1、通过调用微软的在线预览功能&#xff0c; word、ppt、xls文件实现在线预览的方式比较简单可以直接通过调用微软的在线预览功能实现&#xff08;预览前提&#xff1a;资源必须是公共可访问的&#xff09; <iframe srchttps://…...

海外有哪些流行的支付方式?

大家好&#xff0c;我是老三&#xff0c;很久没写支付相关的文章了&#xff0c;这期给大家讲一讲&#xff0c;海外都在用哪些支付方式。 简介 我们先来看下两个主流电商产品的美国站的支付方式&#xff1a; 在国内&#xff0c;想必大家都习惯了支付宝和微信支付二分天下&…...

服务器数据恢复-重组RAID导致RAID6数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 一台存储设备中有一组由12块硬盘组建的RAID6磁盘阵列&#xff0c;上层采用EXT3文件系统&#xff0c;共划分3个LUN。 服务器故障&分析&#xff1a; 存储设备在运行过程中RAID6阵列突然不可用&#xff0c;管理员对故障存储进行了重新分配RAI…...

Redis数据库持久化---RDB(Redis DataBase)概念与实操

一、概念 1redis提供了两种持久化的方式&#xff0c;分别是RDB&#xff08;Redis DataBase&#xff09;和AOF&#xff08;Append Only File&#xff09;。 RDB&#xff08;Redis DataBase&#xff09;&#xff1a;是在不同的时间点&#xff0c;将redis存储的数据生成快照并存…...

分部署存储Ceph

文章目录 Ceph一.deploy-ceph部署1.系统环境初始化1.1 修改主机名&#xff0c;DNS解析1.2 时间同步1.3 配置apt基础源与ceph源1.4关闭selinux与防火墙1.5 创建 ceph 集群部署用户cephadmin1.6分发密钥 2. ceph部署2.1 安装ceph 部署工具2.2 初始化 mon 节点2.3 安装ceph-mon服务…...

项目:点餐系统3mysql知识回顾MySQL客户端

连接数据库 mysql -uroot -p 密码&#xff1a;空 一、第三方库&#xff1a;MySQL 数据库-存储并管理数据的仓库&#xff0c;是一个C/S架构 MySQL客户端通过sql来告诉MySQL服务器&#xff0c;自己需要做什么操作 1.sql语句 sql&#xff1a;structure query language结构化查询…...