Python贪吃蛇实战:30行代码掌握游戏开发核心逻辑
1. 项目概述为什么用30行代码写贪吃蛇如果你刚学Python看了一堆语法变量、循环、列表都懂了但总觉得离“做出点什么”还差一口气那这个项目就是为你准备的。用Python的pygame库30行左右的代码实现一个能跑、能玩、有碰撞检测的经典贪吃蛇游戏。这听起来像是个噱头但它的价值在于它能把你学过的零散知识点——比如列表操作、循环控制、事件处理——瞬间串联成一个看得见、摸得着的成果。这种正反馈是看十遍教程都给不了的。贪吃蛇这个游戏规则极简蛇头控制方向吃到食物变长撞墙或撞到自己就结束。但正是这种简单让它成为入门游戏开发的绝佳练手项目。你不需要纠结复杂的图形和物理引擎可以完全专注于程序逻辑本身。而pygame作为一个专为2D游戏设计的库接口直观文档友好特别适合新手快速上手建立“我也可以做游戏”的信心。2. 环境准备与核心工具解析2.1 Python与Pygame的安装与验证工欲善其事必先利其器。第一步是确保你的Python环境就绪。我推荐使用Python 3.8或更高版本它们对各类库的兼容性更好。你可以打开命令行Windows上是CMD或PowerShellmacOS/Linux上是Terminal输入python --version或python3 --version来检查。如果显示版本号说明已安装。接下来安装pygame。这是最关键的一步很多新手在这里卡住。最稳妥的方式是使用pipPython的包管理工具。在命令行中执行pip install pygame如果你系统里有多个Python版本可能需要用pip3。如果遇到网络超时可以尝试使用国内的镜像源加速例如pip install pygame -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后不要急着写代码先写一个几行的测试脚本验证库是否正常工作。创建一个名为test_pygame.py的文件写入以下内容import pygame pygame.init() screen pygame.display.set_mode((400, 300)) pygame.display.set_caption(Pygame Test) running True while running: for event in pygame.event.get(): if event.type pygame.QUIT: running False screen.fill((0, 0, 0)) # 用黑色填充屏幕 pygame.display.flip() # 更新屏幕显示 pygame.quit()运行这个脚本如果弹出一个黑色的窗口并且点击窗口关闭按钮能正常退出那么恭喜你pygame环境配置成功。这个测试脚本本身就是一个极简的游戏循环框架后面我们会基于它扩展。注意有些集成开发环境IDE如PyCharm或VS Code可能会为每个项目创建独立的虚拟环境。如果你在IDE的终端里安装了pygame但在运行脚本时依然提示“ModuleNotFoundError: No module named pygame”很可能是因为你没有在项目的虚拟环境中安装。需要在IDE的终端或设置里确认当前使用的Python解释器路径。2.2 代码编辑器与项目结构规划对于这个项目任何文本编辑器都可以但我强烈推荐使用VS Code或PyCharm这类智能编辑器。它们能提供代码高亮、自动补全和错误提示能极大提升效率尤其是当你记不清pygame某个函数名的时候。在动手前先在脑子里或纸上规划一下代码结构。虽然我们目标是30行但逻辑必须清晰。核心模块无非这几个初始化导入库初始化pygame设置游戏窗口。游戏状态定义蛇的坐标用一个列表存储食物的坐标蛇的移动方向游戏是否结束的标志。主循环游戏的心脏不断重复“处理事件 - 更新逻辑 - 绘制画面”这个过程。事件处理监听键盘按键改变蛇的移动方向。游戏逻辑更新根据方向移动蛇头检查是否吃到食物坐标重合检查是否撞墙或撞到自己。图形绘制在屏幕上画出蛇的每一节和食物。按照这个思路即使代码紧凑也不会变成一团乱麻。我们追求的是简洁而不是混乱。3. 核心逻辑拆解与代码实现3.1 游戏世界的初始化与基本参数让我们开始写真正的游戏代码。首先创建一个新文件比如snake_game.py。开头当然是导入必要的模块并初始化pygame。import pygame import random # 初始化 pygame.init()接下来定义一些游戏常量。使用常量而不是直接把数字写在代码里是个好习惯方便后期调整。# 游戏常量 WIDTH, HEIGHT 600, 400 # 游戏窗口大小 GRID_SIZE 20 # 网格大小也是蛇身和食物的尺寸 FPS 10 # 游戏帧率控制蛇的移动速度这里的关键是GRID_SIZE。我们将游戏窗口想象成一个网格蛇和食物都占据网格的一个格子。这样蛇的移动就不是平滑的像素移动而是从一个格子“跳”到下一个格子大大简化了碰撞检测和坐标计算。FPSFrames Per Second控制了游戏循环每秒运行的次数也就间接控制了蛇的移动速度。10 FPS意味着蛇每秒移动10个“逻辑帧”速度比较适中。然后创建游戏窗口和时钟对象。# 创建窗口 screen pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption(30行贪吃蛇) clock pygame.time.Clock()screen对象代表了游戏窗口我们所有的绘制操作都发生在这个“画布”上。clock对象用于控制游戏循环的速度确保它在不同的电脑上都能以基本相同的速度运行。3.2 蛇与食物的数据表示与绘制如何用数据表示一条蛇最经典的方式是使用一个列表列表中的每个元素是一个(x, y)坐标元组代表蛇身一节的位置。蛇头就是列表的第一个元素索引0蛇尾是最后一个。# 游戏初始状态 snake [(WIDTH // 2, HEIGHT // 2)] # 蛇初始位置在屏幕中央 snake_dir (GRID_SIZE, 0) # 蛇初始向右移动 (dx, dy) food (random.randrange(0, WIDTH, GRID_SIZE), random.randrange(0, HEIGHT, GRID_SIZE)) # 食物随机位置 game_over Falsesnake_dir是一个表示方向的向量(GRID_SIZE, 0)表示每帧在x轴上增加一个网格宽度y轴不变即向右移动。食物的坐标通过random.randrange生成确保其x和y坐标都是GRID_SIZE的整数倍从而对齐网格。绘制蛇和食物非常简单。在pygame中我们可以用pygame.draw.rect函数画矩形。# 绘制函数 def draw(): screen.fill((0, 0, 0)) # 清屏黑色背景 # 画蛇 for segment in snake: pygame.draw.rect(screen, (0, 255, 0), (*segment, GRID_SIZE, GRID_SIZE)) # 绿色蛇身 # 画食物 pygame.draw.rect(screen, (255, 0, 0), (*food, GRID_SIZE, GRID_SIZE)) # 红色食物 pygame.display.flip() # 更新整个屏幕这里(*segment, GRID_SIZE, GRID_SIZE)是Python的解包操作。因为segment是(x, y)元组所以这等价于(segment[0], segment[1], GRID_SIZE, GRID_SIZE)构成了pygame.draw.rect所需的(x, y, width, height)参数。pygame.display.flip()是将我们在内存中画好的这一帧图像真正更新到显示器上。3.3 游戏主循环与事件处理游戏的核心是一个while循环只要game_over不为True循环就会一直进行。每一轮循环我们称之为一“帧”。# 主游戏循环 while not game_over: # 1. 处理事件 for event in pygame.event.get(): if event.type pygame.QUIT: game_over True elif event.type pygame.KEYDOWN: if event.key pygame.K_UP and snake_dir ! (0, GRID_SIZE): snake_dir (0, -GRID_SIZE) elif event.key pygame.K_DOWN and snake_dir ! (0, -GRID_SIZE): snake_dir (0, GRID_SIZE) elif event.key pygame.K_LEFT and snake_dir ! (GRID_SIZE, 0): snake_dir (-GRID_SIZE, 0) elif event.key pygame.K_RIGHT and snake_dir ! (-GRID_SIZE, 0): snake_dir (GRID_SIZE, 0)事件处理是游戏与玩家交互的桥梁。pygame.event.get()获取当前帧发生的所有事件比如按键、鼠标移动。我们主要关心两种QUIT事件点击窗口关闭按钮和KEYDOWN事件按下键盘。控制蛇转向的逻辑有个关键限制不能直接反向。例如蛇正在向右移动(GRID_SIZE, 0)此时按下左键(-GRID_SIZE, 0)会导致蛇头瞬间掉头撞到自己这通常是不被允许的。所以我们在判断按键时加了一个条件新的方向不能是当前方向的直接反方向。3.4 游戏状态更新移动、吃食与死亡判定处理完玩家输入就要更新游戏内部的状态这是游戏逻辑的核心。# 2. 更新游戏状态 # 计算新的蛇头位置 head_x, head_y snake[0] new_head (head_x snake_dir[0], head_y snake_dir[1])首先根据当前蛇头位置和移动方向计算出下一帧蛇头应该出现的新位置new_head。接下来进行碰撞检测# 碰撞检测撞墙或撞自己 if (new_head[0] 0 or new_head[0] WIDTH or new_head[1] 0 or new_head[1] HEIGHT or new_head in snake): game_over True break条件判断了三件事1. 蛇头x坐标是否超出窗口左/右边界2. 蛇头y坐标是否超出窗口上/下边界3. 新的蛇头位置是否已经存在于蛇身的坐标列表中即撞到自己。只要满足其一游戏结束。如果没发生碰撞就把新的蛇头位置插入到蛇身列表的最前面snake.insert(0, new_head)然后判断是否吃到食物# 吃食物判断 if new_head food: # 生成新的食物确保不在蛇身上 while True: food (random.randrange(0, WIDTH, GRID_SIZE), random.randrange(0, HEIGHT, GRID_SIZE)) if food not in snake: break else: # 没吃到食物移除蛇尾保持长度不变 snake.pop()如果蛇头的新位置和食物位置重合就表示吃到了。这时我们不需要移除蛇尾pop操作蛇自然就变长了一节。然后需要在一个循环里随机生成新的食物位置并确保这个新位置不在蛇身的任何一节上。如果没吃到食物就执行snake.pop()移除列表最后一个元素蛇尾这样蛇的总长度保持不变实现了“移动”的效果。实操心得食物生成这个循环在蛇很长、几乎占满屏幕时可能会短暂地空转很多次才能找到空位。对于这个小游戏无伤大雅但如果要做更复杂的可以考虑预先计算所有空位格子然后随机选择一个效率更高。最后完成这一帧的绘制和速度控制# 3. 绘制 draw() # 4. 控制帧率 clock.tick(FPS)clock.tick(FPS)是点睛之笔它告诉pygame“这一帧循环已经处理完了请暂停一下确保从循环开始到现在的时间刚好是 1/FPS 秒。” 这样就实现了稳定的10帧每秒的更新速度。循环结束后退出pygamepygame.quit()4. 代码优化与功能扩展思路4.1 30行代码的极致压缩与可读性权衡网上流传的“极简版”贪吃蛇往往通过牺牲可读性来压缩行数。例如将初始化、绘制、逻辑更新全部挤进主循环去掉所有函数定义和常量使用短变量名。虽然看起来厉害但不利于学习和调试。我们上面的代码结构清晰约50行已经非常精简。如果非要追求“30行”可以在我们清晰版的基础上进行合并。例如将绘制代码直接写入主循环将方向判断写成字典映射合并一些语句。但我要强调的是对于学习和项目而言清晰可维护的代码远比行数少更重要。你写代码是给人包括未来的自己看的不是给行数统计器看的。我们练习压缩行数的目的是更好地理解Python的语法糖和表达方式而不是以此为目标。4.2 增加游戏功能与提升可玩性基础版本跑通后你可以尝试添加更多功能这才是提升编程能力的正道分数显示在吃到食物时增加一个score变量并在屏幕左上角用pygame.font模块渲染显示出来。游戏结束界面当game_over为True时不要立即退出而是显示“Game Over”和最终得分并提示按R键重新开始。难度递增可以让分数每增加10分FPS就加1这样蛇会越跑越快增加挑战性。音效使用pygame.mixer在吃到食物和游戏结束时播放简单的音效。障碍物在游戏区域随机生成一些不可通过的障碍物方块增加游戏复杂度。每一个小功能的添加都会涉及到新的pygame模块和编程逻辑是绝佳的练习。4.3 从脚本到可执行文件打包分发当你做出了一个让自己满意的版本可能想分享给不会安装Python的朋友。这时就需要打包成独立的可执行文件.exe。最常用的工具是PyInstaller。首先安装它pip install pyinstaller。然后在命令行中进入你的游戏脚本所在目录执行pyinstaller --onefile --windowed snake_game.py--onefile将所有依赖打包成一个单独的exe文件。--windowed运行时不显示命令行控制台窗口对于图形游戏很必要。命令执行后会在当前目录生成一个dist文件夹里面就是打包好的exe文件。你可以把这个文件发给任何人他们在Windows上双击就能运行。踩坑记录打包时最常见的错误是找不到资源文件如图片、字体、音效。如果你的代码里用到了本地文件需要确保PyInstaller能将其打包进去。更高级的做法是使用pyinstaller的--add-data参数指定资源路径。对于我们的纯代码版本则没有这个问题。5. 常见问题与调试技巧实录即使代码逻辑清晰第一次运行时也难免遇到各种“坑”。这里记录几个最常见的问题和排查思路。5.1 运行时报错与导入问题问题运行脚本立即报错ModuleNotFoundError: No module named pygame。排查这说明pygame没有安装到当前Python环境。请确认你安装pygame的命令行环境和运行脚本的环境是否是同一个Python。可以分别用pip list和python -m pygame --version检查。是否使用了虚拟环境venv在PyCharm或VS Code中确保终端激活了正确的虚拟环境并在其中重新安装pygame。问题窗口一闪而过或者打开后无法关闭。排查这通常是游戏循环的逻辑问题。检查while循环的条件是否可能永远为真或者事件处理中是否没有正确响应pygame.QUIT事件。确保你的代码中有for event in pygame.event.get():和if event.type pygame.QUIT:这段逻辑。5.2 游戏逻辑异常与行为纠错问题蛇可以瞬间掉头直接撞死自己。排查检查方向控制的代码。确保在判断“上”键时排除了当前方向是“下”的情况即snake_dir ! (0, GRID_SIZE)。其他方向同理。这是贪吃蛇游戏最常见的逻辑漏洞之一。问题食物有时会出现在蛇的身体上。排查检查食物生成的代码。在吃到食物后生成新食物的循环while True:中必须确保if food not in snake:条件成立才能break。最好在循环内加一个打印语句或者在生成后立即绘制检查看看食物坐标是否合法。问题蛇移动起来一卡一卡的或者速度不稳定。排查这通常和clock.tick(FPS)有关。首先确认FPS的值是否合理10左右比较像经典贪吃蛇。其次确保clock.tick(FPS)是在每一帧循环的最后调用。如果把它放在循环开头或中间会导致帧率计算不准。5.3 性能与体验优化点绘制优化我们的draw()函数每一帧都重绘整个屏幕。对于这个简单游戏没问题。但如果元素很多可以考虑“脏矩形”更新只重绘发生变化的部分。不过在真正遇到性能问题之前不要过早优化。输入处理我们当前只处理了KEYDOWN按键按下事件。这会导致如果长按方向键蛇的移动会取决于键盘的重复速率可能不跟手。一个更流畅的方案是在事件处理中只记录按下的方向键设置一个next_dir变量然后在游戏逻辑更新时用next_dir去更新snake_dir。这样可以确保每一帧只响应一次有效的方向改变更符合直觉。代码组织当功能越来越多时考虑将游戏状态蛇、食物、分数等封装成一个类如GameState将绘制逻辑封装成函数或另一个类。这样主循环会变得非常干净只有handle_events(state),update(state),draw(state)几个调用可读性和可维护性会大大提升。写这个30行的贪吃蛇就像搭乐高。你手头的积木Python基础语法是有限的但通过清晰的逻辑游戏循环把它们组合起来就能创造出有生命力的互动程序。这个过程里遇到的每一个错误解决的每一个问题都比单纯看语法书印象深十倍。试着去改它加分数、改颜色、变规则在动手试错中编程才会从知识变成你的技能。

