2026 秋软件工程个人作业(第二次)
“一箭又一箭”小游戏开发报告
本报告记录本项目从需求分析、AIGC 协作、编码、测试到项目整理的完整过程,可直接作为博客初稿。提交博客前,请将尖括号占位信息替换为自己的真实信息,并补充本人实际试玩时间。
一、作业信息
| 项目内容 | 信息 |
|---|---|
| 课程 | 软件工程与软件工程实践 |
| 课程链接 | H202601软件工程与软件工程实践 |
| 作业要求链接 | 2026 秋软件工程个人作业(第二次) |
| 作业目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | 102401323 |
| 姓名 | 陈勇昊 |
| GitHub 仓库 | GitHub 仓库链接 |
| 项目名称 | 一箭又一箭(Arrow Escape) |
| 开发工具 | Python、Pygame、ChatGPT/Codex |
二、项目展示
2.1 开始界面

开始界面显示游戏名称、基本玩法和开始按钮。游戏说明提醒玩家观察箭头方向,优先点击没有被挡住的箭头。
2.2 游戏界面

游戏界面包含当前关卡、剩余箭头数量、失误机会、棋盘和重新开始按钮。棋盘采用 8×8 网格,四种方向使用不同颜色区分。
2.3 通关界面

清除当前关卡全部箭头后,程序显示“本关完成”面板,玩家可以进入下一关或重玩本关。完成第三关后会显示全部通关状态。
2.4 失败界面

