C++实战:用VS编写贪吃蛇游戏的核心逻辑与完整源码

用VS和C++写一个贪吃蛇游戏,听起来很基础,但真做起来,里面藏着不少值得抠的细节。我把完整源码放在下面,你在Visual Studio里新建一个控制台应用,复制进去就能编译运行。对刚学完C++语法、想做点东西验证自己的入门者来说,贪吃蛇几乎是最理想的第一炮——它不涉及复杂框架,不依赖图形资源,却又把数组、容器、循环、分支、状态机这些核心知识点全串起来了。这篇文章我会从项目定位、设计思路、核心实现到编译运行,完整拆一遍,最后还附上可直接复制的源码和常见问题排查表。

1. 项目定位:为什么我推荐用VS+C++写贪吃蛇

1.1 贪吃蛇是C++入门阶段的“试金石”

很多学C++的人都有过这种感受:语法书看了好几章,指针、引用、类都背得滚瓜烂熟,但真让自己写一个程序,反而不知道从哪里下笔。贪吃蛇恰好能打破这种尴尬。它规模不大,核心逻辑两三百行就能写完,但又没有简单到“照着书抄一遍”的程度。

我在实际接触过一些初学者后发现,能把贪吃蛇完整写出来并调通的人,对C++的基础语法往往会有一次质的提升。原因很简单:贪吃蛇需要你同时处理动态数据(蛇身长度会变)、实时输入(方向键)、状态判断(吃到食物、撞墙、撞自己)以及界面刷新。这些点单独拿出来都不难,但组合在一起,就是对逻辑组织和代码结构的一次真实考验。

换句话说,如果你把贪吃蛇写明白了,再去碰学生管理系统、通讯录、图书借阅这类典型课程设计,基本就是降维打击。因为那些系统本质上是数据的增删改查,难度反而没有贪吃蛇这种“实时变化”的游戏高。

1.2 这套源码适合哪些人直接上手

先说结论:适合已经学过C++基本语法,但还没独立写过完整小项目的人。你需要知道变量、数组、循环、函数、结构体这些概念,不需要精通,能看懂就行。

如果你是完全没接触过C++的纯零基础,我不建议直接拿这份源码硬啃。不是说代码有多难,而是你可能会在编译报错上浪费太多时间,产生挫败感。你可以先找一本基础书,把循环、数组、结构体这几个章节看完,再回来读这份代码,会发现顺畅很多。

如果你已经写过不少控制台程序,这版贪吃蛇对你来说可能偏简单。但你仍然可以把它作为基础版本,在其上做扩展——比如增加关卡、计分板、障碍物,或者把控制台输出改成图形界面。后面我会专门讲扩展方向。

1.3 技术选型:VS加控制台,是我刻意做的选择

有不少人问过我:为什么不用图形库?用EasyX或者Qt画个界面不是更好看吗?我承认,图形界面确实更漂亮,但我不建议入门阶段一上来就碰。

原因有三个。第一,Visual Studio是Windows下最主流的C++开发环境,新建一个控制台应用项目只需要几秒钟,不需要额外配置第三方库。第二,控制台程序能让你把注意力全部放在游戏逻辑上,不会被窗口消息、坐标映射、图片加载这些图形相关的东西干扰。第三,控制台的字符绘制虽然粗糙,但足以帮助你建立“程序输出等于游戏画面”的抽象思维——这点对以后写任何界面程序都有帮助。

从环境成本看,只要电脑上装了Visual Studio,打开就能跑。这也是我标题里写“VS编译就能运行”的原因。整个项目没有任何外部依赖,不装额外的包,不配环境变量,非常适合新手自己动手搭环境。

2. 整体设计思路:动手前先拆解这四个模块

2.1 核心机制:蛇怎么动、吃什么、怎么死

贪吃蛇的规则用一句话就能说完:控制一条蛇在地图里移动,吃到食物变长,撞墙或撞到自己就结束。