相关新闻

Unity安卓14闪退:解决Attempt to load writable dex file错误

Unity安卓14闪退:解决Attempt to load writable dex file错误

1. 项目概述:一次典型的Unity安卓14兼容性危机最近在社区里看到不少Unity开发者朋友都在讨论同一个棘手的问题:项目在安卓14设备上突然闪退,而日志里赫然出现一行令人困惑的错误——Attempt to load writable dex file: /data/user/0/xxx/cac…

2026/10/8 12:22:59 阅读更多 →
前端开发者必看:收藏这份2026年AI Agent开发实战路线图,轻松转型“智能体指挥官”

前端开发者必看:收藏这份2026年AI Agent开发实战路线图,轻松转型“智能体指挥官”

本文为前端开发者量身打造了一份AI Agent开发学习路线图,结合2026年最新技术栈,帮助读者从基础的前端技能转型为掌握大模型与工具集成的“智能体指挥官”。内容涵盖Node.js/Deno、LLM调用库、Prompt Engineering、工具调用、记忆系统、流式响应、任务规划…

2026/10/2 10:58:23 阅读更多 →
收藏必备!小白程序员轻松入门大模型:揭秘 RL-LLM 的 Aha Moment 与推理链奥秘

收藏必备!小白程序员轻松入门大模型:揭秘 RL-LLM 的 Aha Moment 与推理链奥秘

