【C语言扫雷的显微镜级别讲述】

news2024/11/9 0:09:53

C语言扫雷的显微镜级别讲述

分析

很久之前写过这个
现在做一个详细复述从源头出发
首先我们想写扫雷 最基本的框架
1(外部).这个游戏可以玩完之后再玩一次
2.(内部)首先是要创建一个游戏场地
3.(内部) 电脑随机布雷
4.(内部)玩家可以点击排雷 获取周围雷的数量信息
5.(内部) 雷最好是那种点击就炸开的情况
6.(内部)可以做一半标记信息
这里我觉得最难点在于对雷炸开 还有我们点击之后能标记信息
我们现在先开始创建两个源文件和一个头文件即可
在这里插入图片描述
其中project.c是主函数写main
test.c存放各类很长的函数 声明在project.h然后直接调用
(内心os:其实我可以把每部分功能都拆开写比较直观,但是就像我上次写的模块化三子棋其实写的有点问题,但是就算把所有.h合并在一起之后还是感觉很长,所以我以后写这种扫雷的小工程文件,还是把所有外部的函数全部写在test.c里吧)

实践

主函数

好的我们先设计我们的主函数
project.c

int main()
{
    int input = 0;

    do
    {
        menu();//打印菜单栏
        printf("请输入数字进行选择:");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            printf("游戏开始了:\n");
           // play();
            break;
        case 0:
            printf("结束\n");
            break;
        default:
            printf("请重新输入:\n");
            break;
        }
    } while (input);
}

这大概就是我们main函数的框架 通过一个人do while循环 (为什么暂时把play 注释 因为我先跑一遍看看是否有错 )
这个做法是先打印出一个菜单,然后接收用户给出的1还是0 当你输入的不是 1或者是0 时会提示重新输入
为什么用do while 循环 因为input非0即真,那么我们输入的只要是非0 就可以重新开始游戏 继续玩一把了 非常方便
我们在test.c和project.h中分别写入对menu()的声明即可

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

play模块

接下来我们研究游戏本身
写出play模块
首先我们应该创建两个棋盘是不是
为什么 因为一个棋盘用来埋雷 对雷进行操作另外一个用来对我们玩家进行操作
因为你不太好在一张表格上完成雷的排布,再去点击测试是否有雷,当然我说的这是内部场景 外部了肯定只显示用户操作的那一张 是否有雷
如果你听不懂没关系我也觉得这一块没讲好。就这么说吧,你去扫雷有一个显示块,那么其实是不是他背后还有一张藏雷的,我们就把玩家操作和雷模块抽象剥离出来
在这里插入图片描述
还有一个问题
我们再创建棋盘的时候也需要考虑到一个问题 ,就是我们再扫雷之后会读取周围9个格子剩余的雷数,那么为了保证全面性我们和不再那么复杂(不然你想四个顶角和边还有内部 这就有3种复杂的情况了)我们要是考虑这个3种情况那么计算量就很大,为什么不在开始设计棋盘的时候就扩大一圈呢。
在这里插入图片描述
类似于这样那么对于格点上的位置也能很好的处理
我们在头文件里定义行列ROWS和COLS 这样以后修改方便一点

#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9 
#define number 10 

这就是project.h当前的文件
行列 一个是雷的行列 另外ROW COL 主要用在显示块里 然后定义的define 就用来 表示雷的数目
初始化模块

void initboard(char board[ROWS][COLS], int rows, int cols, char ret)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] = ret;
        }
    }
}

写到这里我们不知道正确与否先显示一下
display这里有点小技巧
因为我们得输入数字 不太好一个一个点着看 那么我们可以在开头带上1 到9
//显示模块 显示模块 显示模块