但“一句话说完”和“写出程序”之间隔着很多细节。我习惯拆成三个问题来想:

  • 蛇的位置怎么表示?地图是二维的,蛇是由很多个“点”组成的,每个点有x和y坐标。
  • 蛇怎么移动?每一帧,蛇头朝当前方向前进一步,蛇身跟着往前挪,尾巴如果没吃到食物就要缩掉。
  • 游戏状态怎么判断?每一帧都要检查新蛇头的位置是不是越界了、是不是和身体重叠了、是不是踩到了食物。

把这三个问题想清楚,代码结构自然就出来了。我见过不少人一上来就写绘制逻辑,结果蛇动不了、方向乱跳、撞墙不结束。根源就是没先想清楚移动模型。

2.2 数据结构:用数组固定长度,还是用容器动态管理

蛇的特点是长度会变化。吃一个食物变长一格,没吃食物时保持不变。这意味着我们最好用一个能动态增删的数据结构,而不是先申请一个固定大小的二维数组。

在这版代码里,我用的是vector<Point>。Point是一个包含x、y的结构体,vector负责存放所有蛇身的坐标点,头部在第一个元素。移动的时候,往头部插入新坐标;没吃到食物时,把尾部删掉。一次移动就完成了。

可能有人会问:用链表是不是更合适?从理论上讲,链表做“头插尾删”确实很自然。但考虑到这是入门项目,vector的随机访问能力让绘制和碰撞检测更直观,而且初学者对vector的接受度普遍更高。用链表当然可以,但没必要在这个阶段徒增复杂度。

地图本身我用字符边界表示。地图宽20、高20,四周用#画一圈围墙。这个大小可以直接在代码里改,想地图大一点,改两个常量就行。

2.3 状态流转:游戏循环是整台戏的发动机

控制台游戏本质上是一个死循环:读取输入、更新状态、绘制画面、等待一段时间,然后重复。这跟Web程序里的消息循环、游戏引擎里的主循环是一个套路。我把这个循环戏称为“游戏发动机”,因为它每转一圈,画面就刷新一次。

伪代码大概是这样的:

while (游戏未结束) { 处理键盘输入; 计算蛇的新位置; 判断是否吃到食物; 判断是否撞墙或撞自己; 更新蛇的坐标; 清屏并重新绘制; 延时控制速度; }

这个循环看起来简单,但顺序很重要。如果先绘制再更新,画面会慢半拍;如果先更新再读输入,按键灵敏度会有问题。我建议新手先照着我源码里的顺序写,等理解了再自己调整。

3. 核心细节解析:运行效果背后的关键逻辑

3.1 地图、蛇身和食物的表示方法

我定义了一个常量W和H,分别表示地图宽度和高度。地图不是用二维数组存整张网格的,而是靠“位置比对”来绘制。什么意思?每一帧刷新时,从头到尾遍历地图上的每个格子,判断这个格子是不是蛇身、是不是蛇头、是不是食物,然后输出对应字符。

这样做的好处是代码简单,坏处是绘制效率偏低。但对20×20的小地图来说,性能根本不是问题,反而更容易理解。你不需要去维护一张“地图数组”,只需要维护蛇的坐标列表和食物的坐标。

蛇的每个节点是一个结构体:

struct Point { int x, y; };

食物也是一个Point,只是它单独存在,不放进蛇的列表里。绘制时,蛇头用大写字母O表示,蛇身用小写o表示,食物用*表示,空白就是空格。这样即使不做任何美化,也能一眼看清游戏状态。

3.2 移动算法:头插尾删,一个动作搞定

蛇的移动是整个程序最核心的部分。我的做法非常直接:根据当前方向计算出新蛇头坐标,然后判断情况。

如果没有吃到食物,就把蛇尾删掉,再把新蛇头插到最前面。如果吃到了食物,不删蛇尾,直接插入新蛇头。这样蛇身长度刚好加一。

这里有一个细节值得单独拎出来说:判断“吃到食物”要在“删尾”之前,因为吃到了食物时尾巴不缩。如果先删尾再判断,就会把吃到食物后的长度搞错。

示例逻辑:

Point head = snake[0]; head.x += dirX; head.y += dirY; bool eat = (head.x == food.x && head.y == food.y); if (!eat) { snake.pop_back(); } // 之后检查是否撞到自己,再把head插入snake.begin()

先算新头,再决定删不删尾,最后插入新头。这三步顺序不能乱。

