软件工程课程第二次个人作业
软件工程作业二:使用 Python 和 AIGC 完成“一箭又一箭”小游戏
| 项目内容 | 内容 |
|---|---|
| 这个作业属于哪个课程 | H202601软件工程与软件工程实践 (福州大学 - 计算机与大数据学院) |
| 这个作业要求在哪里 | 作业要求 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | 102401632 |
| GitHub 仓库 | https://github.com/5-bin/one-arrow-and-one-arrow_basic |
一、项目展示
“一箭又一箭”是一款使用 Python 与 Pygame 实现的单机益智小游戏。玩家需要从棋盘中选择一支箭头;只有当箭头指向的路径直到棋盘边缘都没有其他未消除箭头时,它才能飞出棋盘。清空当前关卡中的全部箭头即可通关。
项目当前包含 6 个难度递增且经程序验证可通关的关卡,满足作业要求的“至少 3 关”。游戏还实现了碰撞反馈、失误次数、重新开始、关卡选择、提示、自动求解、计分星级和音效开关等功能。
界面截图

动图展示

二、项目介绍
2.1 游戏规则与操作
- 鼠标左键点击棋盘中的箭头。
- 若箭头前方没有任何未消除箭头,箭头会沿其朝向飞出棋盘并消失。
- 若前方有箭头阻挡,当前箭头不会消失,界面会显示红色晃动反馈,并扣除 1 次失误机会。
- 清空全部箭头后显示通关结算,并可进入下一关;失误次数耗尽后显示失败界面。
- 点击“重新开始”可恢复当前关的初始箭头布局和失误次数。
在基础功能上,项目额外提供“提示”(高亮一支当前可飞的箭头)、DFS 自动求解演示、计分与星级评价、关卡选择和音效开关。扩展功能没有改变基本规则,主要用于帮助玩家理解和验证关卡。
2.2 开发环境
| 项目 | 版本 / 环境 |
|---|---|
| 操作系统 | macOS(Apple Silicon / arm64) |
| Python | 3.13.15 |
| Pygame | 2.6.1 |
| 打包工具 | PyInstaller 6.22.3 |
| AIGC 工具 | ChatGPT / Codex |
2.3 运行方法
克隆仓库后,在项目根目录执行:
python3 -m venv .venv
./.venv/bin/python -m pip install -r requirements.txt
./.venv/bin/python main.py
运行后在开始界面点击按钮进入游戏。若使用已激活的 Python 虚拟环境,也可以直接执行 python main.py。
2.4 本地打包与交付
仓库的 Git 文件树保存源码和 PyInstaller 配置文件 一箭又一箭.spec,不包含已构建的 dist/ 目录;但 v1.0.0 Release 提供了可直接下载的 one-arrow-and-one-arrow-macos-arm64.zip。该发布包适用于 macOS Apple Silicon(arm64),下载并解压后即可打开其中的“一箭又一箭.app”。build/ 和 dist/ 是可重新生成的构建产物,已由 .gitignore 排除,不随 Git 提交。
如需在 macOS 上构建应用,请在创建虚拟环境并安装运行依赖后执行:
./.venv/bin/python -m pip install pyinstaller==6.22.3
./.venv/bin/python -m PyInstaller --noconfirm --clean 一箭又一箭.spec
构建完成后,应用位于 dist/一箭又一箭.app。
三、实现思路
3.1 数据表示与模块划分
棋盘固定为 7 行 × 8 列。每支箭头使用字典保存 row、col、direction 和 eliminated 等状态;方向使用 UP、DOWN、LEFT、RIGHT 四种枚举值。关卡配置集中放在 config.py,因此新增或修改关卡时不需要修改界面代码。
项目将规则逻辑和图形界面分开:
| 模块 | 主要职责 |
|---|---|
main.py |
程序入口 |
game_runner.py |
Pygame 主循环、页面状态、鼠标事件和动画控制 |
game_logic.py |
路径检测、关卡复制、提示、评分和 DFS 求解 |
rendering.py |
棋盘、箭头、按钮、文字和弹窗绘制 |
audio.py |
音效加载、播放与降级处理 |
config.py |
界面常量、颜色、计分规则及 6 个关卡数据 |
游戏状态包括开始界面、关卡选择、游戏进行中、箭头飞行、通关、失败和全部通关。飞行与碰撞反馈期间会暂时限制棋盘重复点击,避免同一支箭头被重复消除或连续扣除失误次数。
3.2 路径检测算法
本游戏的核心是判断一支箭头是否被阻挡。算法从该箭头的下一格开始,按照它的方向逐格扫描,直到坐标越出棋盘:只要扫描路径中存在任意一支未消除箭头,就判定为“被阻挡”;若一路扫描到边界都没有遇到箭头,则该箭头可以飞出。
方向增量如下:
| 方向 | 行增量 | 列增量 |
|---|---|---|
| 上 | -1 | 0 |
| 下 | 1 | 0 |
| 左 | 0 | -1 |
| 右 | 0 | 1 |
关键代码如下。循环条件同时判断行、列范围,因此边缘朝外的箭头会直接结束扫描,不会发生数组越界。
check_row = arrow["row"] + row_step
check_col = arrow["col"] + col_step
while 0 <= check_row < rows and 0 <= check_col < cols:
if (check_row, check_col) in active_positions:
return True
check_row += row_step
check_col += col_step
return False
这里的 active_positions 只收集尚未消除的箭头,所以已经飞出棋盘的箭头不会继续阻挡其他箭头。
3.3 关卡设计与可通关性验证
每个预设关卡均使用 DFS 回溯求解器验证存在完整清关顺序,再进行人工试玩。第 1 至第 3 关的布局和关键解锁关系如下,坐标格式为 (行, 列):
| 关卡 | 已验证的清关顺序 / 解锁关系 |
|---|---|
| 第 1 关 | (3,5) → (3,2);边缘箭头 (6,7) 可在任意时刻飞出。 |
| 第 2 关 | 一条完整顺序为 (3,6) → (3,4) → (3,1) → (2,2) → (5,2) → (5,5) → (1,5) → (4,7)。 |
| 第 3 关 | 可交替处理四条链:右 (1,6) → (1,3) → (1,1)、左 (5,1) → (5,4) → (5,6)、上 (2,2) → (4,2) → (6,2)、下 (4,5) → (2,5) → (0,5);边缘箭头 (6,7)、(0,0) 可在任意时刻飞出。 |
DFS 搜索使用“剩余箭头位掩码”表示状态,并记录已访问状态以减少重复搜索。它只对深拷贝后的临时数据修改 eliminated 标记,不会污染玩家当前的游戏状态。
四、AIGC 使用过程
本项目开发中使用了 ChatGPT / Codex 协助分析、编码与测试。
| 子任务 | 使用的 AIGC 工具 | 我向 AI 提出的具体要求 | AI 提供了什么 | 实际效果 | 我进行的人工修改 |
|---|---|---|---|---|---|
| 项目结构与关卡数据设计 | ChatGPT / Codex | 使用 Python + Pygame 搭建游戏原型;包含开始界面、棋盘、箭头坐标与方向,以及至少 3 个关卡数据。 | 提供初始项目结构、界面绘制函数、LEVELS 关卡数据格式,以及箭头方向常量/枚举建议。 |
原型可运行,关卡数据便于后续扩展。 | 我实际运行并试玩后检查了箭头位置和关卡顺序。AI 初始布局不一定都可通关,因此我人工调整了箭头坐标和方向,并用 DFS 求解器验证每关可通关;当前关卡中的关键通关顺序以 config.py 注释保留。 |
| 四方向路径检测与交互规则 | ChatGPT / Codex | 编写独立的 is_blocked(arrow, arrows, rows, cols) 函数,支持 UP、DOWN、LEFT、RIGHT;已消除箭头不能阻挡;避免数组越界。 |
提供按方向逐格扫描的路径检测逻辑,并建议使用方向枚举和未消除箭头坐标集合进行判断。 | 可以正确判断箭头前方是否存在阻挡物,点击被阻挡箭头时不会被消除。 | 我通过边缘箭头试玩并检查右侧、下方等情况。发现边缘方向存在越界风险,因此补充并确认了循环边界判断;同时测试了已消除箭头不再参与阻挡。 |
| 飞出动画、状态管理与测试 | ChatGPT / Codex | 为可飞出的箭头添加移动后消失的动画;被阻挡时红色晃动并扣失误;实现开始、游戏、通关、失败状态,并补充测试用例。 | 提供基于 START、PLAYING、FLYING、WIN、LOSE 等状态的流程代码,以及 unittest 路径逻辑测试和人工试玩表模板。 |
游戏可显示飞出与碰撞反馈,关卡完成后可进入下一关,失误耗尽后可重开。自动测试覆盖了路径、边缘和深拷贝重置等逻辑。 | 我运行程序并手工点击验证动画、失败和重开流程;根据试玩情况检查了飞行期间重复点击、关卡切换动画残留、重新开始后的数据恢复等问题,并保留了需要继续人工验证的界面交互项。 |
AI 提高了解题、构建测试和整理文档的效率,但关卡难度、动画参数、界面布局以及最终代码正确性仍由我检查和修改。特别是,不能只接受 AI 生成的关卡:每一关都必须经过求解器验证和实际试玩。

五、测试过程与结果
5.1 自动化测试
使用以下命令在前文创建的虚拟环境中运行逻辑自动化测试:
./.venv/bin/python -m unittest discover -s tests -v
本次执行结果:共运行 19 项测试,全部通过(OK)。覆盖内容包括四方向路径扫描、已消除箭头、边缘越界、预设关卡可解性、DFS 解法合法性、重开深拷贝、提示和星级计算。
5.2 人工界面测试
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失,剩余箭头数减少 | 与预期一致 | 通过 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,红色晃动,失误次数减 1 | 与预期一致 | 通过 |
| T03 | 点击位于边缘且朝向棋盘外的箭头 | 箭头正常消失,不发生越界错误 | 与预期一致 | 通过 |
| T04 | 消除本关全部箭头 | 显示通关结果,点击后进入下一关 | 与预期一致 | 通过 |
| T05 | 耗尽失误次数 | 显示失败结果,并允许重新开始 | 与预期一致 | 通过 |
| T06 | 游戏进行中点击重新开始 | 箭头布局与失误次数恢复初始状态 | 与预期一致 | 通过 |
除上述作业要求外,还测试了飞行动画期间的连续点击、碰撞晃动期间点击其他箭头、最后一关结算和音频设备不可用等场景。仓库中的 tests/TEST_RECORD_TEMPLATE.md 提供了人工测试记录格式;本文表格记录本次实际试玩的结果。
六、PSP 表格
以下是本次开发的时间记录。
| 任务 | 预估耗时(小时) | 实际耗时(小时) | 差异(小时) |
|---|---|---|---|
| 需求分析与游戏设计 | 0.5 | 0.5 | 0.0 |
| Python 与图形库学习 | 0.5 | 0.25 | -0.25 |
| 游戏界面实现 | 1.5 | 1.0 | -0.5 |
| 路径与碰撞逻辑实现 | 1.25 | 1.0 | -0.25 |
| 关卡设计 | 0.5 | 0.5 | 0.0 |
| AIGC 辅助开发 | 0.5 | 0.25 | -0.25 |
| 测试与修改 | 1.5 | 1.25 | -0.25 |
| README 与博客撰写 | 1.75 | 1.25 | -0.5 |
| 合计 | 8.0 | 6.0 | -2.0 |
七、心得体会
这次作业让我完整经历了一个小型游戏从需求拆分、规则建模、图形交互、关卡设计到测试交付的过程。最关键的体会是:看起来简单的“点击箭头”规则,真正实现时必须清楚界定扫描方向、边界条件、已消除状态和动画期间的输入限制;这些细节决定了游戏是否稳定。
Codex 在梳理模块职责、生成路径检测思路和补充测试用例方面很有帮助,尤其能够快速指出边界条件和可测试性。但 AI 的输出只能作为初稿:关卡是否好玩、代码是否符合实际界面流程、测试是否覆盖真正的风险,仍需要我自己阅读、修改、运行和试玩验证。
后续如果继续完善,我计划加入进度保存、撤销操作和自定义关卡编辑器,让玩家可以制作并分享自己的关卡。
八、项目链接与资源说明
- 项目仓库:https://github.com/5-bin/one-arrow-and-one-arrow_basic
- README:仓库根目录的
README.md - 音效资源来源与 CC0 许可:
assets/sounds/SOURCES.md、assets/sounds/LICENSE-KENNEY-CC0.txt - 测试记录:
tests/TEST_RECORD_TEMPLATE.md - 发布版本:v1.0.0 Release 提供 macOS Apple Silicon(arm64)可直接运行的 ZIP 包;解压后打开“一箭又一箭.app”。
- 打包说明:
一箭又一箭.spec可在 macOS 本地生成dist/一箭又一箭.app;dist/为忽略的构建产物,不在 Git 文件树中。
浙公网安备 33010602011771号