软件工程第二次个人作业:用 Python + AIGC 完成《一箭又一箭》
本文如实记录了 AIGC 辅助、人工试玩、自动测试和竞品分析过程。
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 2026 秋软件工程与软件工程实践 |
| 这个作业要求在哪里 | 软件工程第二次个人作业 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | 102402101 |
| 姓名 | 章玲 |
| GitHub 仓库 | Luminance-l/OneArrowGame |
一、项目展示
游戏采用原创的米白纸张风格、四色矢量箭头和程序化合成音乐,没有使用原商业游戏的代码或素材。
开始与关卡选择


游戏过程

推理透视

按 T 或点击“推理透视”可以把路径判断过程直接画在棋盘上:绿色表示前方无遮挡,红色表示被其他箭头阻挡,红圈标出第一个阻挡物。该功能默认关闭,不替玩家自动通关;它更像一张可以随时打开的“解题草稿纸”。
五关通关演示

上图完整包含第 1~5 关,每关开始前都有独立标题卡,分别展示 6、10、15、17、24 步通关过程;点击前保留观察停顿,点击后播放飞出动画,通关结算页也会单独停留。为保证记录可复现,这是一段按照已验证合法路径制作的重放演示,并非真人实时录屏;我另外对五关进行了真实鼠标试玩,人工结果记录在本文测试章节。
通关与失败