void displayboard(char board[ROWS][COLS], int row, int col)
{
    //依次打印值喽
    int i = 0;
    int j = 0;
    for (i = 0; i <= row; i++)//第一行打印 数字序列 1到9
    {
        printf("%d ", i);
    }
    printf("\n");//换行真正意义上打印数字组
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);//每次经过一轮打印一个数字
        for (j = 1; j <= col; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
}

显示完成之后开始埋雷
埋雷有两个点 1 是我们是在1到9埋雷的,不能埋雷到我自定义的大框架上
2.埋雷此时需要引入一个随机数的概念
随机数用我们擅长的时间戳实现
srand((unsigned int)time(NULL));需要在主函数中加入随机的函数
并且#include<time.h>
//埋雷 埋雷 埋雷

void mailei(char board[ROWS][COLS], int row, int col)
{
    //我们需要电脑生成随机数。随机生成地雷
    int x = 0;
    int y = 0;
    int count = number;//头文件定义雷的数量是10个
    while (count)//怎么保证有指定数量的雷呢,这里用count--
    {
        x = rand() % row + 1;//指的是1-9
        y = rand() % col + 1;
        if (board[x][y] == '0')
        {
            board[x][y] = '1';
            count--;
        }
    }
}

3.埋雷之后加入我们最喜欢的最复杂的排雷
排雷需要注意一下三点
1.判断第一发是否就炸
2,如果不炸那么 会把周围不是的条件都激发出来
这个激发模块才是最难写的
3,标记是否有雷以便后续实现

//排雷模块
void pailei(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    char ch = 0;
    while (win < row * col - number)
    {
        printf("请输入雷区坐标:\n");//让用户输入坐标
        scanf("%d%d", &x, &y);
        //输入坐标我们首先判断是不是无效坐标
        if (x >= 1 && y >= 1 && x <= row && y <= col)
        {
            if (mine[x][y] == '1')
            {
                printf("你输了\n");
                displayboard(mine, ROW, COL);
                break;
            }
            else
            {
                //此处不是地雷,我们需要激发周围的对象,就像原版扫雷一样,炸开直至看到是地雷的序号
                //需要我们去递归进行操作
                jifa(mine, show, row, col, x, y);
                displayboard(show, row, col);
                //新增加是否标记功能
                    printf("是否标记:Y,不需要标记:N\n");
                while ((ch = getchar()) != '\n');//剔除掉我们最喜欢摁的回车
                scanf("%c", &ch);
                switch (ch)
                {
                case 'Y':
                    biaoji(show, row, col);
                    break;
                default:
                    break;
                }
            }
        }
        else
        {
            printf("字符非法,请重新输入:");
        }
    }
    if (win >= row * col - number)
    {
        printf("扫雷成功");
    }
    else
    {
        printf("扫雷失败\n");
    }
}

我们在这里需要着重介绍的几个点
统计模块
激发模块
标记模块
标记模块和统计模块其实相对来说比较简单就是把判断是否是未知区域,是的话我们想标记那就改成! 仅此而已
//标记模块

void biaoji(char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    while (1)
    {
        printf("请输入要标记的坐标:");
        scanf("%d%d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (show[x][y] == '*')
            {
                show[x][y] = '!';
                break;
            }
            else
            {
                printf("输入非法,请重新输入:\n");
            }
        }
        else
        {
            printf("输入非法,请重新输入:\n");
        }
    }
    displayboard(show, row, col);
}

统计模块我用的是纯手算的方法
就是将他周围九宫格内所有的数字加以计算
//统计模块
// x - 1 y - 1 x - 1 y x - 1 y + 1
// x y - 1 x y + 1
// x + 1y - 1 x + 1 y x + 1 y + 1

int tongji(char mine[ROWS][COLS], int x, int y)
{
    //因为我们是字符0,地雷为字符1 ,根据ASICII码值我们得出结论‘1’-‘0’=1
    return  mine[x - 1][y] +
        mine[x - 1][y - 1] +
        mine[x - 1][y + 1] +
        mine[x][y - 1] +
        mine[x - 1][y + 1] +
        mine[x + 1][y - 1] +
        mine[x + 1][y] +
        mine[x + 1][y + 1] - 8 * '0';
}