3.3 方向键输入与掉头限制

控制方向用的是_getch()读取键盘,方向键在Windows控制台上比较特殊。第一次调用会返回224(是一个功能键前缀),第二次调用才会返回具体的方向码:上72、下80、左75、右77。

如果你不用_kbhit()先检测键盘是否有输入,程序会在读取时阻塞住,游戏画面就没法刷新了。所以我在主循环里先调用_kbhit(),如果有按键才去读_getch()。这个“轮询式”读取方式非常经典,控制台小游戏几乎都这么写。

另一个很容易踩坑的地方是“掉头限制”。如果蛇正在向右移动,你按了左键,蛇不能直接反向,否则会瞬间撞到自己的身体。解决办法是在改变方向之前,判断当前方向:

case 75: if (dirX != 1) { dirX = -1; dirY = 0; } break;

这里的dirX != 1表示当前不是在向右移动,所以允许向左。其他方向同理。这个判断看似简单,但如果没有它,玩家按两下反向键,蛇就会原地穿过自己,游戏逻辑就崩了。

3.4 食物生成与自撞检测的边界处理

食物生成看似简单:随机生成一个坐标就行。但这里有个隐藏问题:如果食物刚好生成在蛇身上,玩家就永远吃不到它。所以生成之后必须检查是否和蛇身重叠,如果重叠就重新生成。

我用了一个do...while循环,反复生成直到不重叠。但如果蛇身占据了大半个地图,理论上存在死循环风险。入门版本可以接受,真要严谨,可以限制尝试次数,超过次数就提示获胜。不过20×20的地图上,这种情况很难出现。

再说自撞检测。每次移动后,新蛇头会与蛇身列表做一次遍历比较。如果新蛇头的坐标出现在蛇身里,就判定游戏结束。

需要注意“尾巴”的情况。如果这一帧没有吃到食物,蛇尾已经被删掉了,那么新蛇头移动到原来尾巴的位置是允许的。经典的贪吃蛇规则允许这种情况。我的代码里是在检查自撞之前,先完成了删尾操作,因此不会误判。

3.5 绘制与游戏循环:S色的世界也能玩出节奏感

绘制部分我用system("cls")清屏,然后逐行输出地图边框、蛇、食物和分数。清屏再输出的方式简单粗暴,但确实有效,而且符合新手预期。

每次循环结束,调用Sleep(100)让程序暂停100毫秒。这个值决定了游戏速度。100毫秒对20×20地图来说比较适中,不会快得让人反应不过来,也不会慢到让人着急。想调速度,直接改这个数字就行。

如果你想让游戏越来越快,可以每得10分减少Sleep的时间。我给的源码里没有做这个,但在后面的扩展建议里会提到。

4. 完整源码与VS运行步骤:拿到就能跑

4.1 Visual Studio版本与项目创建

我用的是Visual Studio Community版,其他版本也没问题。创建项目时注意选择“创建新项目”,然后选“控制台应用(C++)”,项目名称随便起,比如SnakeGame。VS会自动生成一个包含main.cpp的空项目。

这里有一个容易踩坑的点:在VS中创建C++控制台项目时,如果有“解决方案和项目”放在同一个目录的选项,默认即可,不需要特别改。新建完项目后,打开main.cpp,把里面的默认代码全部删掉,替换成下面的源码就行。

4.2 完整源码(可复制)

下面就是我在本地跑通的完整代码。不依赖任何第三方库,只需要Windows自带的头文件,VS2022、VS2019都能直接编译。