本文深入探讨了 DeepSeek 团队的 R1-Zero 实验中,模型在没有 CoT 监督数据的情况下,通过 RL 训练自发产生推理链的现象,即“Aha Moment”。文章详细解析了 CoT 能力的两种来源:模仿型(SFT)和探索型&#xf…

2026/10/5 11:05:07 阅读更多 →

最新新闻

豆包长对话滚动卡顿优化:Tampermonkey脚本实战解析

豆包长对话滚动卡顿优化:Tampermonkey脚本实战解析

用豆包网页版做长对话,最难受的不是AI偶尔答非所问,而是聊了二十轮、三十轮之后,整个页面的滚动开始“粘手”。鼠标滚轮轻轻一格,页面要么纹丝不动,要么顿一下再猛跳一截;快速往上翻历史消息时,…

2026/10/9 11:00:48 阅读更多 →
Excel数据透视图制作全攻略:从数据准备到图表刷新

Excel数据透视图制作全攻略:从数据准备到图表刷新

先说一个我经常遇到的场景:月初拿到一份全公司上个月的订单明细,上千行数据,老板让我按区域、按产品线分别看销售额和订单量。如果靠手工拉公式或者复制粘贴汇总,少说也得折腾大半天。但只要把这份明细扔进“数据透视图”&#xf…

