2026 秋软件工程个人作业(第二次)

「一箭又一箭」小游戏 —— 软件工程课程第二次个人作业

项目 内容
这个作业属于哪个课程 H202601 软件工程与软件工程实践
这个作业要求在哪里 2026 秋软件工程个人作业(第二次)
这个作业的目标 使用 Python 和 AIGC 完成 "一箭又一箭" 小游戏
学号 102401126
GitHub 仓库 https://github.com/diahull/arrow-game

一、项目展示

演示 GIF(开始 → 选关 → 游戏 → 飞出 → 碰撞 → 通关):

demo

开始界面(两步选关:先选难度,再选关卡):

01_menu

01b_menu_level

游戏过程(第 1 关,顶栏显示关卡 / 剩余箭头 / 失误次数 / 倒计时 / 难度):

02_level1_playing

箭头飞出动画(沿方向滑出并淡出):

03_flying_animation

碰撞反馈(箭头晃动、格子变红、提示 "被阻挡!",失误次数 -1):

04_bump_feedback

通关界面与失败界面:

06_level_clear

07_game_over


二、项目介绍

游戏规则

  • 棋盘由网格组成,每个格子中有一支箭头,方向为上、下、左、右四种;

  • 点击一支箭头后,程序检测它前进方向上直到棋盘边界之间是否还有其他箭头:

    • 前方无阻挡 → 箭头飞出棋盘并消失;

    • 前方有阻挡 → 箭头晃动、变红并提示 "被阻挡",同时消耗 1 次失误机会;

  • 清空本关全部箭头即可通关并进入下一关;

  • 失误次数耗尽或超时未清完则本关失败,可重新开始;

  • 每关有时间限制,顶栏实时倒计时,通关时显示本关用时;难度越高时间越短。

界面设计

游戏包含三个阶段的界面:

  1. 开始界面(两步选关):第一步选择难度(简单 / 普通 / 中等 / 困难),第二步进入该难度下选择第 1~4 关,左下角 "返回难度" 可重选;

  2. 游戏界面:顶部信息栏(当前关卡、剩余箭头数量、剩余失误次数、剩余倒计时、当前难度)+ 棋盘 + 提示 / 重新开始 / 返回菜单按钮;

  3. 结果界面:通关界面(显示本关用时,"下一关" 按钮)、失败界面(区分 "时间到" 与 "失误用尽",可重新开始)、全部通关后有 "恭喜通关全部关卡" 界面。

主要功能与特色

  • 四档难度 + 两步选关:简单 / 普通 / 中等 / 困难,难度越高棋盘越大、箭头越多、失误越少、时间越短;

  • 关卡递进:同一难度下越往后越难(每过一关棋盘列数 +1、箭头 +1、时间 -4 秒);

  • 程序化关卡生成:所有关卡由生成器按 "反向构造法" 随机生成,保证每关都可通关,且开局至少存在一支被阻挡的箭头;

  • 限时挑战:每关倒计时,超时判负,通关时显示本关用时;

  • 四种方向箭头用不同颜色区分(↑红 / →绿 / ↓蓝 / ←橙),降低识别成本;

  • 飞出动画(沿方向滑出并淡出)与碰撞反馈(晃动 + 变红 + "被阻挡!" 浮动文字);

  • "提示" 功能:高亮一支当前可飞出的箭头;

  • 快捷键:R 重新开始、H 提示、ESC 返回菜单;

  • 音效由程序首次运行时用 Python 标准库即时合成,无第三方素材、无版权问题。


三、实现思路

1. 箭头、方向与关卡的表示

方向用整数常量表示,配合方向向量便于路径检测:

UP, RIGHT, DOWN, LEFT = 0, 1, 2, 3

DIR_VEC = {UP: (0, -1), RIGHT: (1, 0), DOWN: (0, 1), LEFT: (-1, 0)}