#include <iostream> #include <conio.h> #include <windows.h> #include <vector> #include <cstdlib> #include <ctime> using namespace std; const int W = 20; const int H = 20; struct Point { int x, y; }; int main() { srand((unsigned int)time(NULL)); // 初始化蛇:三个节点,方向朝右 vector<Point> snake; snake.push_back({ W / 2, H / 2 }); snake.push_back({ W / 2 - 1, H / 2 }); snake.push_back({ W / 2 - 2, H / 2 }); // 生成初始食物,避免落在蛇身上 Point food; bool foodOk = false; while (!foodOk) { food.x = rand() % W; food.y = rand() % H; foodOk = true; for (size_t i = 0; i < snake.size(); i++) { if (snake[i].x == food.x && snake[i].y == food.y) { foodOk = false; break; } } } int dirX = 1, dirY = 0; bool gameOver = false; int score = 0; while (!gameOver) { // 判断键盘输入 if (_kbhit()) { int key = _getch(); if (key == 224) { // 方向键的前导值 key = _getch(); switch (key) { case 72: // 上 if (dirY != 1) { dirX = 0; dirY = -1; } break; case 80: // 下 if (dirY != -1) { dirX = 0; dirY = 1; } break; case 75: // 左 if (dirX != 1) { dirX = -1; dirY = 0; } break; case 77: // 右 if (dirX != -1) { dirX = 1; dirY = 0; } break; } } else if (key == 32) { // 空格暂停:清空缓冲后等待下一次按键 while (_kbhit()) _getch(); _getch(); } } // 计算新蛇头 Point head = snake[0]; head.x += dirX; head.y += dirY; // 撞墙检测 if (head.x < 0 || head.x >= W || head.y < 0 || head.y >= H) { gameOver = true; break; } bool eat = (head.x == food.x && head.y == food.y); // 没吃到食物时,先去尾巴 if (!eat) { snake.pop_back(); } else { score += 10; // 重新生成食物,避开蛇身 bool newFoodOk = false; while (!newFoodOk) { food.x = rand() % W; food.y = rand() % H; newFoodOk = true; for (size_t i = 0; i < snake.size(); i++) { if (snake[i].x == food.x && snake[i].y == food.y) { newFoodOk = false; break; } } } } // 自撞检测(此时尾巴已经按需删除) for (size_t i = 0; i < snake.size(); i++) { if (snake[i].x == head.x && snake[i].y == head.y) { gameOver = true; break; } } if (gameOver) { break; } // 新蛇头入列 snake.insert(snake.begin(), head); // 绘制 system("cls"); for (int i = 0; i < W + 2; i++) cout << "#"; cout << endl; for (int y = 0; y < H; y++) { cout << "#"; for (int x = 0; x < W; x++) { bool isSnakeNode = false; for (size_t i = 0; i < snake.size(); i++) { if (snake[i].x == x && snake[i].y == y) { if (i == 0) cout << 'O'; else cout << 'o'; isSnakeNode = true; break; } } if (!isSnakeNode) { if (food.x == x && food.y == y) cout << '*'; else cout << ' '; } } cout << "#" << endl; } for (int i = 0; i < W + 2; i++) cout << "#"; cout << endl; cout << "Score: " << score << endl; cout << "Use Arrow Keys. Space to pause." << endl; Sleep(100); } system("cls"); cout << "Game Over!" << endl; cout << "Final Score: " << score << endl; return 0; }

代码复制进main.cpp后,直接按Ctrl+F5(开始执行而不调试)就能运行。如果弹出安全提示,选择“是”允许即可。

4.3 如果编译报错,先看这里

我在本地测试时非常顺利,但你换一台电脑或多一个步骤,就有可能遇到几个常见问题。先列两个最典型的。

一是_kbhit或_getch提示找不到标识符。这通常是头文件没包含对,或者项目属性里“字符集”设置出了问题。检查一下有没有#include <conio.h>,以及“配置属性 → 常规 → 字符集”是否设置为“使用多字节字符集”。如果这里设成了Unicode,部分老的C风格头文件可能出现兼容问题。

二是vector或者cout报错。这是因为没有包含<vector>或<iostream>。VS的空模板可能不会自动带入这些头文件,所以检查源码顶部的几个#include,不要删掉。

5. 常见问题与排查技巧实录

5.1 高频报错对照表

现象原因解决办法
编译时报“_kbhit”: 找不到标识符缺少conio.h或字符集设置不对包含头文件,并把字符集设为多字节
界面一闪而过,看不到游戏画面程序运行完自动关闭控制台用Ctrl+F5运行,或代码结束前加system("pause")
方向键按下没反应方向键的前导值224处理不当确认if (key == 224)后再次调用_getch()读取方向码
蛇移动速度太快,来不及反应Sleep时间太短把Sleep(100)改成更大的数值,如150或200
蛇反向时瞬间死亡缺少“禁止掉头”判断确保每个方向键分支都检查当前方向,不允许直接相反
食物生成在蛇身上或地图外随机范围不对或没有检查重叠使用rand() % W和rand() % H,并做重叠循环检查