错误点击 3 次后显示“挑战失败”面板,玩家可以重新挑战当前关卡。
当前截图由 Pygame 的无窗口渲染检查生成。正式发布博客前,建议再补充本人实际运行窗口的截图或 GIF。
三、项目介绍
3.1 游戏规则
棋盘中放置带有上、下、左、右方向的单格箭头。玩家点击一个箭头后,程序检查它朝向棋盘边界的路径:
- 如果同一行或同一列的前方没有其他活动箭头,箭头飞出棋盘并消失。
- 如果前方存在其他箭头,当前箭头不能消失,程序播放晃动和变色反馈。
- 每次点击被阻挡的箭头会消耗 1 次失误机会,共有 3 次机会。
- 当前关卡的箭头全部消失后显示通关面板,点击“下一关”进入下一关。
- 失误机会耗尽后显示失败面板,点击“重新挑战”恢复当前关卡。
3.2 项目文件
| 文件 | 作用 |
|---|---|
game_logic.py |
定义方向、箭头数据、路径检测和关卡可解性检查 |
game.py |
Pygame 图形界面、鼠标交互、动画和游戏状态机 |
app.py |
兼容启动入口,执行 python app.py 即可启动游戏 |
test_game_logic.py |
路径检测、边界和关卡可解性自动化测试 |
requirements.txt |
Pygame 依赖 |
screenshots/ |
开始、游戏、通关和失败截图 |
README.md |
项目运行说明和简要技术说明 |
作业报告.md |
本次作业的过程报告 |
原工作区中的 index.html 是开发前已经存在的无关图像生成网页示例,不属于本作业;它已在 .gitignore 中排除,避免被误提交到游戏仓库。
四、开发环境与运行方法
4.1 开发环境
- Python 3.10 及以上
- Pygame 2.5 及以上
- Windows、macOS 或 Linux
- 本项目验证环境:Python 3.13、Pygame 2.6.1
4.2 安装依赖
python -m pip install -r requirements.txt
4.3 启动游戏
python game.py
也可以使用兼容启动器:
python app.py
4.4 运行测试
python -m unittest -v
五、实现思路
5.1 箭头和方向表示
项目使用枚举表示四个方向,每个方向保存横向位移、纵向位移和中文名称:
class Direction(Enum):
UP = (0, -1, "上")
DOWN = (0, 1, "下")
LEFT = (-1, 0, "左")
RIGHT = (1, 0, "右")
一个箭头由 ArrowSpec(row, col, direction) 表示,其中 row 和 col 是 8×8 网格坐标。Pygame 层再为每个箭头维护 active、hit、flying、removed 四种动画状态。
5.2 路径检测
路径检测的核心函数是 can_fly()。它不需要逐格访问棋盘,因此不会因为箭头位于边缘而产生数组越界。对于左右方向,只比较同一行中其他箭头的列坐标;对于上下方向,只比较同一列中其他箭头的行坐标:
if direction.dx:
same_line = origin.row == other.row
ahead = (other.col - origin.col) * direction.dx > 0
else:
same_line = origin.col == other.col
ahead = (other.row - origin.row) * direction.dy > 0
只要存在 same_line and ahead 的活动箭头,就判定为阻挡。边界不需要特殊数组访问,因此位于边缘且朝向棋盘外的箭头可以正常飞出。
5.3 关卡可解性检查
开发过程中增加了 solve_level()。它反复找出当前所有可以飞出的箭头并移除,直到棋盘为空或找不到可移除箭头。三组最终关卡数据都通过了该检查,说明每关至少存在一个完整的移除顺序。
5.4 游戏状态和动画
程序主要页面状态如下:
start 开始界面
playing 游戏进行中
level_clear 当前关卡完成
game_over 失误机会耗尽
all_clear 三关全部完成
点击可飞箭头后进入 0.34 秒飞出动画;点击被阻挡箭头后进入 0.42 秒晃动、变红动画,同时失误次数减 1。飞出状态的箭头不会再参与后续路径检测。
六、开发过程
6.1 需求分析
首先将作业要求拆分为四类功能:
- 棋盘和四种方向箭头显示。
- 点击、路径检测、飞出和碰撞反馈。
- 失误次数、重新开始、通关、失败和关卡切换。
- AIGC 记录、测试、README、截图和 Git 提交材料。
6.2 检查原始工作区
开发开始时,工作区中已有一个与本作业无关的 Flask 图像生成示例,并且原 app.py 中存在硬编码的 Hugging Face Token。处理方式如下:
- 新增独立的
game_logic.py和game.py,避免把无关网页逻辑混入游戏。 - 将
app.py改为无密钥的游戏启动器。 - 用敏感信息搜索检查项目,未发现
hf_...、API_TOKEN或Authorization残留。 - 将旧
index.html加入.gitignore,不删除用户原有文件。
6.3 逻辑实现
先实现不依赖 Pygame 的方向和路径检测,再用单元测试覆盖左右、上下和边界情况。这样即使没有打开图形窗口,也可以先确认最关键的游戏规则正确。
6.4 界面实现
使用 Pygame 绘制开始页、棋盘、状态统计、按钮和结果面板。箭头没有依赖外部素材,而是使用线段和三角形绘制,便于提交和运行。
6.5 验证和截图
安装 Pygame 后进行了以下验证:
- 无窗口绘制开始、游戏、通关和失败四种界面。
- 模拟点击一个被阻挡箭头,确认失误次数从 3 变为 2。
- 自动寻找每关可飞箭头并完成第一关,确认状态进入
level_clear。 - 点击下一关,确认关卡索引从 0 进入 1。
- 连续三次点击被阻挡箭头,确认状态进入
game_over。 - 生成
screenshots/start.png、game.png、result.png和failure.png。
正式提交前仍应由提交者在自己的桌面环境中手工试玩三关,并在博客中补充真实试玩记录。
七、AIGC 使用过程
本项目使用 ChatGPT/Codex 作为 Coding Agent,辅助需求拆解、代码编写、测试和界面检查。下面记录三次具有代表性的协作过程。
| 次数 | 子任务 | 向 AI 提出的要求 | AI 完成的工作 | 人工判断和修改 |
|---|---|---|---|---|
| 第 1 次 | 需求分析和代码结构 | 将作业要求拆成可运行的 Pygame 游戏,并把规则和界面分离 | 设计 game_logic.py、game.py、测试文件和三关数据的结构 |
检查作业评分点,保留开始、游戏、通关、失败和重新开始等基础功能,去掉不必要的复杂机关 |
| 第 2 次 | 路径检测和关卡设计 | 实现上、下、左、右四方向的同轴阻挡判断,并检查三关是否可解 | 生成 Direction、ArrowSpec、can_fly()、solve_level() 和关卡数组 |
人工核对边界条件,确保边界箭头不访问越界坐标;使用求解器检查最终三关数据 |
| 第 3 次 | 碰撞反馈和交付材料 | 增加飞出动画、碰撞晃动、失误次数、结果页面,并整理 README、截图和测试报告 | 完成 active、hit、flying、removed 状态机,生成截图和 Markdown 材料 |
人工检查状态切换、按钮位置和结果面板布局;修正飞出状态仍参与阻挡检测的问题,并调整结果面板高度 |
AI 生成的代码并没有直接作为不可解释的黑盒使用。开发者重点检查了以下内容:
can_fly()是否只检查同一行或同一列。- 方向为上、下时是否正确使用行坐标。
- 箭头飞出后是否从活动集合中移除。
- 失误机会耗尽后是否进入失败页。
- 三关是否至少存在一个通关顺序。
八、测试结果
8.1 自动化测试
执行命令:
python -m unittest -v
实际结果:4 个测试全部通过。
4 tests ... OK
测试覆盖内容包括:
- 左右方向的阻挡和可飞判断。
- 上、下、左、右四个方向在棋盘边界的可飞判断。
- 三个关卡的可解性。
- 按可飞顺序移除第一关的全部箭头。
8.2 功能测试表
| 编号 | 测试内容 | 预期结果 | 当前验证结果 | 验证方式 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 通过 | 自动流程测试 + Pygame 渲染 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,失误次数减 1,并晃动变红 | 通过 | 自动点击测试 |
| T03 | 点击位于边缘且朝向棋盘外的箭头 | 箭头正常消失,不发生越界错误 | 通过 | test_all_directions_at_boundary_can_fly |
| T04 | 消除本关全部箭头 | 显示通关并进入下一关 | 通过 | 自动求解第一关并点击下一关 |
| T05 | 失误次数耗尽 | 显示失败并允许重新开始 | 通过 | 连续三次点击被阻挡箭头 |
| T06 | 游戏进行中重新开始 | 箭头布局和失误次数恢复 | 待本人桌面复核 | 游戏内按钮和 Esc 均已实现 |
8.3 额外检查
python -m py_compile game.py game_logic.py app.py test_game_logic.py:通过。- Pygame 2.6.1 导入和无窗口渲染:通过。
- 敏感信息扫描:未发现 Token、密码或
Authorization残留。 - 三组关卡均通过
solve_level():通过。
九、PSP 记录
下面是本次开发的 PSP 初稿。预计耗时和实际耗时中的“实际”必须由提交者结合自己的开发日志、试玩时间和博客撰写时间确认后再提交,不能直接照抄示例。
| 任务 | 预计耗时(小时) | 实际耗时(小时) | 差异(小时) | 说明 |
|---|---|---|---|---|
| 需求分析与游戏设计 | 0.5 | 0.3 |
-0.2 |
拆分评分点和页面状态 |
| Python 与 Pygame 学习 | 1.0 | 0.8 |
-0.2 |
学习窗口、字体和事件循环 |
| 游戏界面实现 | 1.5 | 2.0 |
+0.5 |
开始页、棋盘和结果页 |
| 路径与碰撞逻辑实现 | 1.0 | 1.2 |
+0.2 |
四方向检测、失误机制 |
| 关卡设计 | 0.5 | 0.4 |
-0.1 |
三关数据和可解性检查 |
| AIGC 辅助开发 | 1.0 | 1.5 |
+0.5 |
需求、编码、调试和整理 |
| 测试与修改 | 1.0 | 0.7 |
-0.3 |
自动化测试、流程测试、截图 |
| README 与博客撰写 | 1.0 | 1.0 |
0.0 |
说明文档、AIGC 记录和报告 |
| 合计 | 7.5 | 7.9 |
+0.4 |
十、Git 使用情况
项目已初始化本地 Git 仓库,并创建了以下有意义的提交:
86c8c28 feat: add arrow puzzle rules and level data
eaf4bd7 feat: implement pygame board and game flow
测试文件已经加入暂存区。由于当前执行环境在后续 Git 索引写入时受到权限限制,测试、README、截图和本报告需要在本地完成最后一次提交。建议在确认内容后执行:
git add test_game_logic.py README.md 作业报告.md screenshots requirements.txt .gitignore
git commit -m "test: add coverage and course report"
然后绑定自己的 GitHub 仓库并推送:
git remote add origin <你的 GitHub 仓库地址>
git branch -M main
git push -u origin main

