软件工程 第二次作业

Arrow Escape小游戏开发作业报告

作业信息

项目 内容
这个作业属于哪个课程 202601 软件工程
这个作业要求在哪里 作业 16717
这个作业的目标 使用 Python 和 AIGC 完成「ARROW ESCAPE」小游戏
学号 182400143
GitHub 仓库 Ther-ux/Arrow_Escape
项目名称 Arrow Escape · 箭境
开发日期 2026 年 9 月

一、项目展示

项目使用 Python 和 Pygame 实现,包含开始界面、游戏界面、通关界面和失败界面。下面的截图来自当前版本的自动化窗口验证,除了基础流程,还展示了提示、撤销、随机可解关卡、AI 自动求解和 Windows 可执行文件等扩展功能。

开始界面

最新进阶玩法开始界面

进阶玩法支持标准模式的难度选择,也支持困难无尽模式。无尽模式在每次通关后随机生成下一关,并保证存在可通关顺序:

无尽模式设置

普通玩法还提供固定三关、更加紧凑的基础界面:

最新普通玩法开始界面

普通模式运行演示:从普通模式首页进入游戏,展示箭头点击、碰撞反馈、重开和第一关通关流程。

普通模式运行演示

游戏过程

最新游戏棋盘和扩展功能按钮

游戏侧栏可以直接看到提示次数、撤销、重开和 AI 求解按钮。

点击可释放的箭头后,箭头会沿当前方向飞出,尾线逐段跟随:

AI 自动求解过程

AI 求解会复用正常的路径判断和飞行动画,按钮在运行期间变为“停止 AI”。

点击前方有阻挡的箭头时,箭头不会消失,并产生红色碰撞反馈,同时扣除一次失误机会:

最新碰撞反馈

点击“提示”后,程序会消耗一次提示机会并高亮当前可以直接释放的箭头:

提示高亮

完成一次有效点击后可以点击“撤销”,恢复箭头或返还碰撞消耗的失误机会:

撤销反馈

进阶模式完整运行演示:包含进阶设置、提示、撤销、AI 自动求解和通关流程。

进阶模式运行演示

柔性尾线的转向、跟随和回弹效果由独立演示验证:

柔性尾线演示

通关和失败结果

AI 自动求解后的通关结果

失败界面

自动化 UI 流程能够完成三个原始关卡、切换下一关、失败、重开、返回首页和退出窗口。随机生成器和 AI 求解器也通过了关卡清空测试。

二、项目介绍

Windows 打包产物为 dist/ArrowEscape.exe,文件大小约 15.3 MB。项目使用 Python 和 Pygame 实现,包含基础玩法和进阶玩法两种模式。

2.1 游戏规则

棋盘由网格组成,每个非空格子中放置一个朝向上、下、左或右的箭头。玩家点击箭头后,程序检查它朝向棋盘边界的整条直线路径:

  1. 前方没有其他箭头时,箭头飞出棋盘并从棋盘状态中移除。
  2. 前方存在其他箭头时,箭头保留在原位置,播放碰撞反馈,并消耗一次失误机会。
  3. 清除当前关卡的全部箭头后显示通关结果,可以进入下一关。
  4. 失误机会归零后显示失败结果,可以重新开始当前关卡。

每局默认有 3 次失误机会和 3 次提示机会。点击 R 或“重新开始”可以恢复当前关卡的原始布局;按 Esc 返回首页。

2.2 主要功能

功能 说明
基础玩法 固定的 3 个原创关卡,使用紧凑棋盘和基础箭头样式
进阶玩法 支持标准模式、简单/中等/困难难度,以及困难无尽模式
路径判断 支持四个方向、边界箭头、近距离和远距离阻挡
飞出动画 非阻塞加速飞出,尾线跟随,末箭动画完成后才显示结果
碰撞反馈 320 ms 左右的前冲、回弹、震动和红色反馈
提示 高亮一支当前可以合法离场的箭头,不自动点击
撤销 撤销最近一次有效点击,恢复飞出的箭头或返还碰撞消耗的机会
AI 求解 自动寻找当前合法箭头,按正常动画顺序完成关卡
随机关卡生成 根据难度和箭头数量生成随机布局,并保证存在合法通关顺序
进度保存 保存无尽模式下一关编号,重新启动后继续挑战
柔性尾线 使用 Verlet 节点、距离约束和曲线采样绘制连续尾线