这张表基本覆盖了我见过的大部分问题。如果你遇到的报错不在这张表里,优先看编译窗口里的红色错误信息,它会定位到具体行号。多数情况下,问题出在漏了头文件、少了分号、函数名写错这三类。

5.2 运行卡顿、闪屏和按键失效的优化技巧

这套代码最大的视觉缺点是闪屏。因为system("cls")每次清屏都会让控制台闪烁,玩久了眼睛不太舒服。想改善可以试试两个方向:

第一,降低刷新时的“全屏重绘”负担。可以把地图和状态信息绘制到同一个缓冲区,再一次性输出。不过这会引入字符串拼接的复杂度,入门阶段不做也没关系。

第二,用Windows API的SetConsoleCursorPosition把光标移到左上角,而不是清屏。思路是:用GetStdHandle拿到控制台句柄,再设置光标位置到(0,0),这样每次绘制会覆盖旧画面,闪烁明显减轻。这个属于进阶玩法,我不放进基础代码里,但你在网上搜“C++控制台游戏防闪烁”能找到很多现成封装。

关于按键失效,最常见原因是暂停后缓冲区里残留了按键。我在暂停代码里用while (_kbhit()) _getch();清空了缓冲。如果你把暂停功能去掉,这个隐患就不会有。我的建议是先跑通基础版,暂停功能等熟练后再加也行。

5.3 从“能跑”到“好用”的四个扩展方向

这份源码只是地基,往上盖楼的空间很大。我给过几个朋友做扩展练习,比较推荐以下四个方向,难度从低到高:

一是计分加速。每吃到食物,得分增加并让Sleep时间减少一点。比如Sleep(max(30, 100 - score / 2));,注意要包含<algorithm>才能用max。这样游戏会越来越刺激。

二是增加关卡和障碍物。可以在地图中生成若干固定的墙,蛇撞上去就结束。墙的位置可以每关换一批,甚至用随机数生成。这个扩展能让你学会“初始化地图”和“碰撞检测”的复用。

三是历史最高分保存。把最高分写到本地文件里,下次启动时读取。这会用到文件流ifstream和ofstream,是很好的工程练习。

四是改成图形界面。接入简单的图形库,把字符替换成方块贴图。这个方向需要学习事件驱动编程,对入门者来说跨度比较大,但如果你学完基础后想挑战一下,非常值得试。

我个人在实际调这个项目时最大的体会是:贪吃蛇的代码量虽小,但每一步都有值得琢磨的决策。从数据结构的选择,到自撞检测的顺序,再到方向键的读取,任何一个地方想当然,程序就会用各种诡异的bug“回报”你。当你真正把这套逻辑理清楚,你收获的不只是一个能跑的游戏,而是面对任何实时反馈类程序时,脑子里那套清晰的问题拆解方法。

最后再分享一个小技巧:调试的时候,把地图尺寸临时改成10 x 10,速度调慢,食物固定在某个坐标。这样能很快验证移动算法是否正确。等逻辑完全没问题了,再改回正常参数。这个小技巧我每次做类似小游戏都会用,能省下不少盲猜的时间。

相关新闻

工业时序建模:分清机理与机制,才能让模型长出筋骨

工业时序建模:分清机理与机制,才能让模型长出筋骨

1. 先把"机理"这层窗户纸捅破&#xff1a;确定性因果链做工业数据建模这些年&#xff0c;最常碰见的尴尬不是算法调不好&#xff0c;而是开会时一屋子人对着"机理"和"机制"这两个词各说各话。做设备的老师傅嘴里的"机理清楚"&#xff…

2026/10/20 14:48:08 阅读更多 →
机房管理系统落地指南:从SNMP/IPMI选型到告警联动与避坑实践

机房管理系统落地指南:从SNMP/IPMI选型到告警联动与避坑实践