十一、心得体会
11.1 AIGC 带来的帮助
AIGC 适合帮助我快速把自然语言需求拆成模块。例如,作业要求同时包含路径判断、碰撞反馈、关卡流程和测试,如果直接从一个大文件开始编写,很容易把界面绘制和游戏规则混在一起。通过让 AI 先设计纯逻辑模块,我可以在没有打开图形窗口的情况下测试最重要的判断逻辑。
AI 还帮助我补充了关卡可解性检查、状态机和测试用例,使开发过程不只关注“能显示”,也能检查“能不能通关”。
11.2 需要人工判断的地方
AI 给出的代码不能直接视为正确答案。实际检查中,重点需要人工确认:
- 方向坐标的正负号是否一致。
- 箭头飞出动画过程中是否仍被其他箭头认为是阻挡物。
- 结果面板中的按钮是否超出面板边界。
- 关卡是否真的存在可通关顺序。
- README 中的测试结果是否与实际执行结果一致。
本项目中通过 unittest 和 solve_level() 检查规则,通过 Pygame 无窗口渲染检查界面,并根据检查结果修改活动箭头集合和结果面板布局。
11.3 本次收获
这次作业让我理解了一个小游戏通常由“数据表示、规则判断、界面绘制、输入事件和状态管理”几部分组成。即使规则很简单,也需要处理边界、动画时序和失败状态。AIGC 可以提高初始实现速度,但最终能否提交仍取决于开发者是否运行、测试和理解代码。
浙公网安备 33010602011771号