箭头用网格坐标 + 方向表示:Arrow(col, row, direction)。棋盘 Board 持有一组箭头,负责路径检测与移除。关卡是一份字典:列数、行数、失误次数、限时、箭头列表。由于后期改为全部随机生成,关卡数据不再手工维护,而是由 generator.py 按 "难度 + 关卡序号" 作为随机种子现场生成。

2. 路径检测(核心)

对一支箭头,从它所在格子出发,沿其方向一格一格检查,只要在出界之前遇到任意箭头即被阻挡;走到边界仍未遇到箭头则畅通:

def is_blocked(self, arrow):

    dx, dy = DIR_VEC[arrow.direction]

    c, r = arrow.col + dx, arrow.row + dy

    while 0 <= c < self.cols and 0 <= r < self.rows:

        if self.arrow_at(c, r) is not None:

            return True

        c += dx

        r += dy

    return False

关键点在于 while 0 <= c < self.cols and 0 <= r < self.rows:保证边界情况正确 —— 位于边缘、朝向棋盘外的箭头(如第 1 行朝上的 、最右列朝右的 )循环直接不进入,返回 "无阻挡",不会发生数组越界。

3. 关卡可解性校验(贪心求解器)

移除一支 "当前可移除" 的箭头只会减少阻挡、不会让局面变差,因此用贪心即可判断关卡是否可通关:

def solve(board):

    b = board.copy()

    order = []

    while b.arrows:

        cand = b.removable_arrows()

        if not cand:          # 没有可移除箭头但仍有剩余 → 死局

            return False, order

        b.remove(cand[0])

        order.append(cand[0])

    return True, order

早期手工设计关卡时,正是这个求解器发现第 4 关存在死局(同一行里 互相指向对方,形成无法解开的环),调整关卡数据后重新校验通过。改为程序化生成后,该求解器仍作为自动化测试保留。

4. 程序化关卡生成(反向构造法)

需求是 "难度越高棋盘越大、箭头越多,且全部随机生成"。随机撒箭头很容易生成死局,我让 AI 设计了反向构造法:从空棋盘开始逐格放置箭头,每次放置时要求新箭头在当前已放置箭头构成的局面下是可飞出的。最后一个放入的箭头就是第一个飞出的箭头,按放入逆序一定能清空全部箭头 —— 关卡天然可通关。

\# 放置时:从四个方向里挑一个"在当前已放置箭头下畅通"的方向

free = [d for d in range(4) if not blocked_by_placed(col, row, d)]

arrows.append((col, row, choice(free)))

此外加了两条保险:① 开局至少存在一支被阻挡的箭头(否则一关全是直接能点的,没有解谜性);② 生成后再用贪心求解器复验,通不过就换随机种子重试。难度按 DIFFICULTY_PROFILES 表配置,每过一关列数 +1、箭头 +1、时间 -4 秒。

5. 状态机与动画

游戏用简单状态机管理界面流转:

menu(选难度 → 选关卡)→ playing → clear → playing(下一关)

                                   ↘  over  → playing(重新开始)

                             全部通关 → all_clear

飞出动画 FlyingArrow:沿方向按时间插值滑出棋盘并淡出;碰撞反馈 BumpArrow:箭头沿方向小幅晃动、格子变红、浮动文字 "被阻挡!"。点击被阻挡箭头会先扣失误次数,等碰撞动画播完再进入失败界面,避免瞬间跳转。


四、AIGC 使用过程

本次开发使用 豆包(Doubao) 作为 AIGC 编程助手,共记录了 6 次有代表性的协作过程。

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
需求分析与架构设计 豆包 给出模块划分(logic/ui/game/levels)与界面状态机建议 框架清晰,开发顺利 确认文件结构,确定 4 个关卡与失误次数
四方向路径检测 豆包 生成四种方向的路径检测代码 上 / 下 / 左 / 右检测逻辑正确 手工补充 "边缘朝外箭头不越界" 用例,发现并修复校验脚本的解包 bug
关卡设计 豆包 设计关卡并编写贪心求解器 求解器能自动验证通关顺序 人工发现第 4 关死局,调整箭头方向后重新校验通过
碰撞动画 豆包 实现晃动、变红与浮动文字 反馈明显 调整晃动幅度与动画时长,避免抖动过强
自动化测试 豆包 生成路径检测与游戏流程测试用例 26 个用例全部通过 补充 "每关开局存在被阻挡箭头"" 关卡无重复位置 " 等检查
程序化关卡生成器 豆包 给出 "反向构造法" 生成思路与代码 随机关卡天然可通关 手工加了 "开局至少一支被阻挡" 与求解器复验两条保险