2.3 界面设计

项目采用暗色极简科技风:背景接近 #0D1224,使用青蓝色表示主要交互,绿色表示成功,珊瑚红表示碰撞或失败,紫色作为辅助色。按钮和棋盘命中测试共用同一套几何换算,减少“看得见但点不到”的问题。

三、实现思路

3.1 项目结构

main.py                程序入口
core/arrow.py          Arrow 模型与四方向枚举
core/path_checker.py   纯路径检测函数
core/board.py          棋盘占用状态
core/game.py           游戏状态机、点击结果和动画计时
core/progress.py       无尽模式进度读写
data/levels.py         关卡数据、难度和可解关卡生成
ui/app.py              Pygame 页面、按钮、事件和主循环
ui/rope.py             Verlet 柔性尾线模拟
ui/routes.py           尾线路径规划
ui/rope_renderer.py    尾线平滑曲线和抗锯齿绘制
tests/                 路径、状态、界面和尾线测试
tools/smoke_ui.py      自动化窗口流程与截图
tools/rope_demo.py     柔性尾线独立演示

3.2 箭头和棋盘表示

箭头使用不可变数据类表示,核心字段为 rowcoldirection。方向使用枚举表示,并映射到行列增量:

UP    = (-1, 0)
DOWN  = (1, 0)
LEFT  = (0, -1)
RIGHT = (0, 1)

棋盘使用 (row, col) -> Arrow 的字典保存占用状态。成功点击后立即从字典中删除箭头,绘制层再使用动画副本显示它飞出,因此后续箭头可以马上利用新开放的路径。

3.3 路径检测

core/path_checker.py 中的 is_path_clear() 不依赖 Pygame,也不修改传入的占用集合。算法从箭头的下一格开始,沿箭头方向逐格扫描,直到离开棋盘:

row, col = arrow.row + row_step, arrow.col + col_step
while 0 <= row < rows and 0 <= col < cols:
    if (row, col) in occupied:
        return False
    row += row_step
    col += col_step
return True

因此该算法只检查箭头前方同一行或同一列的格子,不会误把后方箭头或其他行列的箭头当作阻挡。若箭头位于边缘且朝向棋盘外,循环不会执行,路径直接判定为畅通。设前方有 k 个格子,时间复杂度为 O(k),额外空间复杂度为 O(1)

3.4 游戏状态和动画

Game 使用 HOMEPLAYINGSUCCESSFAILED 四种页面状态。点击结果分为 FLYINGCOLLISIONIGNORED。成功点击只改变棋盘状态并创建飞行动画;失败点击保留箭头、减少一次机会并创建碰撞动画。

动画由主循环中的 update(dt) 推进,不调用 sleep()。这样窗口仍然能够持续处理鼠标、键盘和关闭事件。为了避免多条尾线叠在同一通道,当前飞行尾线结束前不会释放下一支箭头。

3.5 柔性尾线

尾线由一串约 10 px 间距的节点组成,头节点跟随箭头,其他节点通过 Verlet 积分和距离约束逐步跟随。模拟采用固定 240 Hz 子步长、较强阻尼和轨迹横向约束;绘制时使用 Catmull-Rom 曲线插值并进行超采样,得到较平滑的线条。

尾线只负责视觉表现,不参与棋盘规则判断。游戏规则始终以单格箭头和直线路径为准。

3.6 关卡可解性

前三个原创关卡均已通过自动化合法点击序列验证。简单、中等和困难模式按照 4/6/86/9/128/12/16 个箭头逐关增加;随机关卡生成器在构造时保留合法移除顺序,生成的关卡再由 AI 求解测试完整清空。无尽模式每次通关后生成新的困难关卡,并保存下一关编号。

前三个原始关卡的一个合法顺序如下,坐标从 0 开始:

关卡 合法点击顺序
L1 初见出口 (0,1) -> (1,1) -> (2,0) -> (2,4) -> (2,2) -> (4,3)
L2 逐步释放 (0,0) -> (0,2) -> (0,4) -> (2,0) -> (2,2) -> (2,4) -> (4,0) -> (4,2) -> (4,4)
L3 交错方向 (0,1) -> (0,4) -> (1,1) -> (1,4) -> (2,0) -> (2,2) -> (2,4) -> (3,5) -> (3,3) -> (5,1) -> (3,1) -> (5,4)

