C语言——简易版扫雷
目录
前言
编辑
游戏规则
游戏结构的分析
游戏的设计
使用多文件的好处有以下几点:
游戏代码实现
框架(test.c)
game函数(test.c)
InitBoard初始化(game.c)
Print打印棋盘(game.c)
Setmine设置雷(game.c)
Findmine排查雷(game.c)
GetMine
game.h
game.c
exe程序
Debug和Release的区别
前言
扫雷游戏是一种益智类的游戏,目标是通过揭示方块上的数字来找到不带雷的方块,避免触雷。
游戏规则
玩家的目标是根据已翻开的方块信息来推测出地雷的位置,并避开它们。每个方块要么是空白,要么显示数字。数字表示该方块周围八个方向上的地雷数量。通过使用数字信息和逻辑推理,玩家可以确定哪些方块是安全的,哪些是地雷。当玩家翻开所有非地雷方块时,游戏胜利。如果玩家不慎踩到地雷,游戏失败。
游戏结构的分析
扫雷的过程中,布置的雷和排查出的雷的信息都需要存储,所以我们需要⼀定的数据结构来存储这些 信息。
所以我们首先会想到一个9*9的矩阵。
我们将有雷的设置为“1”,没雷的地方设置为“0”。
示例
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
4 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
8 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
9 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
假设我们排查(5,3),在(5,3)周围的一圈有雷,则会在屏幕上记起来。
这就是我们想要设计的样子,但是当我们想访问(6,9)的时候,我访问就会越界,到了界外去了,为了解决这一问题,我们将表格变成11*11的模型,这就能很好的解决这个问题。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
4 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
8 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
9 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
继续分析,我们已经设置了数字“1”为雷,“0”为非雷,当我们排查到一个雷时,需要将这个雷的信息储存起来,然后将它打印出来,作为排雷的重要参考信息的。。那这个雷的个数信息存放在哪⾥呢?如果存放在布 置雷的数组中,这样雷的信息和雷的个数信息就可能或产⽣混淆和打印上的困难。
将雷和⾮雷的信息不要使⽤数字,使⽤某些字符就⾏,这样就避免冲 突了,但是这样做棋盘上有雷和⾮雷的信息,还有排查出的雷的个数信息,就⽐较混杂,不够⽅便。
这⾥我们采⽤另外⼀种⽅案,我们专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。这样就互不⼲扰了,把雷布置到 mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期 排查参考。
mine数组
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
0 | ||||||||||||
1 | ‘1’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘1’ | ‘0’ | ‘0’ | ||
2 | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘1’ | ||
3 | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘1’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ||
4 | ‘0’ | ‘1’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘1’ | ‘0’ | ||
5 | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ||
6 | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘1’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ||
7 | ‘1’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘1’ | ‘0’ | ||
8 | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ||
9 | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘1’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ||
10 | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ‘0’ | ||
11 |
char mine[11][11] = {0};//⽤来存放布置好的雷的信息char show[11][11] = {0};//⽤来存放排查出的雷的个数信息
对于show数组就是将所有‘0’和‘1’换成‘*’这里就不展示了,不水字数了。
游戏的设计
使用多文件的好处有以下几点:
1. 组织性好:将代码划分到不同的文件中,可以更好地组织和管理代码。每个文件可以分别负责不同的功能模块,使代码结构更清晰。
2. 可维护性强:多文件的编程方式使得修改或更新某个功能模块变得更加简单。只需修改相应的文件,不需要修改整个程序。
3. 可重用性高:将一些常用的函数或功能封装到单独的文件中,可以在多个项目中复用这些代码。
4. 编译效率高:当调用某个函数时,编译器只需要编译包含该函数的文件,而不需要重新编译整个程序,提高了编译速度。
5. 可扩展性强:如果需要添加新的功能模块,只需添加一个新的文件,不会对原有代码造成影响。
6. 可测试性好:每个文件可以独立地进行测试,便于定位和修复问题。
总之,使用多文件的编程方式可以提高代码的组织性、可维护性、可重用性和扩展性,提高编译效率和测试效率。
在这个扫雷中我们需要:
game.h ⽂件中写游戏需要的数据类型和函数声明等
game.c ⽂件中写游戏中函数的实现等
text.c ⽂件中写游戏的测试逻辑
游戏代码实现
框架(test.c)
我们写个基础的框架。将头文件都放在game.h里面,就需要包含头文件,而我们自己的头文件要用“”。
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
int main()
{text();return 0;
}
我们进入text函数是,打印菜单menu(),让玩家进行选择,是进入游戏,还是退出游戏。
void menu()
{printf("******************\n");printf("***** 1.game *****\n");printf("***** 0.exit *****\n");printf("******************\n");
}
函数进来是直接do-while进行打印菜单,然后供玩家选择,选择1进入游戏,0退出游戏,若输入以外的内容则会提示出错误,需要重新输入。
void text()
{int input = 0;srand((unsigned int)time(NULL));//这是播种由函数 rand 使用的随机数发生器。//我们先放在这里do{menu();printf("请输入你的选择:");scanf("%d", &input);switch(input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新输入:");break;}} while (input);
}
game函数(test.c)
我们整体思路是将数组初始化,mine初始化为‘0’,show初始化为‘*’;随后布置地雷,我们初始化和布置雷好后都能打印一下看看是否符合我们的要求。最后进行排查地雷,将所有的雷找出来就行了。
void game()
{char mine[ROWS][COLS] ;char show[ROWS][COLS] ;//初始化InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*');//打印棋盘Print(show, ROWS, COLS);/*Print(mine, ROWS, COLS);*///布置地雷Setmine(mine, ROW ,COL);//排查地雷Findmine(mine,show,ROW,COL);
}
InitBoard初始化(game.c)
对数组mine和show进行初始化,将mine的数组全部初始化为‘0’,show初始化为‘*’。如果只是简单的在数组中初始化化‘0’,‘*’。我们传入应该char set就能够让代码更加灵活,不用在写一样的代码浪费时间和空间。
void InitBoard(char arr[ROWS][COLS], int rols, int cols,char set)
{for (int i = 0; i < rols; i++){for (int j = 0; j < cols; j++){arr[i][j] = set;//'0' , '*'}}
}
Print打印棋盘(game.c)
对数组mine和数组show进行打印。虽然我们设置的是11*11的棋盘,但是对于玩家来说他们只需要再9*9的棋盘里面进行排查雷就行了,所以我们打印的是9*9的棋盘。在加上坐标,能让玩家更精确的定位。
void Print(char arr[ROWS][COLS], int rols, int cols)
{printf("-----扫雷游戏——————\n");//让界面整体更加美观for (int i = 0; i < rols - 1 ; i++){printf("%d ", i);}printf("\n");for (int i = 1; i < rols - 1; i++){printf("%d ", i);for (int j = 1; j < cols - 1; j++){printf("%c ", arr[i][j]);}printf("\n");}
}
Setmine设置雷(game.c)
我们只需要在9*9的棋盘随机布置雷就行了,这时需要用到rand这个函数rand()%row = 8 再加1。
void Setmine (char board[ROWS][COLS], int row, int col)
{int count = minebox;while(count){//设置行数和列数的随机int x = rand() % row + 1;int y = rand() % col + 1;if (board[x][y] == '0'){board[x][y] = '1';count--;}}
}
需要的头文件
rand----> #inlcude<stdlib.h>
time----> #include<time.h>
Findmine排查雷(game.c)
开始我们需要踹按创建变量x和y,供玩家输入坐标,我们的坐标只有1~9所以需要 0<x<10,0<y<10作为条件,这个坐标之外的为非法最标,需要重新输入如果玩家排查的坐标是雷,那么游戏结束,并打印棋盘。如果不是雷,我们需要统计一下它周围有几个雷,这就需要统计雷GetMine,将雷的信息传到数组show上,个数统计出来还要加上‘0’;如果仅仅是这样的话游戏是不会结束的,还需要给whle加上条件win< row * col - minebox(minebox是雷的数量),每次没排查到雷级win++。
如果有耐心的坚持去玩,那么肯定是能玩完的,前提是没被炸死哈。
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 - minebox){printf("请输入要扫的坐标:");scanf("%d %d", &x, &y);if (x > 0 && x < row && y >0 && y < col){system("cls");if (mine[x][y] == '1'){printf("你被炸死了,游戏失败\n");Print(show, ROWS, COLS);break;}else {int count = GetMine(mine, x, y);show[x][y] = count + '0';Print(show, ROWS, COLS);win++;}}else{printf("非法输入\n");}}if (win == row * col - minebox){printf("恭喜你,排雷成功\n");Print(mine, ROW, COL);}}
system("cls")的头文件跟rand的一样
GetMine
static是静态的意思,静态函数只能在声明它的文件中可见,其他文件不能引用该函数。
‘1’的值是49;'0'的值是48;‘1’-‘0’=1是个整数。我们将周边的数都加起来-8*‘0’就能得到雷的数。
static int GetMine(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] +mine[x + 1][y + 1] +mine[x][y + 1] +mine[x - 1][y + 1] -8 * '0');
}
game.h
#define ROW 9 //行数
#define COL 9 //列数#define ROWS ROW+2
#define COLS COL+2#define minebox 10 //雷的个数#include<stdio.h> //main函数的头文件
#include<time.h> //time函数的头文件
#include<stdlib.h> //system,rand函数的头文件//初始化棋盘
void InitBoard(char arr[ROWS][COLS], int rols, int cols, char set);//打印棋盘
void Print(char arr[ROWS][COLS], int rols, int cols);//设置雷
void Setmine(char arr[ROWS][COLS], int x, int y);//找雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
同理,game.c要使用game.h的东西也得包含头文件。
到这里,我们这个简易版的扫雷就实现了。
怎么把代码编程可发布的exe程序呢?
exe程序
- 将debug模式改为Release模式。
- 打开“项目”点击属性。
- 打开“C/C++”下的“代码生成”将“运行库”改为多线程(/MT)
- “Ctrl+F5”运行程序,这里exe的程序就出现在文件夹里面了。
- 打开我们存放代码的文件夹找到x64里面会有两个文件夹,一个是Debug,一个是Relase,点开,我们就能看到一个exe的程序后缀,这样就能直接发给其他人。
Debug和Release的区别
Debug和release是软件开发中常见的两种构建(build)模式,它们在编译、优化和调试方面有以下区别:
- 1. 编译方式:Debug模式通常会生成包含调试信息的可执行文件,以便在调试过程中能够准确定位代码的问题。而release模式会采用更高级别的优化和压缩,生成体积更小、性能更高的可执行文件。
- 2. 优化级别:Debug模式通常会使用较低级别的优化,以便更好地保留源代码的结构和逻辑,使得调试更容易。而release模式会使用更高级别的优化,以提高程序的运行性能。
- 3. 调试信息:Debug模式会保留更多的调试信息,如变量名、函数名等,以便在调试器中能够查看和修改这些信息。而release模式会舍弃部分调试信息,以减小可执行文件的体积。
- 4. 异常处理:Debug模式通常会提供更多的异常信息,使得在程序出错时能够更方便地定位问题。而release模式会舍弃部分异常信息,以提高程序的性能和稳定性。
总之,Debug模式适用于开发和调试阶段,能够提供更多的调试信息和更好的可读性;而release模式适用于发布阶段,能够提供更高的性能和较小的体积。在实际开发中,通常会进行Debug模式的开发和调试,然后再切换到release模式进行最终的发布。
相关文章:

C语言——简易版扫雷
目录 前言 编辑 游戏规则 游戏结构的分析 游戏的设计 使用多文件的好处有以下几点: 游戏代码实现 框架(test.c) game函数(test.c) InitBoard初始化(game.c) Print打印棋盘(g…...
L3自动驾驶的“双保险”:冗余EPS关键技术解析
摘要: 本文主要介绍冗余EPS的发展路径和关键技术。 引言 在乘用车领域,电动助力转向系统(Electric Power Steering,EPS)相比传统的液压助力转向系统(Hydraulic Power Steering,HPS)具有结构简单、响应迅速、能耗低等优点,因此应用很广。随着智能驾驶的发展,作为底层…...
java.net.UnknownHostException
目录 报错信息 报错分析 UnknownHostException 分析 尝试解决 域名 报错可能 网络请求: 数据库连接: Socket通信: 总结: 报错信息 java.net.UnknownHostException Caused by: java.net.UnknownHostException:at java.…...

比派电器T6白色系高速吹风机,高品质保证下,追求极致性价比
广东比派电器科技有限公司于2020年成立于东莞市松山湖高新技术企业园区融易大厦,公司聚焦于小家电的研发,生产,销售。专注在小家电的PCBA研发,产品设计,成品生产。提供小家电产品一站式解决方案,致力于成为…...
每天学习一个Linux命令之ss
每天学习一个Linux命令之ss 在Linux中,网络管理是非常重要的一项工作。ss(Socket Statistics)是一个强大的命令行工具,用于获取各种网络套接字统计信息。它可以帮助我们查看网络连接、监听套接字、路由表、组播成员等信息。本文将…...
Qt的信号槽机制
1. 什么是元对象编译器和元对象系统? 在开始讲信号槽之前,我们先了解下Qt的框架的核心组成部分,Qt的元对象编译器(MOC)和元对象系统是Qt框架的核心组成部分,它们使得Qt拥有了信号与槽机制、反射(…...
跨域问题总结
文章目录 概要web应用整体请求流程技术名词解释跨域问题产生的原理解决方案前端代码角度前端服务器角度后端代码角度后端服务器角度 小结 概要 在不成熟的前后端开发过程中,经常遇到跨域问题; 在前后端分离的模式下的开发过程中,经常遇到跨域…...

K8s-MySQL主从集群
K8s-MySQL主从集群 引言 该案例代码均可从https://github.com/WeiXiao-Hyy/k8s_example 获取,欢迎Star! 需求 一个“主从复制”的MySQL集群有一个主节点Master有多个从节点Slave从节点需要能水平扩展所以写操作只能在主节点上执行读操作可以在所有节点…...

seo js转码工具
js转码工具作用 用于把js加密 如果不想让别人看到自己的js 代码就可以使用这个方法 js工具网址 https://tool.chinaz.com/js.aspx 效果...

【SQL】601. 体育馆的人流量(with as 临时表;id减去row_number()思路)
前述 知识点学习: with as 和临时表的使用12、关于临时表和with as子查询部分 题目描述 leetcode题目:601. 体育馆的人流量 思路 关键:如何确定id是连续的三行或更多行记录 方法一: 多次连表,筛选查询方法二&…...

java上传本地文件到服务器共享
在Windows系统中,将本地文件夹中的某个文件上传到另一台Windows服务器电脑上,前提:两台电脑网络互通,要接收文件的Windows服务器文件夹开启了共享,可以被本机用如下方式进行写入和读取: 如何配置服务器共享请自行百度查找。 所需要的maven依赖如下: <dependency>…...
Redis场景总结
使用场景 在大型的秒杀库存扣减,app首页流量高峰,很容易将传统的关系型数据库(mysql,oracle等)给压垮。 还有很多没必要持久化的数据,比如说短信验证码,点赞数等。 分布式锁。 分布式缓存(会话共享)。 …...

2024.3.11 C++作业
1、提示并输入一个字符串,统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数要求使用C风格字符串完成 #include <iostream>using namespace std;int main() {char str[20];cout << "please enter the str:";gets(str);in…...

【wps】wps与office办公函数储备使用(结合了使用案例 持续更新)
【wps】wps与office办公函数储备使用(结合了使用案例 持续更新) 1、TODAY函数 返回当前电脑系统显示的日期 TODAY函数:表示返回当前电脑系统显示的日期。 公式用法:TODAY() 2、NOW函数 返回当前电脑系统显示的日期和时间 NOW函数:表示返…...

初级爬虫实战——伯克利新闻
文章目录 发现宝藏一、 目标二、简单分析网页1. 寻找所有新闻2. 分析模块、版面和文章 三、爬取新闻1. 爬取模块2. 爬取版面3. 爬取文章 四、完整代码五、效果展示 发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不…...
WPF资源的继承
假设这里有一个全局的资源 <Style TargetType"TextBlock"><Setter Property"FontSize" Value"40"/> </Style> 这是时候有些控件可能需要一个样式在这个基础上加一点内容的 <Style x:Key"textBlockStyle" Targ…...

linux网络通信(TCP)
TCP通信 1.socket----->第一个socket 失败-1,错误码 参数类型很多,man查看 2.connect 由于s_addr需要一个32位的数,使用下面函数将点分十进制字符串ip地址以网络字节序转换成32字节数值 同理端口号也有一个转换函数 我们的端口号位两个字…...

Mybatis 多个简单类型参数传入sql语句
如果只有一个简单类型的参数传入sql语句,我们可以在在#{}中可以随意命名,都可以获取到数据。但通常与接口方法中的参数同名。 但是如果有多个简单类型参数,如果没有特殊处理,那么Mybatis无法根据参数名获取数据。 正确获取方式如…...

SpringCloud OpenFeign 服务接口调用
一、前言 接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第四篇,即介绍 Feign 和 OpenFeign 服务接口调用。 二、概述 2.1 Feign 是什么 Feign 是一…...

WAP网站商业计划书(附下载)
这份文件“WAP网站商业计划书.zip”详细阐述了一个由富有创造力和远见的大学生团队构思的创业项目。这个计划旨在开发并运营一个专注于无线应用协议(WAP)技术的网站,以服务于移动设备用户群体,提供一个易于访问、功能丰富且用户体…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...