记录 1:需求分析与架构设计

提出的要求:向 AI 描述作业要求(点击式箭头解谜、四种方向、路径检测、失误次数、3 个以上关卡、图形界面),请求给出代码结构设计。

AI 完成:建议拆分为 "核心逻辑(与界面无关)" 与 "游戏表现层" 两层,核心逻辑包含箭头、棋盘、路径检测、求解器,表现层包含状态机、动画、UI 按钮;并建议用常量字典表示方向向量。

效果:模块划分让路径检测可以先脱离图形界面单独测试,后续写自动化测试非常方便。

人工修改:确认了最终文件结构(logic.py / levels.py / generator.py / game.py / ui.py / sounds.py),并决定关卡数量为 4 关、每关失误次数 3~4 次。

记录 2:四方向路径检测

提出的要求:实现 "判断箭头前进方向上是否还有其他箭头" 的函数,要求处理上、下、左、右四种方向和边界。

AI 完成:生成了基于方向向量逐格扫描的检测代码。

效果:主体逻辑正确。

人工修改:我补充了需求文档中的两个示例做验证(→ · · ↑ · 中朝右箭头被阻挡;边界箭头可直接飞出)。同时发现校验脚本里求解器返回格式和脚本预期不一致,人工修复;又补了 "位于边缘且朝向棋盘外的箭头不发生越界" 的测试用例。

记录 3:关卡设计与可解性校验

提出的要求:请 AI 设计 3 个以上关卡,并确保存在合理的通关顺序。

AI 完成:先设计关卡数据,再编写贪心求解器自动验证每一关可通关。

效果:求解器输出第 4 关 "不可通关"—— 该关存在 互相指向对方的箭头,形成死局。

人工修改:把其中一支改为朝外方向,解除环状依赖,重新运行求解器后 4 关全部通过。这让我理解了一个重要规则:同一行里 左侧会互相阻挡形成死局,除非其中一支位于边缘朝外。

记录 4:碰撞动画

提出的要求:被阻挡的箭头要有 "晃动、变色或文字" 等明显反馈。

AI 完成:实现了碰撞动画类 —— 箭头沿方向小幅晃动、所在格子变红、上方浮现 "被阻挡!" 文字并逐渐上飘消失。

效果:反馈清晰,且失误次数同步 -1。

人工修改:初始晃动幅度偏大、频率偏高,我调整了幅度系数和动画时长,让抖动更自然。

记录 5:自动化测试

提出的要求:编写测试覆盖作业要求的 T01~T06 场景。

AI 完成:生成基于 unittest 的测试文件,覆盖四方向路径检测、边缘越界、关卡可解性、通关 / 失败 / 重新开始流程,共 26 个用例。

效果:全部通过,且测试驱动我发现了截图脚本和冒烟脚本中的问题。

人工修改:补充了 "每关开局都存在被阻挡箭头"" 关卡内无重复坐标 "两个检查;后期加入难度系统后又补了" 时间随难度递减 ""关卡递进" 两条断言。

记录 6:程序化关卡生成器

提出的要求:要求 "难度越高棋盘越大、箭头越多,且关卡全部随机生成",但随机撒箭头很容易出现死局。

AI 完成:提出 "反向构造法"—— 从空棋盘逐格放置,每次只挑在当前局面下畅通的方向,按放入逆序必可通关。

效果:生成的关卡天然可通关,无需逐关手工验证。

人工修改:我发现纯反向构造生成的关卡有时全部箭头开局就能飞(太简单),于是加了 "开局至少一支被阻挡" 的校验;并保留贪心求解器对每个生成关卡复验一遍,不通过就换种子重试。


