《一箭又一箭》小游戏开发记录
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 2026 年软件工程与软件工程实践 |
| 这个作业要求在哪里 | 第二次个人作业:利用 AIGC 完成小游戏 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成一箭又一箭小游戏 |
| 学号 | 102402124 |
| Github仓库 | https://github.com/lzh5316/SE-HW2 |
一、项目展示
作业要求实现“一箭又一箭”的核心玩法:点击箭头,检查它前方有没有其他箭头挡路,没有就让它飞出棋盘并消除,有则失败一次;清空全部箭头通关,失误次数用完则本关失败。
我用 Python + Pygame 独立完成了它,一共 5 个关卡(5×5 到 8×8,6 到 24 支箭头),包含开始界面、游戏界面、通关/失败面板,以及飞出、抖动、飘字、粒子等动画反馈。
图片需先上传到博客园或图床,再把下面的路径替换成实际链接。
![游戏开始界面]

![第 5 关]

![通关面板]

运行方式:
pip install -r requirements.txt
python main.py # 从开始界面进入
python main.py --level 3 # 直接跳到第 3 关
二、实现思路
1. 先分层,再写代码
我把项目分成“规则层”和“界面层”:
- 规则层:
config.py(常量)、levels.py(关卡数据)、board.py(棋盘与路径检测)、solver.py(求解器)——完全不依赖 pygame; - 界面层:
ui.py(按钮/面板/箭头绘制)、animation.py(动画)、scenes.py(场景)、app.py(主循环)。
这样规则可以脱离窗口测试。整套 59 个自动化用例只需要 1.4 秒,改逻辑时不用开窗口。
2. 路径检测:一个循环同时处理阻挡与边界
四个方向用“行增量、列增量”表示:
DIRECTION_DELTA = {UP: (-1, 0), DOWN: (1, 0), LEFT: (0, -1), RIGHT: (0, 1)}
判断时从箭头所在格沿方向逐格前进:先遇到箭头 → 被阻挡;先越出棋盘 → 可以飞出。
两种情况共用一个循环条件 while 0 <= row < rows and 0 <= col < cols,
因此永远不会读到棋盘外的数据,T03 的越界问题从结构上就不存在。
3. 鼠标悬停时的通道预警
为了降低挫败感,鼠标停在箭头上时会:
- 把前方通道的格子染色:畅通为青色、被挡为红色;
- 给挡住去路的那支箭头加红框,给鼠标指向的箭头加白框。
这样玩家点下去之前就知道结果,但依然要自己规划顺序。
4. 动画反馈
- 成功:箭头沿方向“先慢后快”飞出棋盘,带渐隐拖尾与粒子;
- 碰撞:箭头左右抖动并变红、飘出“前方有阻挡!”、屏幕轻微震动、失误爱心闪一下;
- 结果面板延迟 0.55 / 0.8 秒弹出,先让玩家看清动画。
5. 关卡怎么保证一定能通关
这一条是整个作业里最值得记录的。我先定一个“消箭顺序”,再倒着把箭头摆回棋盘:
放回一支箭头时只要保证它前进方向上没有已经摆好的箭头就行(等价于它在正向里更早被消掉)。
这样构造出的布局,正向一定能按逆序依次消除。
但“构造上可解”不等于“实际可解”,所以我还写了个校验脚本:
python tools/validate_levels.py -r docs/LEVEL_REPORT.txt
结果它真的抓到了一处死局:第 3 关的 (4,4)朝右 需要等 (4,5) 先走,
而 (4,5)朝左 又需要等 (4,4) 先走,两支箭头互相锁死。
把 (4,5) 改成 朝上 之后,5 个关卡全部通过“贪心 + 穷举”双重验证。
顺带还证明了一个有意思的结论:因为消除箭头只会让通道更空、不会制造新的阻挡,
所以本游戏不存在“选错顺序把自己堵死”的情况。
这一点我用穷举搜索对 60 个随机盘面做了交叉验证。
三、AIGC 使用过程
开发中使用 Cline 辅助,模型侧我接的是自己注册的 DeepSeek。完整记录见仓库 docs/AIGC_LOG.md。中间踩过接口和模型能力的坑,也碰到过 AI 生成的关卡不能玩,挑几件比较有代表性的说。
一开始我图省事,用别人给的第三方 API Key 接工具,结果一调用就报 Invalid token。我检查了半天配置,最后确认就是这个 key 不能用。后来我自己注册了 DeepSeek,换成自己的 key,才把调用跑通。
刚换 DeepSeek 时还闹了个乌龙。我发了一张很长的图给它,结果直接报错。我当时真有点怀疑是不是模型坏了,后来才知道 DeepSeek 是纯文本模型,根本看不了图。这个错误挺低级,但也让我记住:不同模型能做什么、不能做什么,得先搞清楚,不能默认它什么都能干。
环境配置这块,我用了 Cline 这个 AI 编程助手,让它帮我建 Pygame 环境。它会一步步给命令、装依赖、改配置,确实省了我不少翻教程的时间。对当时只想快点进到玩法实现的我来说,这一步帮助很大。
但快不代表一定对。Cline 写代码很快,一个关卡没多久就能生成出来。有一次它写出来的关卡,我实际玩的时候发现根本过不去,是个死局。刚开始我还以为是自己操作问题,试了几次才确定:这关设计本身就有问题。于是我让它重新写,调整之后关卡才变成能正常通关的版本。后来我又补了校验脚本,结果它真的抓到第 3 关的 (4,4)朝右 需要等 (4,5) 先走,而 (4,5)朝左 又需要等 (4,4) 先走,两支箭头互相锁死。把 (4,5) 改成朝上之后,5 个关卡才全部通过“贪心 + 穷举”双重验证。
后面继续用 Cline 辅助代码结构、测试和排查。挑三次代表性的:
| 子任务 | AIGC 工具 | 我提出的要求 | AI 产出了什么 | 实际效果 | 我的修改 |
|---|---|---|---|---|---|
| 代码结构 | Cline + DeepSeek | 把作业要求拆成功能清单并给出模块划分 | config/levels/board/solver/ui/animation/scenes/app 分层方案,规则层不依赖 pygame |
结构清晰,测试好写 | 把字体加载从 config.py 拆成 fonts.py,避免命令行脚本被迫初始化 pygame |
| 关卡设计 | Cline + DeepSeek | 设计 5 关并保证都能通关 | “逆向构造法” + 可解性校验脚本 | 第 3 关被校验脚本判定为无解(两支箭头互相锁死) | 手工调整 (4,5) 的方向后复测 |
| 测试与排查 | Cline + DeepSeek | 按 T01–T06 写自动化测试 | 5 个测试文件、59 个用例 | 单文件能过,整套连跑时 access violation 崩溃 |
在 App.shutdown() 清空字体/背景缓存 + 兜底初始化 |
最深的体会:AI 写代码很快,但“代码是否真的满足要求”必须自己验证。API Key 要自己确认,模型边界要自己弄明白,关卡能不能通关要自己试,退出后的缓存崩溃、飘字越界这类问题,AI 第一次都不会主动发现,是靠“跑校验脚本 + 逐帧截图核对 + 自己试玩”才暴露出来的。
四、测试过程与结果
| 编号 | 测试内容 | 预期结果 | 实际结果 |
|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 通过:箭头被消除,剩余箭头减少,失误次数不变 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,失误次数减 1 | 通过:箭头抖动变红 + 飘字,失误次数 -1 |
| T03 | 点击边缘且朝向棋盘外的箭头 | 正常消失,不越界报错 | 通过:四个角与四条边均正常,点击棋盘外无反应 |
| T04 | 消除本关全部箭头 | 通关并进入下一关 | 通过:弹出“关卡完成!”面板,可进入下一关;最后一关显示“全部通关!” |
| T05 | 失误次数耗尽 | 显示失败并允许重新开始 | 通过:弹出“游戏失败”面板,可重新开始 |
| T06 | 进行中重新开始 | 布局与失误次数恢复 | 通过:箭头、失误次数、计时全部复原 |
自动化测试:
$ python -m pytest -q
collected 59 items
tests\test_board.py ..................... [ 35%]
tests\test_game_flow.py ...... [ 45%]
tests\test_levels.py ......... [ 61%]
tests\test_scenes.py ................. [ 89%]
tests\test_solver.py ...... [100%]
============================= 59 passed in 1.35s ==============================
五、遇到的问题与解决
- 第 3 关死局:用校验脚本定位,改方向后复测通过(上文已述)。
- 整套测试崩溃:
Windows fatal exception: access violation。
原因是上一个用例跑完主循环调用pygame.quit()之后,字体缓存里仍是失效的Font对象。
解决:退出时清空字体与背景缓存,并在conftest.py中兜底初始化 pygame。 - 界面排版:通关瞬间面板盖住动画 → 延迟弹出;提示飘字在第一行被裁掉 → 移到格子下方;
开始界面两行说明文字轻微重叠 → 调整行距。这些问题都是靠自动生成的截图逐张核对发现的。 - 命令行编码:繁体 Windows 控制台(cp950)无法打印简体中文 → 对 stdout 设置
errors="replace"。
六、PSP 时间记录
| 阶段 | 预估(分钟) | 实际(分钟) |
|---|---|---|
| 需求分析与设计 | 115 | 110 |
| 编码(逻辑 + 界面 + 动画) | 250 | 235 |
| 测试(用例 + 关卡校验 + 排查) | 110 | 115 |
| 文档(README / 设计 / 博客 / 截图) | 105 | 90 |
| 合计 | 570 | 550 |
七、心得
- 先想清楚“数据长什么样”,代码会简单很多。方向用行列增量表示之后,
四方向检测、路径预览、飞出距离计算都变成了同一个循环的不同用法。 - 可验证的自动化手段(校验脚本、单元测试、离屏截图)是这次效率提升最大的部分,
尤其“关卡可解性校验”直接把一个隐藏死局挡在了提交之前。 - AIGC 相当于一个很快的编程搭子:它能给出结构合理、能跑的代码,
但对“是不是真的能通关”“动画好不好看”“边界会不会炸”没有判断力,这些必须自己把关。 - 通过这次作业,我把“作业要求 → 功能清单 → 模块设计 → 自动化测试”这条链路完整走了一遍,
也第一次用脚本给自己的关卡“做质量保证”。

浙公网安备 33010602011771号