2026秋软件工程个人作业(第二次)
软件工程第二次个人作业:基于 Python 与 AIGC 的“一箭又一箭”解谜小游戏开发
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 202601 软件工程 |
| 这个作业要求在哪里 | 2026秋软件工程个人作业(第二次) |
| 这个作业的目标 | 借助 AIGC 工具,使用 Python 独立开发“一箭又一箭”小游戏,掌握项目架构设计、路径算法实现、自动化测试与团队协作工具链 |
| 学号 | 102401609 |
| GitHub 仓库 | King-Zhi/ArrowByArrow |
一、项目展示
根据作业要求(“展示开始界面、游戏过程、通关或失败界面,建议提供演示 GIF 或视频”),本项目提供实机演示视频与核心界面静态截图,全方位展现游戏视效与交互逻辑:
1. 游戏实机演示视频
说明:演示视频时长约 23 秒,完整覆盖了开始界面、游戏过程(消除/碰撞/提示)、关卡通关界面与失败结算重试界面。

2. 核心界面截图对照
(1) 游戏开始界面
赛博朋克合成波暗色调设计,具备粒子星空、地平线透视网格、标题呼吸动效、独立 BGM/音效开关与纯几何矢量图标:

(2) 游戏过程与交互反馈
- 箭头消除与飞出动画:点击前方畅通的箭头,箭头沿其指向高速飞出视口,并激发出绚丽的动态彩光粒子。
- 阻挡碰撞与物理反馈:点击被阻挡的箭头,箭头向前探出后受阻回弹,产生阻尼指数衰减的正弦晃动,并触发红色警示粒子,失误次数精准扣减 1;在此期间开启互斥锁定保护。

(3) 关卡选择列表
内置 4 大难度梯度关卡,清晰指示各关网格尺寸与箭头密集度,支持快捷跳转与挑战:

(4) 通关与失败结算界面
- 关卡通关结算:清空所有箭头后呼出结算弹窗,展示过关耗时、失误次数,并根据表现评定一星至三星,点击可无缝进入下一关。
- 失败与重试:失误次数耗尽时弹出警示窗口,支持快速重新开始当前关卡。