四、AIGC 使用过程

本项目使用 Codex 作为 Coding Agent,AIGC 参与了需求拆分、代码实现、测试设计、Bug 修复和界面迭代。以下表格按照作业要求记录 4 次真实开发过程,完整记录保存在 docs/aigc-log.md

子任务 我的要求 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
路径检测(AI-01,2026-09-13) 覆盖四方向、边界、近距离阻挡、远距离阻挡、无关行列和 blocker 移除;核心逻辑不依赖 UI。 Codex 建立不可变 ArrowDirectionis_path_clear(),并补充 pytest 测试。 首轮实现出现 AbstractSet 导入错误,测试及时暴露问题。 人工审核错误原因,要求改正导入位置并重新运行测试;34 项测试通过。
棋盘状态和可玩 MVP(AI-02,2026-09-15) 实现棋盘、鼠标点击、飞出、碰撞、失误计数、重开和关卡切换,并保留关键 Commit。 Codex 实现 BoardGame、动画计时、3 个原创关卡及 T01-T06 状态测试。 基本流程可运行,但连续点击碰撞中的箭头可能重复扣分。 人工审核后要求增加动画期间的箭头锁定和重复点击测试;最后一次反馈结束后才进入失败页,48 项测试通过。
Pygame 界面和基础动效(AI-03,2026-09-15) 完成开始页、棋盘页、通关页和失败页,采用暗色科技风,并验证真实窗口事件。 Codex 实现 main.pyui/app.py、共用 BoardLayout、按钮命中、飞出/碰撞动画和 UI smoke 脚本。 自动窗口流程可以通过三关;代码审查发现返回首页后可能残留旧按钮命中区域。 要求按当前页面过滤按钮并补充回归测试;根据截图调整 6×6 棋盘标题间距和失误数字显示。
柔性尾线和路径分离(AI-04,2026-09-15) 实现近端先牵引、远端渐进跟随的柔性线条,避免尾线重叠和无控制甩动。 Codex 实现 Verlet 节点链、距离约束、阻尼、历史轨迹约束、Catmull-Rom 平滑曲线和统一尾线路径规划。 首次曲线采样不足,首次轨迹约束会让远端过早前移。 要求增加曲线采样密度,改为横向约束并保留纵向滞后;通过路线间距测试检查尾线分离。68 项测试通过,并生成 121 帧演示 GIF。

这些过程说明 AIGC 生成的代码不能直接视为最终实现,必须经过运行、测试、截图检查和人工修改。

五、测试结果

5.1 自动化测试命令

在项目根目录执行:

.venv\Scripts\python.exe -m pytest -q
# 94 passed in 8.33s

.venv\Scripts\python.exe -m compileall -q core data ui tools tests main.py
# PASS

当前测试分布为:路径检测 10 项、游戏状态 23 项、界面交互 14 项、尾线和曲线 7 项、路径规划 1 项、进度保存 3 项,参数化用例展开后共 94 项。

5.2 作业要求测试矩阵

编号 测试内容 预期结果 实际结果 状态
T01 点击前方无阻挡的箭头 箭头飞出并消失 棋盘立即移除箭头,动画完成后清除动画记录 PASS
T02 点击前方有阻挡的箭头 箭头保留,失误减 1 箭头仍在原位,3 次机会按一次点击减为 2 次 PASS
T03 点击边缘且朝向棋盘外的箭头 正常消失且不越界 1×1 边界测试通过 PASS
T04 清除本关全部箭头 显示通关并可进入下一关 L1/L2/L3 自动点击完成,通关和下一关按钮通过 PASS
T05 失误次数耗尽 显示失败并允许重开 连续三次碰撞后进入失败页,重开恢复 3 次机会 PASS
T06 游戏中重新开始 布局和机会恢复 原始箭头、失误次数、动画和计时均恢复 PASS
T07 四种方向 UP/DOWN/LEFT/RIGHT 判断一致 参数化路径测试通过 PASS
T08 移除 blocker 后再次判断 路径变为畅通 移除阻挡后路径测试和连续点击测试通过 PASS
T09 其他行列箭头 不应误判为阻挡 无关行列测试通过 PASS
T10 重复非法点击 一次反馈只扣一次 动画期间重复点击均被忽略,反馈结束后才可再次点击 PASS
T11 最后一箭 动画结束后再显示结果 最后一支尾线结束前仍是游戏页,结束后进入通关页 PASS
T12 关卡切换 新关卡重新初始化 下一关布局、机会和动画状态正确重置 PASS
T13 提示功能 高亮合法箭头且消耗提示次数 提示测试通过,每局最多 3 次,不改变棋盘 PASS
T14 撤销和 AI 求解扩展 撤销可恢复,AI 能自动清关 状态、界面和各难度 AI 求解测试通过 PASS
T15 正式关卡可通关 每关存在合法顺序 原始三关及简单/中等/困难生成关卡均通过自动求解;需补本人实际试玩记录 PASS(自动化)/ RISK(手工)