五、测试结果

自动化测试(python3 -m unittest discover -s tests -v)与手工试玩相结合。手工试玩对每个难度的关卡各完整通关一遍,确认存在合理通关顺序。

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 箭头沿方向滑出并淡出,剩余箭头数 -1 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 箭头晃动变红提示 "被阻挡!",失误次数 -1 通过
T03 点击位于边缘且朝向棋盘外的箭头 箭头正常消失,不发生越界错误 边缘箭头直接飞出,程序无异常 通过
T04 消除本关全部箭头 显示通关并进入下一关 弹出 "第 X 关 通关!",点击 "下一关" 进入下一关 通过
T05 失误次数耗尽 显示失败并允许重新开始 弹出 "闯关失败",点击 "重新开始" 恢复本关 通过
T06 游戏进行中重新开始 箭头布局和失误次数恢复 棋盘恢复初始布局,失误次数恢复为满值 通过

自动化测试共 26 个用例全部通过:

Ran 26 tests in 0.321s

OK

六、PSP 表格

任务 预估耗时(小时) 实际耗时(小时) 差异(小时)
需求分析与游戏设计 0.5 0.4 -0.1
Python 与图形库学习 1.0 1.0 0
游戏界面实现 2 2.5 +0.5
路径与碰撞逻辑实现 3.0 2.5 -0.5
关卡设计 2.0 2.5 +0.5
AIGC 辅助开发 2.0 3.0 +1.0
测试与修改 2.0 2.5 +0.5
README 与博客撰写 1.5 2.0 +0.5
合计 14.0 16.4 +2.4

七、心得体会

AI 带来的帮助

  1. 架构建议省去了大量试错:AI 一开始就建议把 "路径检测" 这类核心逻辑与图形界面分离,这让逻辑可以先独立测试,也让代码更容易解释;

  2. 代码生成速度快:路径检测、状态机、动画、程序化生成器等常见模式,AI 生成的初版代码可运行率较高,我只需要做边界与细节修正;

  3. 测试用例补全:AI 生成的测试覆盖了作业要求的 T01~T06,还自动验证了每个关卡的可通关性,这在手工试玩之外多了一层保障。

出现的问题

  1. 关卡死局:最初手工设计的第 4 关存在 互相指向对方的箭头,任何顺序都无法通关。这类问题靠眼睛很难发现,最终是靠贪心求解器自动检测出来的;

  2. 边界越界风险:AI 初版代码在向上检测时曾对行号判断不够严谨,通过补充 "边缘朝外箭头" 测试用例后修正;

  3. AI 生成的工具脚本自身也有 bug:关卡校验脚本与求解器返回格式不一致、GIF 工具把连续相同帧合并等,都需要人工阅读输出、定位并修复;

  4. 随机生成关卡太简单:纯反向构造法生成的关卡有时开局全部箭头都能直接飞,没有解谜性,需要人工增加 "开局至少一支被阻挡" 的约束。

收获

通过这次作业,我完整经历了一次 "需求分析 → AIGC 协作开发 → 自动化验证 → 试玩修正 → 文档交付" 的小型软件开发流程。最大的体会是:AI 是高效的 "结对程序员",但理解代码、设计测试、发现死局这些 "把关" 工作必须由自己完成——AI 给出代码,而我对每一行关键逻辑负责。


附:如何运行

pip install -r requirements.txt

python3 main.py

测试:

python3 -m unittest discover -s tests -v
```# 「一箭又一箭」小游戏 —— 软件工程课程第二次个人作业



| 项目         | 内容                                                                             |
| ---------- | ------------------------------------------------------------------------------ |
| 这个作业属于哪个课程 | <课程链接>                                                                         |
| 这个作业要求在哪里  | <作业链接>                                                                         |
| 这个作业的目标    | 使用 Python 和 AIGC 完成 "一箭又一箭" 小游戏                                                |
| 学号         | XXXXXXXX                                                                       |
| GitHub 仓库  | [https://github.com/diahull/arrow-game](https://github.com/diahull/arrow-game) |



***

## 一、项目展示

演示 GIF(开始 → 选关 → 游戏 → 飞出 → 碰撞 → 通关):


![demo](https://img2024.cnblogs.com/blog/3596020/202609/3596020-20260921233704556-147330838.gif)


开始界面(两步选关:先选难度,再选关卡):



![01_menu](https://img2024.cnblogs.com/blog/3596020/202609/3596020-20260921234032200-889349342.png)


游戏过程(第 1 关,顶栏显示关卡 / 剩余箭头 / 失误次数 / 倒计时 / 难度):


![01b_menu_level](https://img2024.cnblogs.com/blog/3596020/202609/3596020-20260921234038187-582807974.png)


箭头飞出动画(沿方向滑出并淡出):



![02_level1_playing](https://img2024.cnblogs.com/blog/3596020/202609/3596020-20260921234042189-2057426227.png)


碰撞反馈(箭头晃动、格子变红、提示 "被阻挡!",失误次数 -1):



![03_flying_animation](https://img2024.cnblogs.com/blog/3596020/202609/3596020-20260921234049551-1526186181.png)


通关界面与失败界面:



![通关](06_level_clear.png)



![失败](07_game_over.png)

(发布博客时请将 `screenshots/` 目录下的图片一并上传到博客系统。)



***

## 二、项目介绍

### 游戏规则



* 棋盘由网格组成,每个格子中有一支箭头,方向为上、下、左、右四种;

* 点击一支箭头后,程序检测它**前进方向**上直到棋盘边界之间是否还有其他箭头:


  * 前方无阻挡 → 箭头飞出棋盘并消失;

  * 前方有阻挡 → 箭头晃动、变红并提示 "被阻挡",同时消耗 1 次失误机会;

* 清空本关全部箭头即可通关并进入下一关;

* 失误次数耗尽或**超时未清完**则本关失败,可重新开始;

* 每关有时间限制,顶栏实时倒计时,通关时显示本关用时;难度越高时间越短。

### 界面设计

游戏包含三个阶段的界面:



1. **开始界面(两步选关)**:第一步选择难度(简单 / 普通 / 中等 / 困难),第二步进入该难度下选择第 1\~4 关,左下角 "返回难度" 可重选;

2. **游戏界面**:顶部信息栏(当前关卡、剩余箭头数量、剩余失误次数、剩余倒计时、当前难度)+ 棋盘 + 提示 / 重新开始 / 返回菜单按钮;

3. **结果界面**:通关界面(显示本关用时,"下一关" 按钮)、失败界面(区分 "时间到" 与 "失误用尽",可重新开始)、全部通关后有 "恭喜通关全部关卡" 界面。

### 主要功能与特色



* **四档难度 + 两步选关**:简单 / 普通 / 中等 / 困难,难度越高棋盘越大、箭头越多、失误越少、时间越短;

* **关卡递进**:同一难度下越往后越难(每过一关棋盘列数 +1、箭头 +1、时间 -4 秒);

* **程序化关卡生成**:所有关卡由生成器按 "反向构造法" 随机生成,保证每关都可通关,且开局至少存在一支被阻挡的箭头;

* **限时挑战**:每关倒计时,超时判负,通关时显示本关用时;

* 四种方向箭头用不同颜色区分(↑红 / →绿 / ↓蓝 / ←橙),降低识别成本;

* 飞出动画(沿方向滑出并淡出)与碰撞反馈(晃动 + 变红 + "被阻挡!" 浮动文字);

* "提示" 功能:高亮一支当前可飞出的箭头;

* 快捷键:`R` 重新开始、`H` 提示、`ESC` 返回菜单;

* 音效由程序首次运行时用 Python 标准库即时合成,无第三方素材、无版权问题。



***

## 三、实现思路

### 1. 箭头、方向与关卡的表示

方向用整数常量表示,配合方向向量便于路径检测:



UP, RIGHT, DOWN, LEFT = 0, 1, 2, 3

DIR_VEC = {UP: (0, -1), RIGHT: (1, 0), DOWN: (0, 1), LEFT: (-1, 0)}


箭头用网格坐标 + 方向表示:`Arrow(col, row, direction)`。棋盘 `Board` 持有一组箭头,负责路径检测与移除。关卡是一份字典:列数、行数、失误次数、限时、箭头列表。由于后期改为全部随机生成,关卡数据不再手工维护,而是由 `generator.py` 按 "难度 + 关卡序号" 作为随机种子现场生成。

### 2. 路径检测(核心)

对一支箭头,从它所在格子出发,沿其方向一格一格检查,只要在出界之前遇到任意箭头即被阻挡;走到边界仍未遇到箭头则畅通:



```c
def is_blocked(self, arrow):

    dx, dy = DIR_VEC[arrow.direction]

    c, r = arrow.col + dx, arrow.row + dy

    while 0 <= c < self.cols and 0 <= r < self.rows:

        if self.arrow_at(c, r) is not None:

            return True

        c += dx

        r += dy

    return False