这里有个小技巧 这也是为什么我们埋雷用的是字符1 记住是char 而不是int 因为相对ASIC码值来说我们‘1’ 和‘0’相减还是相差1 那不就是周围雷的数目
下面是最重要的激发模块
我们逐个逐个详细说明
//激发模块

void jifa(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{
    //激发面对的是如果
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
        int z = tongji(mine, x, y);
        if (z == 0)
        {
            //把附近没有地雷的位置变成字符 “空格”
            show[x][y] = ' ';
            int i = 0;
            //向四周共8个位置递归调用
            for (i = x - 1; i <= x + 1; i++)//3行
            {
                int j = 0;
                for (j = y - 1; j <= y + 1; j++)//3列
                {
                    if (show[i][j] == '*')
                    {
                        jifa(mine, show, row, col, i, j);
                    }
                }
            }
        }
        else
        {
            show[x][y] = z + '0';
        }
    }
}

就是怎么说这个函数我们既传递了地雷块也传递了显示模块我们先int z 加入当前点位 x y的统计数 然后递归激发 从当前点位触发3行3列为了以防撞到边界和对自身的重定义 边界的话我们就控制x y的大方位在 x >= 1 && x <= row && y >= 1 && y <= col 1到9 然后 防止重复激发就用
if (show[i][j] == '')
{
jifa(mine, show, row, col, i, j);
}
如果仅在
位才能激发

完结下面是全部代码

project.c

#define _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h >
#include<stdlib.h>
#include<time.h>
#include"project.h"

void play();
int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();//打印菜单栏
        printf("请输入数字进行选择:");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            printf("游戏开始了:\n");
           play();
            break;
        case 0:
            printf("结束\n");
            break;
        default:
            printf("请重新输入:\n");
            break;
        }
    } while (input);
}
void play()
{
    char mine[ROWS][COLS] = { 0 };//地雷模块
    char show[ROWS][COLS] = { 0 };//用户模块
    //设置完两个棋盘之后初始化一下
    initboard(mine, ROWS, COLS, '0');//初始化埋雷表格,置入字符‘0’
    initboard(show, ROWS, COLS, '*');
    //displayboard(mine, ROW, COL);//地雷模块我们一般显示只是为了确认正确性
   // displayboard(show, ROW, COL);//显示模块是显示在屏幕上的我们把自己增加的外围去掉用ROW
    //显示完成之后开始埋雷 在mine上完成
    mailei(mine, ROW, COL);//埋雷
  // displayboard(mine, ROW, COL);
    displayboard(show, ROW, COL);//display只是为了调试时候方便 最后哪个不好看,自己删去即可
    //雷埋好了,也显示出来了我们需要去排雷
    pailei(mine, show, ROW, COL);
}

project.h

#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9 
#define number 10 
//菜单
void menu();
//初始化
void initboard(char board[ROWS][COLS], int rows, int cols, char ret);
//显示
void displayboard(char board[ROWS][COLS], int row, int col);
//埋雷
void mailei(char board[ROWS][COLS], int row, int col);
//排雷模块
void pailei(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//统计模块
int tongji(char board[ROWS][COLS], int row, int col);
//激发模块
void jifa(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y);
//标记模块
void biaoji(char show[ROWS][COLS], int row, int col);

test.c

#define _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h >
#include<stdlib.h>
#include<time.h>
#include"project.h"


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



// 初始化 初始化 初始化
void initboard(char board[ROWS][COLS], int rows, int cols, char ret)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] = ret;
        }
    }
}



//显示模块 显示模块 显示模块
void displayboard(char board[ROWS][COLS], int row, int col)
{
    //依次打印值喽
    int i = 0;
    int j = 0;
    for (i = 0; i <= row; i++)//第一行打印 数字序列 1到9
    {
        printf("%d ", i);
    }
    printf("\n");//换行真正意义上打印数字组
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);//每次经过一轮打印一个数字
        for (j = 1; j <= col; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
}