二、项目介绍
棋盘中的每支箭只占一个格子,方向分为上、下、左、右。玩家点击箭头后,程序沿其朝向检查同一行或同一列:如果箭头和边界之间没有其他箭头,它会飞出棋盘;否则箭头会变红并晃动,界面显示 BLOCKED,同时失去一次机会。三次机会耗尽则失败,清空棋盘则进入下一关。
基础功能之外,我实现了五关、关卡选择、计时与得分、星级评价、提示、撤销、本地进度保存、AI 自动求解、推理透视,以及背景轻音乐和情境音效。附加功能没有改变基础规则,主要目的是提升可玩性、可解释性和可测试性。
三、竞品与市场思考
数据检索时间:2026-09-21。下载量和评分会随时间变化;下面的市场判断是根据公开商店信息做出的推断,不等同于厂商收入数据。
1. 市面上有哪些竞品
| 类型与代表产品 | 公开表现 | 做得好的地方 | 相对不足或风险 |
|---|---|---|---|
| 全球 3D Tap Away: Tap Away 3D | App Store 约 22.8 万条评分、4.4 分;Google Play 显示 5000 万+下载 | 3D 旋转、皮肤和主题带来强视觉反馈,内容量和商业化体系成熟 | 安装包约 469 MB,开发成本高;广告、内购和同类产品很多,已是红海 |
| 混合玩法: Unpuzzle: Tap Away & Car Out | App Store 约 4.4 万条评分、4.6 分 | 将 Tap Away 与停车解谜组合,内容变化多,生命周期更长 | 规则更复杂、体量约 395 MB,纯粹的“观察—推理—消除”体验被稀释 |
| 国内移动箭头解谜: 箭了个箭、箭了又箭消消 | 前者约 4265 个评分、4.6 分并进入益智解谜榜;后者是 9 MB 安卓轻量游戏 | 一秒上手,适合通勤和小游戏渠道;通过传送门、转向等机制持续加料 | 核心交互接近,名称和美术容易同质化,竞争最后常变成关卡数量与买量能力 |
| 浏览器轻游戏: Arrows | 无需安装,可直接在网页运行 | 进入成本最低,规则与碰撞反馈直观 | 平台替代品多,用户停留和品牌沉淀相对困难 |
2. 哪些市场更好,哪些一般
我认为“更好”要拆成市场规模和独立开发者机会两个维度:
- 全球移动 3D 休闲市场规模最好,但进入难度也最高。 Tap Away 的 5000 万+下载证明需求真实;同时成熟产品已有 3D 美术、海量关卡、皮肤、活动与投放体系。个人项目若只把 2D 改成 3D,很难形成竞争壁垒。
- 国内微信/安卓轻量箭头小游戏仍有传播机会,但同质化最严重。 规则学习成本低、单局时间短,非常适合碎片场景;相反,玩法容易复刻,如果没有新机制或持续关卡供给,热度也容易快速消退。
- 纯 PC 单机商业市场表现一般,但“开源 + 教学 + 可解释解谜”更适合本项目。 它不一定带来最大的用户量,却能服务编程学习、算法展示和无广告离线玩家,和本次软件工程作业的目标高度一致。
因此,我没有追求“做一个更小的商业复制品”,而是选择体量较小但逻辑完整的方向:让玩家不仅知道哪支箭可以点,还能看懂程序为什么这样判断。
3. 我的差异化与不可替代性
我不认为当前作品在商业上“不可替代”——基础点击规则很容易被复现。更准确的说法是,它形成了一个同类轻游戏中少见的组合:
- 可解释玩法: 推理透视把扫描算法可视化,绿线代表安全出口,红线和红圈解释具体阻挡关系。它既是辅助功能,也是算法教学工具。
- 可证明的关卡质量: 每关不是只靠人工声称“应该能过”,而是由 BFS 给出完整解,再由自动测试防止后续修改破坏可解性。
- 规则层可复用:
GameState完全不依赖 Pygame,可以用于测试、命令行演示或以后接入其他界面。 - 克制且透明: 游戏离线运行、无广告、无内购,不收集数据;代码、关卡、矢量界面和程序化音频均可检查和复现。
真正较难替代的不是某一个按钮,而是“原创关卡 + 可解释提示 + 求解器证明 + 自动测试 + 开源过程记录”这一整套可信开发链路。这也是我在竞品分析后新增推理透视,而不是盲目堆叠特效的原因。
四、实现思路
1. 数据结构
Arrow 是不可变数据类,保存 row、col 和 Direction。当前棋盘使用字典 dict[(row, col), Arrow],因此判断某个格子是否被占用是 O(1)。Direction 枚举同时保存方向增量,例如 UP 为 (-1, 0)、RIGHT 为 (0, 1)。
关卡在 level.py 中以二维元组保存;加载关卡时转换成箭头字典。界面层只读取状态,不直接修改关卡数组。
2. 路径检测
核心算法从箭头前方一格开始,每次增加 (dr, dc),直到遇到其他箭头或离开棋盘。这里特别注意不能从箭头自身开始,否则每支箭都会被自己阻挡。
dr, dc = arrow.direction.delta
row, col = arrow.row + dr, arrow.col + dc
while 0 <= row < size and 0 <= col < size:
blocker = arrows.get((row, col))
if blocker is not None:
return blocker
row += dr
col += dc
return None
时间复杂度为 O(n),其中 n 是棋盘边长;空间复杂度为 O(1)。
3. 状态与动画分离
GameState.click() 只返回 removed、blocked、empty 或 ignored,便于测试。Pygame 收到 removed 后创建一个短生命期的 FlyingArrow,按方向移动并逐渐降低透明度;收到 blocked 后记录时间戳,在 650ms 内让箭头变红、左右晃动并显示提示。
这种分离使自动测试不必打开窗口,也避免动画帧率影响规则正确性。
4. AI 自动求解
求解器使用广度优先搜索。一个搜索状态是剩余箭头坐标的 frozenset;从该状态可以移除任意一支当前无遮挡的箭头。搜索到空集合时得到完整通关路径。提示功能只显示路径的第一步,而测试会要求所有关卡都能搜索到完整路径。
第 5 关初版就被求解器发现不可解,这比只依赖肉眼试玩更可靠。修改一支箭方向后,5 个关卡分别得到 6、10、15、17、24 步完整解。
5. 推理透视如何解释算法
透视模式遍历当前所有箭头,复用与点击判定完全相同的 blocker_for()。若没有阻挡,就沿方向画到棋盘边缘;若有阻挡,就把射线终止在首个阻挡箭头并加红圈。因此画面解释与真实规则来自同一个数据源,不会出现“提示说能走、实际却扣机会”的两套逻辑。
五、AIGC 使用过程
我使用 OpenAI Codex 辅助需求拆解、编码、测试与文档整理,下面是最有代表性的五次协作。
| 子任务 | AIGC | AI 实现/提供 | 实际效果 | 人工判断与修改 |
|---|---|---|---|---|
| 需求与结构 | Codex | 将 PDF 要求拆成规则、界面、测试、文档四层 | 核心逻辑可脱离 Pygame 测试 | 保留“基础优先”,删去复杂机关设想 |
| 路径检测 | Codex | 方向枚举与逐格扫描 | T01–T03、四方向测试通过 | 增加边缘朝外、首个阻挡物用例 |
| 关卡设计 | Codex | 5 个关卡与 BFS 求解器 | 首次发现第 5 关不可解 | 将 (3,1) 从 UP 改为 LEFT,复测得到 24 步解 |
| UI 与动画 | Codex | 矢量箭头、飞出淡出、碰撞晃动、截图模式 | 首次截图按钮出现方框字 | 删除不兼容字符,并修复结算计时继续增长 |
| 竞品与差异化 | Codex | 检索竞品并提出推理透视 | 将后台算法转为玩家可见的绿/红路径解释 | 默认关闭避免降低难度,新增 T 开关和回归测试 |
我体会到,AIGC 可以快速产出结构完整的初稿,但不会自动保证关卡可解,甚至测试代码本身也可能写错。只有真正运行、观察失败信息并设计回归测试,AI 输出才会变成可靠的软件。
六、测试结果
我将课程规定的 6 个测试全部写成自动化测试,并增加四方向、撤销、提示、全关卡可解性和音频资源完整性测试。
| 编号 | 测试内容 | 预期结果 | 实际结果 | 结论 |
|---|---|---|---|---|
| T01 | 无阻挡箭头 | 飞出并消失 | 返回 removed,数量减 1 |
通过 |
| T02 | 有阻挡箭头 | 保留,机会减 1 | (2,2) 被 (2,4) 阻挡,3→2 |
通过 |
| T03 | 边缘朝外箭头 | 正常消失且不越界 | (1,0) 向左正常移除 |
通过 |
| T04 | 清空关卡 | 显示通关并进入下一关 | 状态 CLEARED,出现结算层 |
通过 |
| T05 | 机会耗尽 | 显示失败并可重开 | 状态 FAILED,出现“再试一次” |
通过 |
| T06 | 重新开始 | 布局和机会恢复 | 状态、箭头、机会均恢复 | 通过 |
执行命令:
python -m unittest discover -s tests -v
最终结果为 12/12 通过。此外还生成六张界面截图,逐张检查了字体、裁切、遮挡和按钮状态,并实际验证推理透视、背景音乐与四类情境音效能够正常工作。
人工试玩记录
自动测试负责验证规则,人工试玩负责检查真实操作体验。我使用鼠标完整试玩了五个关卡,结果如下:
| 关卡 | 箭头数量 | 人工试玩结果 | BFS 验证结果 |
|---|---|---|---|
| 第 1 关:初见 · 四向 | 6 | 正常通关 | 6 步可解 |
| 第 2 关:交错 · 留白 | 10 | 正常通关 | 10 步可解 |
| 第 3 关:回声 · 回廊 | 15 | 正常通关 | 15 步可解 |
| 第 4 关:棱镜 · 逆光 | 17 | 正常通关 | 17 步可解 |
| 第 5 关:终章 · 星阵 | 24 | 正常通关 | 24 步可解 |
试玩时还检查了被阻挡箭头的红色晃动、三次失误后的失败界面、重新开始、下一关、提示、撤销、推理透视和静音开关。
七、PSP 表格
| 任务 | 预估耗时(小时) | 实际耗时(小时) | 差异 |
|---|---|---|---|
| 需求分析与游戏设计 | 0.8 | 0.5 | -0.3 |
| Python 与图形库学习 | 0.8 | 0.3 | -0.5 |
| 游戏界面实现 | 1.8 | 1.3 | -0.5 |
| 路径与碰撞逻辑实现 | 1.5 | 0.9 | -0.6 |
| 关卡设计 | 1.2 | 0.7 | -0.5 |
| AIGC 辅助开发 | 1.0 | 0.8 | -0.2 |
| 测试与修改 | 1.2 | 0.9 | -0.3 |
| README 与博客撰写 | 1.5 | 1.5 | 0.0 |
| 竞品分析与推理透视 | 0.8 | 0.6 | -0.2 |
| 合计 | 10.6 | 7.5 | -3.1 |
八、心得体会
这次作业让我感受最深的不是 Pygame 绘图,而是“看起来能玩”和“可以证明正确”之间的差别。路径扫描只有十几行,但方向、起点和边界任何一个细节都可能导致错误;关卡看起来很丰富,也可能形成互相阻挡的死环。
Codex 帮我快速搭好了结构、界面和测试初稿,但实际运行仍发现了不可解关卡、错误测试坐标、字体缺字和计时问题。解决这些问题时,我学会了把 UI 与规则拆开、用小测试定位错误、用求解器验证关卡,而不是反复手点碰运气。
竞品分析也让我意识到,“功能更多”不等于“产品更独特”。3D、皮肤和海量关卡是成熟商业产品的优势,个人作业很难正面竞争;把已有算法转化为推理透视,反而更符合项目规模,也让软件工程中的“可解释、可验证”成为玩家能看到的体验。
如果继续完善,我会加入关卡编辑器和可执行文件打包,并让玩家导出自己设计且经求解器验证的关卡。不过就本次作业而言,我更愿意保持规则清楚、依赖简单、测试充分,让别人按照 README 可以一次运行成功。
浙公网安备 33010602011771号