关键点在于 while 0 <= c < self.cols and 0 <= r < self.rows:保证边界情况正确 —— 位于边缘、朝向棋盘外的箭头(如第 1 行朝上的 、最右列朝右的 )循环直接不进入,返回 "无阻挡",不会发生数组越界。

3. 关卡可解性校验(贪心求解器)

移除一支 "当前可移除" 的箭头只会减少阻挡、不会让局面变差,因此用贪心即可判断关卡是否可通关:

def solve(board):

    b = board.copy()

    order = []

    while b.arrows:

        cand = b.removable_arrows()

        if not cand:          # 没有可移除箭头但仍有剩余 → 死局

            return False, order

        b.remove(cand[0])

        order.append(cand[0])

    return True, order

早期手工设计关卡时,正是这个求解器发现第 4 关存在死局(同一行里 互相指向对方,形成无法解开的环),调整关卡数据后重新校验通过。改为程序化生成后,该求解器仍作为自动化测试保留。

4. 程序化关卡生成(反向构造法)

需求是 "难度越高棋盘越大、箭头越多,且全部随机生成"。随机撒箭头很容易生成死局,我让 AI 设计了反向构造法:从空棋盘开始逐格放置箭头,每次放置时要求新箭头在当前已放置箭头构成的局面下是可飞出的。最后一个放入的箭头就是第一个飞出的箭头,按放入逆序一定能清空全部箭头 —— 关卡天然可通关。

\# 放置时:从四个方向里挑一个"在当前已放置箭头下畅通"的方向

free = [d for d in range(4) if not blocked_by_placed(col, row, d)]

arrows.append((col, row, choice(free)))

此外加了两条保险:① 开局至少存在一支被阻挡的箭头(否则一关全是直接能点的,没有解谜性);② 生成后再用贪心求解器复验,通不过就换随机种子重试。难度按 DIFFICULTY_PROFILES 表配置,每过一关列数 +1、箭头 +1、时间 -4 秒。

5. 状态机与动画

游戏用简单状态机管理界面流转:

menu(选难度 → 选关卡)→ playing → clear → playing(下一关)

                                   ↘  over  → playing(重新开始)

                             全部通关 → all_clear

飞出动画 FlyingArrow:沿方向按时间插值滑出棋盘并淡出;碰撞反馈 BumpArrow:箭头沿方向小幅晃动、格子变红、浮动文字 "被阻挡!"。点击被阻挡箭头会先扣失误次数,等碰撞动画播完再进入失败界面,避免瞬间跳转。


四、AIGC 使用过程