//埋雷 埋雷  埋雷
void mailei(char board[ROWS][COLS], int row, int col)
{
    //我们需要电脑生成随机数。随机生成地雷
    int x = 0;
    int y = 0;
    int count = number;//头文件定义雷的数量是10个
    while (count)//怎么保证有指定数量的雷呢,这里用count--
    {
        x = rand() % row + 1;//指的是1-9
        y = rand() % col + 1;
        if (board[x][y] == '0')
        {
            board[x][y] = '1';
            count--;
        }
    }
}


//排雷模块
void pailei(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    char ch = 0;
    while (win < row * col - number)
    {
        printf("请输入雷区坐标:\n");//让用户输入坐标
        scanf("%d%d", &x, &y);
        //输入坐标我们首先判断是不是无效坐标
        if (x >= 1 && y >= 1 && x <= row && y <= col)
        {
            if (mine[x][y] == '1')
            {
                printf("你输了\n");
                displayboard(mine, ROW, COL);
                break;
            }
            else
            {
                //此处不是地雷,我们需要激发周围的对象,就像原版扫雷一样,炸开直至看到是地雷的序号
                //需要我们去递归进行操作
                jifa(mine, show, row, col, x, y);
                displayboard(show, row, col);
                //新增加是否标记功能
                    printf("是否标记:Y,不需要标记:N\n");
                while ((ch = getchar()) != '\n');//剔除掉我们最喜欢摁的回车
                scanf("%c", &ch);
                switch (ch)
                {
                case 'Y':
                    biaoji(show, row, col);
                    break;
                default:
                    break;
                }
            }
        }
        else
        {
            printf("字符非法,请重新输入:");
        }
    }
    if (win >= row * col - number)
    {
        printf("扫雷成功");
    }
    else
    {
        printf("扫雷失败\n");
    }
}
//统计模块
// x - 1 y - 1  x - 1 y    x - 1 y + 1
// x y - 1             x y + 1
// x + 1y - 1  x + 1 y     x + 1 y + 1


int tongji(char mine[ROWS][COLS], int x, int y)
{
    //因为我们是字符0,地雷为字符1 ,根据ASICII码值我们得出结论‘1’-‘0’=1
    return  mine[x - 1][y] +
        mine[x - 1][y - 1] +
        mine[x - 1][y + 1] +
        mine[x][y - 1] +
        mine[x - 1][y + 1] +
        mine[x + 1][y - 1] +
        mine[x + 1][y] +
        mine[x + 1][y + 1] - 8 * '0';
}
//激发模块
void jifa(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
        int z = tongji(mine, x, y);
        if (z == 0)
        {
            //把附近没有地雷的位置变成字符 “空格”
            show[x][y] = ' ';
            int i = 0;
            //向四周共8个位置递归调用
            for (i = x - 1; i <= x + 1; i++)//3行
            {
                int j = 0;
                for (j = y - 1; j <= y + 1; j++)//3列
                {
                    if (show[i][j] == '*')
                    {
                        jifa(mine, show, row, col, i, j);
                    }
                }
            }
        }
        else
        {
            show[x][y] = z + '0';
        }
    }
}
//标记模块
void biaoji(char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    while (1)
    {
        printf("请输入要标记的坐标:");
        scanf("%d%d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (show[x][y] == '*')
            {
                show[x][y] = '!';
                break;
            }
            else
            {
                printf("输入非法,请重新输入:\n");
            }
        }
        else
        {
            printf("输入非法,请重新输入:\n");
        }
    }
    displayboard(show, row, col);
}

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

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

相关文章

Set 集合