2026/10/9 11:00:48 阅读更多 →
数据属性定性与定量全解析:数学建模中如何避免属性判断失误

数据属性定性与定量全解析:数学建模中如何避免属性判断失误

1. 从一次建模翻车说起:为什么数据属性是道绕不过去的坎刚接触数学建模那会儿,我踩过一个现在想起来还觉得脸红的坑。当时拿到一份关于城市交通流量的数据集,里面有车流量、平均车速、路段编号、天气状况这么几列。我二话不说,把所…

2026/10/9 11:00:48 阅读更多 →
【新手速上手】OpenClaw 2.6.4 部署报错修复与完整教程(内含安装包)

【新手速上手】OpenClaw 2.6.4 部署报错修复与完整教程(内含安装包)

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

2026/10/9 11:00:48 阅读更多 →
数据属性与测量尺度:数学建模中定性与定量数据的判定与处理指南

数据属性与测量尺度:数学建模中定性与定量数据的判定与处理指南

1. 数据属性到底在分什么:从一次建模翻车说起前两年带一个模拟项目,题目给了一张几百行的表格,字段包括“年龄段”“满意度评分”“城市等级”“月均消费”。队里一位同学上来就把所有列一股脑塞进相关性矩阵,跑出来一堆0.7以上的…

2026/10/9 11:00:48 阅读更多 →
viewport meta标签:移动Web渲染的底层控制开关

viewport meta标签:移动Web渲染的底层控制开关

1. 为什么“viewport”不是个可有可无的meta标签,而是页面渲染的生死开关你有没有遇到过这样的情况:在手机上打开自己写的网页,文字小得像蚂蚁,图片被强行压缩变形,按钮点不到,滑动卡顿,整个页面…

2026/10/9 10:59:47 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 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/8 21:13:17 阅读更多 →
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/8 15:26: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/9 6:17:20 阅读更多 →