本次开发使用 豆包(Doubao) 作为 AIGC 编程助手,共记录了 6 次有代表性的协作过程。

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
需求分析与架构设计 豆包 给出模块划分(logic/ui/game/levels)与界面状态机建议 框架清晰,开发顺利 确认文件结构,确定 4 个关卡与失误次数
四方向路径检测 豆包 生成四种方向的路径检测代码 上 / 下 / 左 / 右检测逻辑正确 手工补充 "边缘朝外箭头不越界" 用例,发现并修复校验脚本的解包 bug
关卡设计 豆包 设计关卡并编写贪心求解器 求解器能自动验证通关顺序 人工发现第 4 关死局,调整箭头方向后重新校验通过
碰撞动画 豆包 实现晃动、变红与浮动文字 反馈明显 调整晃动幅度与动画时长,避免抖动过强
自动化测试 豆包 生成路径检测与游戏流程测试用例 26 个用例全部通过 补充 "每关开局存在被阻挡箭头"" 关卡无重复位置 " 等检查
程序化关卡生成器 豆包 给出 "反向构造法" 生成思路与代码 随机关卡天然可通关 手工加了 "开局至少一支被阻挡" 与求解器复验两条保险

记录 1:需求分析与架构设计

提出的要求:向 AI 描述作业要求(点击式箭头解谜、四种方向、路径检测、失误次数、3 个以上关卡、图形界面),请求给出代码结构设计。

AI 完成:建议拆分为 "核心逻辑(与界面无关)" 与 "游戏表现层" 两层,核心逻辑包含箭头、棋盘、路径检测、求解器,表现层包含状态机、动画、UI 按钮;并建议用常量字典表示方向向量。

效果:模块划分让路径检测可以先脱离图形界面单独测试,后续写自动化测试非常方便。

人工修改:确认了最终文件结构(logic.py / levels.py / generator.py / game.py / ui.py / sounds.py),并决定关卡数量为 4 关、每关失误次数 3~4 次。

记录 2:四方向路径检测

提出的要求:实现 "判断箭头前进方向上是否还有其他箭头" 的函数,要求处理上、下、左、右四种方向和边界。

AI 完成:生成了基于方向向量逐格扫描的检测代码。

效果:主体逻辑正确。

人工修改:我补充了需求文档中的两个示例做验证(→ · · ↑ · 中朝右箭头被阻挡;边界箭头可直接飞出)。同时发现校验脚本里求解器返回格式和脚本预期不一致,人工修复;又补了 "位于边缘且朝向棋盘外的箭头不发生越界" 的测试用例。

记录 3:关卡设计与可解性校验

提出的要求:请 AI 设计 3 个以上关卡,并确保存在合理的通关顺序。

AI 完成:先设计关卡数据,再编写贪心求解器自动验证每一关可通关。

效果:求解器输出第 4 关 "不可通关"—— 该关存在 互相指向对方的箭头,形成死局。

人工修改:把其中一支改为朝外方向,解除环状依赖,重新运行求解器后 4 关全部通过。这让我理解了一个重要规则:同一行里 左侧会互相阻挡形成死局,除非其中一支位于边缘朝外。

记录 4:碰撞动画

提出的要求:被阻挡的箭头要有 "晃动、变色或文字" 等明显反馈。

AI 完成:实现了碰撞动画类 —— 箭头沿方向小幅晃动、所在格子变红、上方浮现 "被阻挡!" 文字并逐渐上飘消失。

效果:反馈清晰,且失误次数同步 -1。

人工修改:初始晃动幅度偏大、频率偏高,我调整了幅度系数和动画时长,让抖动更自然。

记录 5:自动化测试

提出的要求:编写测试覆盖作业要求的 T01~T06 场景。

AI 完成:生成基于 unittest 的测试文件,覆盖四方向路径检测、边缘越界、关卡可解性、通关 / 失败 / 重新开始流程,共 26 个用例。

效果:全部通过,且测试驱动我发现了截图脚本和冒烟脚本中的问题。

人工修改:补充了 "每关开局都存在被阻挡箭头"" 关卡内无重复坐标 "两个检查;后期加入难度系统后又补了" 时间随难度递减 ""关卡递进" 两条断言。

记录 6:程序化关卡生成器

提出的要求:要求 "难度越高棋盘越大、箭头越多,且关卡全部随机生成",但随机撒箭头很容易出现死局。

AI 完成:提出 "反向构造法"—— 从空棋盘逐格放置,每次只挑在当前局面下畅通的方向,按放入逆序必可通关。