1:特点 无序&#xff1a;存取顺序不一致不重复&#xff1a;可以去除重复无索引&#xff1a;不能使用普通for循环遍历&#xff0c;也不能通过索引来获取元素 2&#xff1a;实现类特点 HashSet&#xff1a; 无序&#xff0c;不重复&#xff0c;无索引LinkedHashSet&#xff1a…

Python3 实例(三) | 菜鸟教程(二十一)

目录 一、Python 二分查找 二、Python 线性查找 三、Python 插入排序 四、Python 快速排序 五、Python 选择排序 六、Python 冒泡排序 七、Python 归并排序 一、Python 二分查找 &#xff08;一&#xff09;二分搜索是一种在有序数组中查找某一特定元素的搜索算法。 &a…

手写map

目录 背景过程简介手写HashMap4、put方法5、get方法5、remove方法 总结 背景 让我们来了解一下HashMap吧 过程 简介 HashMap是Java中一中非常常用的数据结构&#xff0c;也基本是面试中的“必考题”。它实现了基于“K-V”形式的键值对的高效存取。JDK1.7之前&#xff0c;Ha…

Docker容器的tomcat安装后访问报404页面的解决办法

上次我们创建的tomcat容器访问的时候是404页面,是因为高版本的并没有把默认的页面放到webapps目录下,这时,就需要我们登录创建的tomcat容器了 登录tomcat容器: docker exec -it my_tomcat /bin/bash 查看当前目录: ls 将webapp.dist下的默认页面复制到webapps目录下: cp …

unity3d:YooAsset零冗余构建Assetbundle代码分析

BuildAssetInfo构建asset信息 1.每个收集器下asset会构建出BuildAssetInfo&#xff0c;这种asset是没有冗余&#xff0c;只有依赖列表 2.每个依赖asset会构建出BuildAssetInfo&#xff0c;会记录将要打入的bundle列表 依赖的Asset列表 这个asset依赖的其他asset列表&#xf…

Tree 树结构

Case 1st 最少的摄像头——亚马逊面试问题 给定一个二叉树&#xff0c;我们在树的节点上安装摄像头。 节点上的每个摄像机都可以监视其父级、自身及其直接子级。 计算监视树的所有节点所需的最小摄像机数。 例&#xff1a; Input: [0,0,null,0,0]Output: 1Explanation: One cam…

asp.net宠物购物商城系统MyPetShop

asp.net宠物购物商城系统 在线购物网站&#xff0c;电子商务系统 主要技术&#xff1a; 基于asp.net架构和sql server数据库 功能模块&#xff1a; 用户可以购买宠物&#xff0c;查看订单记录 修改密码等 运行环境&#xff1a; 运行需vs2013或者以上版本&#xff0c;sql serv…

183 · 木材加工

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a;九章算法 - 帮助更多程序员找到好工作&#xff0c;硅谷顶尖IT企业工程师实时在线授课为你传授面试技巧 class Solution { public:/*** param l: Given n pieces of wood wi…

Java8 Stream详解

Stream类继承关系 前置知识 Spliterator接口使用 Spliterator是在java 8引入的一个接口&#xff0c;它通常和stream一起使用&#xff0c;用来遍历和分割序列。 只要用到stream的地方都需要Spliterator&#xff0c;比如List&#xff0c;Collection&#xff0c;IO channel等等…

大语言模型的百家齐放

基础语言模型 概念 基础语言模型是指只在大规模文本语料中进行了预训练的模型&#xff0c;未经过指令和下游任务微调、以及人类反馈等任何对齐优化。 如何理解 只包含纯粹的语言表示能力,没有指导性或特定目标。 只在大量无标注文本上进行无监督预训练,用于学习语言表示。 …

unity制作手游fps僵尸游戏

文章目录 介绍制作基本UI枚举控制角色移动切枪、设置音效、设置子弹威力、设置子弹时间间隔、换弹准星控制射击僵尸动画、血条设置导航 介绍 利用协程、枚举、动画器、导航等知识点。 实现移动、切枪、换弹、射击、僵尸追踪、攻击。 制作基本UI 制作人类血条、僵尸血条、移动按…