简介&#xff1a;一套面向高校数据库课程设计的机房管理系统完整资料&#xff0c;覆盖机房信息、设备信息、用户信息、预约信息和使用记录等核心业务实体&#xff0c;并针对资源调度、冲突避免与使用分析给出明确的数据组织方案。资源共三个文件&#xff0c;包含两份文档和一份…

2026/10/20 14:48:08 阅读更多 →
融合敏感度先验的条件扩散模型:电阻抗成像重建新思路

融合敏感度先验的条件扩散模型:电阻抗成像重建新思路

最近整理手头的一个电阻抗成像项目代码和实验记录&#xff0c;想把这套技术路线从头到尾理清楚。电阻抗成像&#xff08;Electrical Impedance Tomography&#xff0c;EIT&#xff09;本质上就是个逆问题&#xff1a;边界贴电极&#xff0c;注入已知电流&#xff0c;测一组电压…

2026/10/20 14:48:08 阅读更多 →

最新新闻

Context-Mode 上下文模式:多租户与异步场景下的工程实践指南

Context-Mode 上下文模式:多租户与异步场景下的工程实践指南

1. 从“上下文模式”这个命名说起&#xff1a;它到底在解决什么问题第一次看到“context-mode”这个词&#xff0c;很多人会下意识觉得它是个抽象概念&#xff0c;不像某个具体框架或库那样一眼能看懂。我最初也是这个反应——直到自己在几个项目里反复被同一类问题折磨之后&am…

2026/10/20 15:28:17 阅读更多 →
深入拆解Java包装类与泛型:集合中的类型陷阱与实战排查

深入拆解Java包装类与泛型:集合中的类型陷阱与实战排查

搞Java这么多年&#xff0c;我见过太多人在集合上栽跟头&#xff1a;往ArrayList<Integer>里存了个值&#xff0c;取出来用比较&#xff0c;结果在127和128两个数字上表现完全不一样&#xff1b;想写个List<int>省点内存&#xff0c;编辑器直接报错&#xff1b;自定…

2026/10/20 15:28:17 阅读更多 →
三相并网变流器与SVG无功补偿Simulink仿真建模全解析

三相并网变流器与SVG无功补偿Simulink仿真建模全解析

前段时间做了一套光伏并网方向的仿真模型&#xff0c;客户点名要三相并网变流器带上无功静态补偿的功能&#xff0c;还要带一份能讲清楚原理和结果分析的报告。我一开始也觉得这东西不就是把SVG并联在并网点上嘛&#xff0c;真动手建模才发现里面值得抠的细节比想象中多得多。这…

2026/10/20 15:28:17 阅读更多 →
Unity射击游戏工程快速上手:版本、管线与输入系统避坑指南

Unity射击游戏工程快速上手:版本、管线与输入系统避坑指南

简介&#xff1a;这是一份面向Unity3D初学者与游戏开发入门者的射击小游戏完整工程包&#xff0c;基于Unity5.0构建&#xff0c;适合想通过实战理解引擎核心机制的开发者练手。压缩包共28个文件&#xff0c;约33.73MB&#xff0c;包含dll动态库、config配置、assets资源、exe可…

2026/10/20 15:28:17 阅读更多 →
Django仓库管理系统实战:从库存流水设计到并发扣减与部署

Django仓库管理系统实战:从库存流水设计到并发扣减与部署

做仓库管理这套系统&#xff0c;说起来不算什么特别新鲜的事&#xff0c;但从需求梳理到真正能跑起来、能交到使用者手里&#xff0c;中间隔着的东西远比想象中多。我最近正好把一个基于 Python Django 的仓库管理系统从源码到数据库再到部署文档完整过了一遍&#xff0c;这套…

2026/10/20 15:28:17 阅读更多 →
计组与计网底层逻辑全解析:从CPU到TCP的软硬件协同

计组与计网底层逻辑全解析:从CPU到TCP的软硬件协同

我知道很多同学一看到“计组”和“计网”这两个词&#xff0c;脑子里浮现的就是“背不完的概念”和“算不完的题”。作为一个在计算机领域摸爬滚打多年的老兵&#xff0c;我可以负责任地说&#xff1a;CS基础里的计算机组成原理和计算机网络&#xff0c;恰恰是最能拉开技术上限…

2026/10/20 15:27:16 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →