《一箭又一箭》小游戏开发记录

项目 内容
这个作业属于哪个课程 2026 年软件工程与软件工程实践
这个作业要求在哪里 第二次个人作业:利用 AIGC 完成小游戏
这个作业的目标 使用 Python 和 AIGC 完成一箭又一箭小游戏
学号 102402124
Github仓库 https://github.com/lzh5316/SE-HW2

一、项目展示

作业要求实现“一箭又一箭”的核心玩法:点击箭头,检查它前方有没有其他箭头挡路,没有就让它飞出棋盘并消除,有则失败一次;清空全部箭头通关,失误次数用完则本关失败。

我用 Python + Pygame 独立完成了它,一共 5 个关卡(5×5 到 8×8,6 到 24 支箭头),包含开始界面、游戏界面、通关/失败面板,以及飞出、抖动、飘字、粒子等动画反馈。

图片需先上传到博客园或图床,再把下面的路径替换成实际链接。

![游戏开始界面]
螢幕擷取畫面 2026-09-22 204628

![第 5 关]
螢幕擷取畫面 2026-09-22 0205528

![通关面板]
螢幕擷取畫面 2026-09-22 211254

运行方式:

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 ==============================

五、遇到的问题与解决

  1. 第 3 关死局:用校验脚本定位,改方向后复测通过(上文已述)。
  2. 整套测试崩溃Windows fatal exception: access violation
    原因是上一个用例跑完主循环调用 pygame.quit() 之后,字体缓存里仍是失效的 Font 对象。
    解决:退出时清空字体与背景缓存,并在 conftest.py 中兜底初始化 pygame。
  3. 界面排版:通关瞬间面板盖住动画 → 延迟弹出;提示飘字在第一行被裁掉 → 移到格子下方;
    开始界面两行说明文字轻微重叠 → 调整行距。这些问题都是靠自动生成的截图逐张核对发现的。
  4. 命令行编码:繁体 Windows 控制台(cp950)无法打印简体中文 → 对 stdout 设置 errors="replace"

六、PSP 时间记录

阶段 预估(分钟) 实际(分钟)
需求分析与设计 115 110
编码(逻辑 + 界面 + 动画) 250 235
测试(用例 + 关卡校验 + 排查) 110 115
文档(README / 设计 / 博客 / 截图) 105 90
合计 570 550

七、心得

  • 先想清楚“数据长什么样”,代码会简单很多。方向用行列增量表示之后,
    四方向检测、路径预览、飞出距离计算都变成了同一个循环的不同用法。
  • 可验证的自动化手段(校验脚本、单元测试、离屏截图)是这次效率提升最大的部分,
    尤其“关卡可解性校验”直接把一个隐藏死局挡在了提交之前。
  • AIGC 相当于一个很快的编程搭子:它能给出结构合理、能跑的代码,
    但对“是不是真的能通关”“动画好不好看”“边界会不会炸”没有判断力,这些必须自己把关。
  • 通过这次作业,我把“作业要求 → 功能清单 → 模块设计 → 自动化测试”这条链路完整走了一遍,
    也第一次用脚本给自己的关卡“做质量保证”。
posted @ 2026-09-22 21:29  风间豊  阅读(11)  评论(0)    收藏  举报