百度智能车竞赛丝绸之路1——智能车设计与编程实现控制

百度智能车竞赛丝绸之路1——智能车设计与编程实现控制 百度智能车竞赛丝绸之路2——手柄控制 一、项目简介 本项目现已基于鲸鱼机器人开发套件对其整体外形进行设计&#xff0c;并且对应于实习内容——以“丝绸之路”为题&#xff0c;对机器人各个功能与机器人结构部分进行相…

【几何数学】【Python】【C++】判断两条线段是否相交,若相交则求出交点坐标

判断线段是否相交的办法&#xff08;使用了向量叉积的方法&#xff09;&#xff1a; 首先&#xff0c;通过给定的线段端点坐标p1、p2、p3和p4构建了四个向量v1、v2、v3和v4&#xff1a; v1表示从p1指向p2的向量&#xff0c;其分量为[p2[0] - p1[0], p2[1] - p1[1]]。 v2表示从…

Camtasia Studio2023标准版屏幕录制和视频剪辑软件

Camtasia Studio2023提供了强大的屏幕录像、视频的剪辑和编辑、视频菜单制作、视频剧场和视频播放功能等。它能在任何颜色模式下轻松地记录屏幕动作&#xff0c;包括影像、音效、鼠标移动的轨迹&#xff0c;解说声音等等&#xff0c;另外&#xff0c;它还具有及时播放和编辑压缩…

[前端]JS——join()与split()的使用

Array.join():数组转换为字符串,"()"里元素指定数组转为字符串用什么串联&#xff0c;默认为空。 Array.join()的使用&#xff1a; <script>let arr[1,2,3,4]console.log("arr未转换前:",arr,typeof(arr));console.log("arr使用join():"…

Netty核心技术八--Netty编解码器和handler的调用机制

1.基本说明 netty的组件设计&#xff1a;Netty的主要组件有Channel、EventLoop、ChannelFuture、 ChannelHandler、ChannelPipe等 ChannelHandler充当了处理入站和出站数据的应用程序逻辑的容器。 例如&#xff0c;实现ChannelInboundHandler接口&#xff08;或ChannelInbound…

Typora图床配置-OSS对象存储

Typora图床配置-OSS对象存储 1.PicGo下载 下载地址&#xff1a; Release 2.3.0 Molunerfinn/PicGo GitHub https://github.com/Molunerfinn/PicGo/releases/tag/v2.3.1 下载如下&#xff1a; 2.安装和配置 进入阿里云创建OSS对象存储服务。 设置为公共读才能被别人访问到。…

树与图的深度优先遍历

树的重心 本题的本质是树的dfs&#xff0c; 每次dfs可以确定以u为重心的最大连通块的节点数&#xff0c;并且更新一下ans。 也就是说&#xff0c;dfs并不直接返回答案&#xff0c;而是在每次更新中迭代一次答案。 这样的套路会经常用到&#xff0c;在 树的dfs 题目中 #includ…

IMU 互补滤波

IMU学名惯性测量单元&#xff0c;所有的运动都可以分解为一个直线运动和一个旋转运动&#xff0c;故这个惯性测量单元就是测量这两种运动&#xff0c;直线运动通过加速度计可以测量&#xff0c;旋转运动则通过陀螺。 void IMUupdate(float gx, float gy, float gz, float ax,fl…

Go 语言 context 都能做什么?

原文链接&#xff1a; Go 语言 context 都能做什么&#xff1f; 很多 Go 项目的源码&#xff0c;在读的过程中会发现一个很常见的参数 ctx&#xff0c;而且基本都是作为函数的第一个参数。 为什么要这么写呢&#xff1f;这个参数到底有什么用呢&#xff1f;带着这样的疑问&am…