5.3 非功能检查

检查项 结果
非阻塞动画 update(dt) 推进动画,没有 time.sleep()
Pygame 窗口退出 UI smoke 脚本注入 QUIT 事件后正常退出
30 FPS 与 144 FPS 尾线固定子步长测试结果一致
绘制纯度 重复 draw() 不推进尾线物理状态
素材来源 箭头和界面图形由 Pygame 图元绘制,没有使用商业游戏素材、代码、音效或关卡
敏感信息 当前工作区未发现密码、Cookie、API Key 或 Token

六、PSP 表格

下表根据开发阶段记录整理,实际耗时为当前开发记录的估算值;提交前可以按照个人真实投入时间修改。

任务 预估耗时(小时) 实际耗时(小时) 差异(小时)
需求分析与游戏设计 1.0 0.8 -0.2
Python 与 Pygame 学习 1.0 0.8 -0.2
游戏界面实现 2.0 2.0 0.0
路径与碰撞逻辑实现 1.5 1.2 -0.3
关卡设计与可解性验证 1.0 1.0 0.0
AIGC 辅助开发 1.5 1.8 +0.3
测试与修改 1.5 1.8 +0.3
README 与博客撰写 1.0 0.6 -0.4
合计 10.5 10.0 -0.5

耗时偏差的主要原因是:路径检测和基础状态逻辑较容易拆分测试;柔性尾线、曲线连续性、尾线分离和界面截图检查需要多轮迭代,因此测试与 AIGC 协作时间相对增加。

七、心得体会

这次作业让我认识到,一个规则看起来很简单的小游戏,仍然需要同时处理数据模型、路径算法、输入事件、状态切换、动画时序和测试证据。最基础的路径判断如果和界面代码混在一起,后续很难验证四个方向和边界情况;将 is_path_clear() 单独实现并用 pytest 覆盖后,核心规则就可以脱离窗口快速回归。

AIGC 对需求拆分、样板代码生成、测试用例设计和问题定位帮助明显,尤其适合快速搭建 ArrowBoardGame 等模块。但 AIGC 生成的代码并不一定能直接使用:本项目中曾出现类型导入错误、重复点击重复扣分、尾线远端过早移动和曲线采样不足等问题,都是通过实际运行或测试才发现并修正的。这说明开发者仍然需要理解代码、设计反例、阅读测试失败信息,并对 AI 的实现负责。

在界面实现方面,我体会到“能运行”和“看起来舒服”是两件事。动画不能阻塞事件循环,结果页不能早于最后一条尾线结束,尾线还需要避免重叠;这些问题不能只靠静态阅读代码判断,必须结合逐帧更新、截图和独立演示检查。

后续如果继续完善项目,我会优先补充本人真实试玩记录、完善更系统的关卡解法记录,并进一步增加声音反馈和可选的计时/星级展示。在此基础上再考虑打包和发布,保证附加功能不会影响基础规则的稳定性。

八、运行方式

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements-dev.txt
.\.venv\Scripts\python.exe main.py

运行柔性尾线独立演示:

.\.venv\Scripts\python.exe -m tools.rope_demo

运行测试:

.\.venv\Scripts\python.exe -m pytest -q
posted @ 2026-09-17 09:59  Ofseven  阅读(10)  评论(0)    收藏  举报