二、项目介绍
1. 游戏规则
游戏棋盘为标准的二维正交网格,格中分布有若干带有明确方向属性(上、下、左、右)的箭头:
- 消除规则:玩家用鼠标左键点击某个箭头后,系统检测该箭头前进方向与棋盘边界之间的射线路径。如果路线上不存在其他未消除箭头的阻挡,该箭头便顺利飞出棋盘并被清除。
- 阻挡与失误:若路线上存在其他活跃箭头,该箭头无法离开棋盘,触发受阻晃动动画,同时扣减一次宝贵的失误机会。
- 通关与失败:清空本关所有箭头后即获胜并解锁下一关;若失误机会耗尽(变为 0),关卡判定失败,允许玩家随时重置当前关卡。
2. 界面设计与主要特色
- 视觉风格:采用符合现代主流游戏审美的深空暗色系(Dark Theme)卡片式设计,高对比度高亮箭头多边形,长时间游玩不伤眼。
- 物理动画:支持平滑的二次曲线加速飞出动画以及带有指数衰减的正弦碰撞摆动反馈,告别生硬的瞬移。
- 零依赖程序音效:使用 Python 标准库
wave与数学函数纯代码实时合成 16-bit PCM 游戏音效(消除呼啸声、木质顿挫敲击声、通关和弦琶音与失败哀鸣),彻底杜绝了外部音效文件丢失、音画脱节或商业素材侵权的问题。 - 高分附加功能:集成了关卡选择列表、步数撤销(Undo)、智能提示(Hint)、AI 拓扑自动演示求解、用时统计与星级评价系统。
三、实现思路
1. 数据结构设计
在 src/core/arrow.py 中,定义了强类型的 Direction 枚举与 Arrow 实体:
- 方向向量表示:
每个方向被赋予网格行(row)和列(col)的增量向量(dr, dc):UP:(-1, 0)(向上移动,行坐标减 1)DOWN:(1, 0)(向下移动,行坐标加 1)LEFT:(0, -1)(向左移动,列坐标减 1)RIGHT:(0, 1)(向右移动,列坐标加 1)
- 状态机与动画:
箭头具备IDLE(静止就绪)、FLYING(飞出中)、COLLIDING(受阻晃动)和ELIMINATED(已消除)四种离散状态,帧循环中利用anim_progress计算屏幕像素级位移插值。
2. 核心算法:射线投射路径检测 (Raycast Path Detection)
路径检测是整个游戏最为核心的算法,位于 src/core/board.py 中的 is_path_clear 方法:
def is_path_clear(self, arrow: Arrow) -> Tuple[bool, Optional[Arrow]]:
"""
判断箭头在其朝向的行/列方向上,直至棋盘边界,是否存在其他未消除箭头的阻挡。
"""
r, c = arrow.row, arrow.col
dr, dc = arrow.direction.delta
curr_r = r + dr
curr_c = c + dc
# 沿方向向量单步向前扫描,直至越出棋盘边界
while 0 <= curr_r < self.rows and 0 <= curr_c < self.cols:
target_cell = (curr_r, curr_c)
if target_cell in self.grid:
blocker = self.grid[target_cell]
# 若路线上存在实体未消除的箭头,即构成阻挡
if blocker.state != ArrowState.ELIMINATED:
return False, blocker
curr_r += dr
curr_c += dc
# 扫描线安全穿出棋盘边界,未遇到任何阻挡
return True, None
- 边界安全性设计:如果箭头本身位于边缘且朝向外侧(例如
(0, 0)且朝向UP),则在首次计算后curr_r = -1,while循环条件直接不成立,直接判定为(True, None),不仅逻辑严密,而且从根本上避免了数组索引越界异常。
3. 关卡可解性与拓扑求解器 (Topological Peeling Solver)
为了严格落实作业要求的“确保关卡可以正常通关”,我们在 src/core/solver.py 中实现了拓扑消解算法:
- 算法遍历当前棋盘中所有无阻挡的箭头候选集;
- 模拟依次剥离,若剩余箭头无法继续剥离但数量不为 0,则表明存在类似死锁的闭环死局(A 挡 B,B 挡 C,C 挡 A);
- 关卡加载器在游戏初始化阶段会对每一个关卡进行预检,一旦存在死锁即阻止加载,从源头上保证了预设关卡的 100% 可通关性。
四、AIGC 使用过程记录
在本次项目的研发流程中,我们全面借助了现代 AIGC 工具(基于 Google DeepMind Gemini 的 Coding Agent)作为结对编程伙伴。但在实际开发与测试过程中,AI 生成的代码暴露出多处深层逻辑缺陷、界面交互阻断与打包兼容性 Bug。我们没有盲目信任 AI,而是通过扎实的真机实测与严谨的代码审查,主导发现了多项关键缺陷并督促 AI 进行了精准排查与重构。
以下为本次开发过程中极具代表性的 4 次真实协作记录汇总:
1. AIGC 协作记录汇总表
| 子任务 | 借助何种 AIGC 技术 | AI 实现或提供了什么 | 效果如何 | 人工分析与修改 |
|---|---|---|---|---|
| 提示交互与输入派发 | Antigravity(Gemini) | 实现了智能提示高亮算法与呼吸动画 | 提示激活时,点击其他受阻箭头无任何响应,点击事件被阻断 | 指出“提示时点不了受阻箭头”,指导 AI 解耦提示层与点击层,恢复全局点击判定 |
| 关卡星级成就结算 | Antigravity(Gemini) | 编写了关卡通关与大满贯结算弹窗 | 终极关卡出现 2 次失误通关后,弹窗依然固定显示 3 星满分评价 | 发现“最后一关通关后总是3星”,指导 AI 抽离统一的星级计算函数,严格绑定当关失误数据 |
| UI 跨平台字符与视觉 | Antigravity(Gemini) | 采用 Unicode 字符拼装按钮图标与基础界面 | 在缺少对应字库的 Windows 上,按钮图标全部沦为方块乱码(□) | 要求废除字符拼接,改用纯数学几何矢量路径绘制图标,并重构为 80s 赛博合成波主题 |
| 物理受阻与输入防抖 | Antigravity(Gemini) | 实现了受阻前冲物理动画与失误扣心 | 最后一颗心扣除时提前弹窗破坏动画 | 要求将扣心推迟至真实撞击瞬间并延后结算 |
2. 深度协作与 Bug 修复案例详解
案例 1:提示激活状态下点击受阻箭头无响应 Bug
- 提出的要求:实现“智能提示”功能(快捷键
H),高亮当前可行箭头;要求提示高亮期间,玩家依然可以自主点击棋盘上的任意箭头尝试探索,系统应正常给出飞出或碰撞反馈。 - 借助工具:Antigravity(Google Antigravity)
- AI 实现与提供:AI 顺利实现了拓扑扫描与金色呼吸光环,但在派发点击事件时,错误地对提示状态施加了互斥逻辑,导致点击判定被拦截。
- 实际效果与发现的 Bug:在真机试玩测试时,人工开启提示后,去点击位于第 5 行第 5 列向下的蓝色方框箭头(前方有阻挡),鼠标点击毫无反应,箭头既不向前飞跃撞击,也不产生晃动或扣心。
- 人工分析与修改:人工立刻在交互中敏锐捕获并指出该阻断缺陷:“还有个 bug,在提示的时候点不了蓝色框那个箭头……点击了这个箭头没有反应,也没有碰撞”。人工指导 AI 审查
game_app.py中的_handle_click与hover_cell逻辑,要求将“提示高亮”彻底降级为纯视觉引导层,不得拦截鼠标左键向底层 Board 派发网格坐标。修复后,提示状态下点击任何箭头均能正常产生物理碰撞与扣心,若点击畅通箭头则顺利飞出并自动消除提示框。
案例 2:终极关卡通关固定显示 3 星结算 Bug
- 提出的要求:根据玩家在当前关卡中消耗的失误次数动态评星(0失误为3星,1失误为2星,2失误为1星)。
- 借助工具:Antigravity (Google Antigravity)
- AI 实现与提供:AI 编写了结算弹窗渲染函数,支持常规关卡结算与全通关大满贯结算。
- 实际效果与发现的 Bug:在全流程通关测试中,人工特意在第 4 关故意点错两次、心形仅剩最后 1 颗时才完成通关,结果弹窗弹出的居然依然是金灿灿的“★★★ 三星达成”!
- 人工分析与修改:人工当即提出质询:“最后一关通关后似乎总是3星?”。经检查发现,AI 在切换到全局胜利状态
GameState.ALL_CLEAR时,直接复用了初始化时的常量数据或错误引用了上一关的初始满血状态。人工指导 AI 将星级计算重构成独立的纯函数_calculate_stars(board),让普通关卡通关和最终通关均统一传入当前的 Board 实体,根据board.mistakes严格计算实际星级,彻底修平了这一隐蔽的数据流传递漏洞。
案例 3:UI 按钮方块乱码(□)与赛博合成波矢量重构
- 提出的要求:重构游戏主界面与 HUD,杜绝字符集兼容问题,打造具有视觉张力的现代街机解谜风格。
- 借助工具:Antigravity (Google Antigravity)
- AI 实现与提供:AI 最初给出的按钮渲染使用了特殊的 Unicode 符号(如
▶,⚙,♫,💡,✖)拼装在文字前方。 - 实际效果与发现的 Bug:在测试机不同的 Windows 字体配置下,这些特殊符号无法被默认中文字体解析,直接变成了难看的白色方块(□),既不美观又严重影响操作辨识。
- 人工分析与修改:人工明确指出字符库依赖不可靠,要求彻底弃用文本符号。指导 AI 改用纯数学几何路径绘制矢量图标(在
src/ui/renderer.py中通过pygame.draw.polygon和pygame.draw.line实时计算三角形、折线、几何齿轮与音符)。同时,人工主导了视觉风格升级,引入深邃星空、洋红/青色地平线透视网格与 80s 赛博合成波(Synthwave)暗色卡片,消除了所有平台乱码隐患。
案例 4:连续点击受阻箭头导致动画穿模与扣心时序错乱
- 提出的要求:受阻箭头向前冲撞并回弹,产生逼真的物理打击感与红色警示火花,失误次数扣减 1。
- 借助工具:Antigravity (Google Antigravity)
- AI 实现与提供:AI 最初直接在检测到阻挡的瞬间扣减心形,并启动了一个独立的局部位移动画。
- 实际效果与发现的 Bug:当玩家快速连续点击同一个或多个受阻箭头时,多个箭头同时在空单元格中位移飞跃并互相穿模重叠;尤其致命的是,在只剩 1 颗心时,刚点下鼠标瞬间(箭头尚未接触障碍物),屏幕就骤然弹出失败弹窗,打断了动作过程,视觉逻辑严重割裂。
- 人工分析与修改:人工要求系统必须具备物理真实性与严格的时序因果律,指导 AI 落实三项关键改动:
- 碰撞复位互斥锁:在
Board中新增has_colliding_arrow()状态查询,只要有箭头正处于冲撞或回弹原位的过程中,系统全面锁定输入并隐藏悬浮框,杜绝多箭头穿模; - 帧精确碰撞接触:将心形扣减时机从“点击瞬间”延后至“箭头尖端与障碍物边缘相切的碰撞关键帧”;
- 死亡动画优雅缓冲:在扣除最后一颗心后启动
fail_timer,完整播放飞跃、撞击、火花、反弹滑回的全套“死亡绝唱”,等待 0.45 秒动画彻底归位后再呼出失败弹窗。
- 碰撞复位互斥锁:在
五、项目测试与质量保证
1. 作业核心测试用例(T01 ~ T06)记录表
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头脱离网格飞出棋盘并消失,失误次数不变 | 箭头进入 FLYING 状态并移出网格,失误次数未扣除 |
通过 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,产生受阻晃动,失误次数减 1 | 箭头进入 COLLIDING 晃动动画,失误次数减 1 |
通过 |
| T03 | 点击位于边缘且朝向棋盘外的箭头 | 箭头正常飞出消失,不发生数组越界错误 | 正常判定为 Clear 并飞出,无任何越界异常 | 通过 |
| T04 | 消除本关全部箭头 | 显示关卡通关结算,并允许进入下一关 | 触发 LEVEL_CLEAR 状态,成功切换至第 2 关 |
通过 |
| T05 | 失误次数耗尽(剩余 0 次) | 显示失败弹窗并允许重新开始 | 触发 GAME_OVER 状态,点击重试恢复初始生命 |
通过 |
| T06 | 游戏进行中点击“重新开始” | 棋盘箭头布局与失误次数恢复初始状态 | 箭头全部复位,失误次数重置为 3,历史清空 | 通过 |
2. 自动化单元测试运行结果
通过 Python 标准 unittest 模块对核心逻辑进行了全面的回归测试:
$ python -m unittest discover -s tests
..........
----------------------------------------------------------------------
Ran 10 tests in 0.261s
OK
测试不仅严格覆盖了 T01 ~ T06 的全部作业规格场景,还包含了所有预设关卡拓扑可解性验证(test_all_preset_levels_solvable)、提示与撤销扩展功能测试(test_hint_and_undo_features)、受阻碰撞归位互斥锁测试(test_cannot_click_while_another_arrow_is_colliding)以及音频与 BGM 管理器 API 测试(test_sound_manager_bgm_and_sound_toggles),全部 10 项测试通过率 100%。
六、PSP 耗时表格
| 任务 / 阶段 | 预估耗时(小时) | 实际耗时(小时) | 差异(小时) | 原因与分析(与正文完全对应) |
|---|---|---|---|---|
| 需求分析与游戏设计 | 1.0 | 1.2 | +0.2 | 对应正文第二节:除作业基本规则外,细化了星级评定、失误扣心与关卡梯度架构,耗时略超预估 |
| Python 与图形库学习 | 1.5 | 1.0 | -0.5 | 对应正文第四节:借助 AI 快速掌握 Pygame 事件循环与 Surface 双缓冲机制,上手较快节约了时间 |
| 游戏界面实现 | 2.0 | 2.8 | +0.8 | 超出预估(对应第四节案例3):字符图标跨平台渲染为方块乱码(□),推翻重构为纯几何矢量绘制并升级赛博合成波主题 |
| 路径与碰撞逻辑实现 | 2.0 | 2.8 | +0.8 | 超出预估(对应第三节及第四节案例4):实机发现连点穿模与扣心提前,增加了碰撞归位互斥锁与接触关键帧同步判定 |
| 关卡设计 | 1.5 | 2.0 | +0.5 | 对应正文第三节:高难度第 4 关遭遇首尾死锁,编写了拓扑消解判定算法(Solver)并进行逆向生成验证 |
| AIGC 辅助开发 | 1.5 | 2.2 | +0.7 | 超出预估(对应第四节案例1、2):与 AI 结对多轮排错,抓出提示阻断点击、终局固定三星结算等隐蔽缺陷,提示词调优与代码审查耗时增加 |
| 测试与修改 | 1.5 | 2.2 | +0.7 | 超出预估(对应第五节及第七节):除 10 项自动化单测外,多轮真机实测抓出用时显示 0 秒、状态死锁等交互 Bug,调试耗时增加 |
| README 与博客撰写 | 1.5 | 1.8 | +0.3 | 严格对齐 Git 仓库实际跟踪的代码结构,详实梳理 4 大真实 AIGC 协作案例与测试数据 |
| 合计 | 12.5 | 16.0 | +3.5 | 总体实际耗时多出 3.5 小时。初期搭建框架迅速,但后期在 UI 跨平台重构、状态机互斥锁与隐蔽 Bug 修复上投入了更多时间 |
七、心得体会与总结
-
AI 是强大的生产力倍增器,但绝不能做“甩手掌柜”:
在项目起步阶段,AI(Coding Agent)展现出了惊人的脚手架搭建能力。无论是 Pygame 窗口骨架、基于数学波形的零依赖 PCM 音效合成算法,还是有向图拓扑可解性算法,AI 都能在极短时间内给出高质量的代码框架,帮助我省去了大量翻阅底层 API 文档的繁琐耗时。这让我深刻认识到 AIGC 在“探索原型设计”与“扫清技术盲区”上的巨大赋能。 -
单体测试无法替代真机实测,深层交互缺陷往往隐藏在复合状态机中:
这次开发中最让我警醒的是:AI 编写的代码在跑通离散的基础单元测试时几乎全绿,但一旦进入真实人机交互与状态流转,就暴露出大量严重的体验硬伤——比如开启提示呼吸光环后,普通受阻箭头的点击事件竟然被意外阻断无响应;打通终局关卡时,星级计算未绑定当局真实数据,哪怕多次失误依然虚假显示满分 3 星;甚至在自动化截取通关图时,留下了“通关用时 0 秒”这种明显脱离实际的假象。这让我深刻意识到:软件测试绝不仅仅是跑几个预设好的断言函数,开发者必须亲自坐在屏幕前进行全流程探索性测试,去体验每一个点击手感与状态边界。 -
对工程交付细节与底层规范的重新审视:
在后续的跨平台兼容、独立打包与文档交付过程中,AI 多次暴露出“浮于表面”的问题:比如按钮使用 Unicode 特殊字符导致跨平台白框乱码(□);在生成 README 架构树时盲目扫描本地文件夹,把被.gitignore排除的临时文件也错误写入。正是通过一次次人工审查与纠偏,促使我深入理解了Pygame 矢量几何光栅化与严格的 Git 版本控制规范。
总结:结对编程并不是让 AI 代替人类思考,而是让开发者从繁琐的机械性敲代码中解放出来,转变为一名更高维度的架构设计师、边界审查者与质量把关人。唯有保持严谨的批判性思维,软件工程的质量防线才真正牢不可破。

浙公网安备 33010602011771号