效果:生成的关卡天然可通关,无需逐关手工验证。

人工修改:我发现纯反向构造生成的关卡有时全部箭头开局就能飞(太简单),于是加了 "开局至少一支被阻挡" 的校验;并保留贪心求解器对每个生成关卡复验一遍,不通过就换种子重试。


五、测试结果

自动化测试(python3 -m unittest discover -s tests -v)与手工试玩相结合。手工试玩对每个难度的关卡各完整通关一遍,确认存在合理通关顺序。

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 箭头沿方向滑出并淡出,剩余箭头数 -1 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 箭头晃动变红提示 "被阻挡!",失误次数 -1 通过
T03 点击位于边缘且朝向棋盘外的箭头 箭头正常消失,不发生越界错误 边缘箭头直接飞出,程序无异常 通过
T04 消除本关全部箭头 显示通关并进入下一关 弹出 "第 X 关 通关!",点击 "下一关" 进入下一关 通过
T05 失误次数耗尽 显示失败并允许重新开始 弹出 "闯关失败",点击 "重新开始" 恢复本关 通过
T06 游戏进行中重新开始 箭头布局和失误次数恢复 棋盘恢复初始布局,失误次数恢复为满值 通过

自动化测试共 26 个用例全部通过:

Ran 26 tests in 0.321s

OK

六、PSP 表格

任务 预估耗时(小时) 实际耗时(小时) 差异(小时)
需求分析与游戏设计 0.5 0.4 -0.1
Python 与图形库学习 1.0 1.0 0
游戏界面实现 2 2.5 +0.5
路径与碰撞逻辑实现 3.0 2.5 -0.5
关卡设计 2.0 2.5 +0.5
AIGC 辅助开发 2.0 3.0 +1.0
测试与修改 2.0 2.5 +0.5
README 与博客撰写 1.5 2.0 +0.5
合计 14.0 16.4 +2.4

七、心得体会

AI 带来的帮助

  1. 架构建议省去了大量试错:AI 一开始就建议把 "路径检测" 这类核心逻辑与图形界面分离,这让逻辑可以先独立测试,也让代码更容易解释;

  2. 代码生成速度快:路径检测、状态机、动画、程序化生成器等常见模式,AI 生成的初版代码可运行率较高,我只需要做边界与细节修正;

  3. 测试用例补全:AI 生成的测试覆盖了作业要求的 T01~T06,还自动验证了每个关卡的可通关性,这在手工试玩之外多了一层保障。

出现的问题

  1. 关卡死局:最初手工设计的第 4 关存在 互相指向对方的箭头,任何顺序都无法通关。这类问题靠眼睛很难发现,最终是靠贪心求解器自动检测出来的;

  2. 边界越界风险:AI 初版代码在向上检测时曾对行号判断不够严谨,通过补充 "边缘朝外箭头" 测试用例后修正;

  3. AI 生成的工具脚本自身也有 bug:关卡校验脚本与求解器返回格式不一致、GIF 工具把连续相同帧合并等,都需要人工阅读输出、定位并修复;

  4. 随机生成关卡太简单:纯反向构造法生成的关卡有时开局全部箭头都能直接飞,没有解谜性,需要人工增加 "开局至少一支被阻挡" 的约束。

收获

通过这次作业,我完整经历了一次 "需求分析 → AIGC 协作开发 → 自动化验证 → 试玩修正 → 文档交付" 的小型软件开发流程。最大的体会是:AI 是高效的 "结对程序员",但理解代码、设计测试、发现死局这些 "把关" 工作必须由自己完成——AI 给出代码,而我对每一行关键逻辑负责。


附:如何运行

pip install -r requirements.txt

python3 main.py

测试:

python3 -m unittest discover -s tests -v
```![demo - 副本](https://img2024.cnblogs.com/blog/3596020/202609/3596020-20260921233704556-147330838.gif)
posted @ 2026-09-21 23:56  diahull  阅读(0)  评论(0)    收藏  举报