软件工程第二次个人作业——使用 AIGC 完成“一箭又一箭”小游戏

项目内容 内容
这个作业属于哪个课程 H202601 软件工程与软件工程实践
这个作业要求在哪里 2026 秋软件工程个人作业(第二次)
这个作业的目标 使用 Python 和 AIGC 完成“一箭又一箭”小游戏
学号 102401513
GitHub 仓库 mclennonwyms-art/ruangong

一、项目展示

本项目使用 Python 标准库 Tkinter 开发,不依赖第三方图形库。棋盘、箭头和界面装饰均由 Canvas 实时绘制,没有使用商业游戏的代码、美术素材或关卡。

游戏演示

image

1. 开始界面

start

开始界面展示游戏名称、玩法说明和快捷键,并提供五个关卡入口。玩家可以从第一关开始,也可以直接选择其他关卡进行测试。

2. 通关界面

cleared

截图中第一关的 7 支箭头已经全部清除,剩余 3 次机会,得分 805 分,共操作 7 次。通关后会显示本关结果,并提供“下一关”和“返回主页”按钮。

3. 失败界面

failed

点击被阻挡的箭头会扣除一次机会。机会耗尽后显示挑战失败界面,保留当前棋盘作为失败现场,并允许重新挑战或返回主页。

二、项目介绍

“一箭又一箭”是一款点击式箭头解谜游戏。棋盘中的每支箭头只占一个网格,方向分为上、下、左、右四种。玩家点击箭头后,程序检查它前进方向到棋盘边界之间是否存在其他箭头:

  • 路径没有阻挡时,箭头沿自身方向飞出棋盘并消失;
  • 路径存在箭头时,本次点击失败,箭头晃动并标出阻挡位置,同时扣除一次机会;
  • 清空全部箭头后本关通关,机会耗尽后本关失败;
  • 玩家可以随时重新开始,使布局、得分和失误机会恢复初始状态。

项目完成了作业要求的全部基础功能,并增加了以下功能:

  • 五个难度逐步增加的关卡;
  • 关卡选择;
  • 得分与计时;
  • H 键提示当前可安全移除的箭头;
  • U 键撤销上一次成功操作;
  • 自动关卡求解与可解性验证;
  • 11 项自动化逻辑测试。

三、实现思路

1. 项目结构

为了降低界面和业务逻辑之间的耦合,我将程序分为三层:

one-arrow-after-another/
├─ main.py                    # 程序入口
├─ arrow_game/
│  ├─ levels.py              # 关卡数据
│  ├─ model.py               # 路径判断与状态管理
│  └─ ui.py                  # Tkinter 界面和动画
├─ tests/test_game_logic.py  # 自动化测试
├─ tools/verify_levels.py    # 关卡可解性验证
├─ docs/screenshots/         # 运行截图
└─ README.md                 # 项目说明

model.py 不依赖 Tkinter,因此核心规则可以脱离图形界面运行自动测试。ui.py 只负责绘制、接收点击和播放动画。

2. 箭头与方向表示

每支箭头由“行、列、方向”三个字段表示。例如 (2, 0, "R") 表示第 3 行第 1 列的一支向右箭头。四个方向统一转换为坐标步长:

UP    = ("U", -1, 0, "上")
DOWN  = ("D",  1, 0, "下")
LEFT  = ("L",  0, -1, "左")
RIGHT = ("R",  0, 1, "右")

当前箭头使用字典保存,键为 (row, column)。这样既可以快速定位玩家点击的箭头,也可以用接近常数时间判断某个格子是否被占用。

3. 路径检测

路径检测是本项目的核心。程序先取得箭头方向对应的行列步长,然后从相邻格开始沿直线检查:

row_step, column_step = arrow.direction.delta
row = arrow.row + row_step
column = arrow.column + column_step

while 0 <= row < self.level.rows and 0 <= column < self.level.columns:
    blocker = self.arrows.get((row, column))
    if blocker is not None:
        return blocker
    row += row_step
    column += column_step
return None

如果循环过程中发现箭头,就返回离当前箭头最近的阻挡物;如果坐标先离开棋盘范围,则说明路径畅通。上下左右只需要使用不同步长,不需要分别复制四段代码,因此边界规则保持一致。

4. 游戏状态管理

游戏模型使用四种状态:

  • PLAYING:正在进行;
  • LEVEL_CLEARED:当前关卡已清空;
  • FAILED:失误次数耗尽;
  • ALL_CLEARED:全部关卡完成。

成功点击会删除箭头并增加得分;失败点击保留箭头、扣除机会并降低得分;重新开始会从原始关卡数据重新构造字典。界面只根据模型返回的结果决定播放何种动画,避免界面和规则各维护一份状态。

5. 飞出与碰撞反馈

箭头成功时,界面绘制一个临时副本,使用 Tkinter 的 after() 每隔约 15 ms 沿箭头方向移动一次,直到离开棋盘。发生碰撞时,箭头按照正负偏移序列左右晃动,最近阻挡物出现红色边框,同时在操作区显示原因。动画没有使用 sleep(),因此不会冻结窗口。

6. 关卡可解性验证

仅凭肉眼设计关卡容易出现方向闭环,所以项目实现了 solve_level()。求解器不断选择当前路径畅通的箭头并移除;如果棋盘未清空但找不到可移除箭头,则判定关卡死锁。

删除箭头只会减少阻挡,不会产生新的阻挡,因此在本作业的基础规则下,持续移除任意当前可行箭头就可以验证关卡是否可解。五个正式关卡都能输出完整清除序列。

四、AIGC 使用过程

本项目使用 ChatGPT / Codex 辅助需求分析、编码、测试与文档整理。AI 生成结果并未直接作为最终答案,而是经过运行、测试和修改后进入项目。

子任务 AIGC 工具 AI 实现或提供的内容 实际效果 人工检查与修改
需求拆分与结构设计 ChatGPT / Codex 将程序拆分为关卡、模型、界面和测试模块 核心逻辑可以脱离 GUI 测试,后续修改比较清晰 阅读各模块职责,并在 README 中补充结构和运行说明
路径检测 ChatGPT / Codex 使用四个方向步长生成统一的直线路径检测代码 四方向边缘、最近阻挡物和空白格测试全部通过 按 3×3、1×5 示例逐格检查,确认边界条件与最近阻挡物正确
关卡设计 ChatGPT / Codex 生成五个关卡,并生成自动求解器验证 初版第 4、5 关被求解器判定为无解 重新调整部分箭头方向,再运行求解器,五关全部通过
动画与反馈 ChatGPT / Codex 生成飞出动画、碰撞晃动、红框和提示文字 基本效果可用,界面未发生阻塞 检查后发现晃动末尾存在轻微位置偏移,将偏移序列末尾补为 0,使箭头回到原格
自动化测试 ChatGPT / Codex 根据作业 T01~T06 编写测试,并补充边界测试 共 11 项测试全部通过 使用真实图形界面再次测试开始、通关、失败和重开流程

具有代表性的协作过程

第一次:让 AI 设计代码结构

将完整作业要求交给 Codex,希望它完成图形界面、路径判断、关卡和测试。AI 给出的第一版建议把关卡数据、纯游戏规则和 Tkinter 界面分离。我阅读代码后保留了该结构。其直接好处是测试路径判断时不需要反复打开窗口。

第二次:检查路径检测和边界

我要求 AI 避免为四个方向复制四段代码,并覆盖边缘箭头。AI 使用方向步长统一处理。随后通过 T03 测试四个朝向棋盘外的边缘箭头,均能正常消失,没有发生数组越界;又增加最近阻挡物测试,确认碰撞提示指向第一个阻挡物。

第三次:发现 AI 生成的关卡并不可靠

AI 初次生成了五个看起来合理的关卡,但运行求解器后发现第 4、5 关无法清空。这说明“方向齐全”和“箭头很多”并不代表关卡有解。之后重新计算部分箭头方向,再次执行 verify_levels.py,五关都输出了完整通关顺序。这个问题让我认识到 AI 生成的数据也必须经过程序验证。

第四次:修改碰撞动画细节

我让AI 使用多个正负水平偏移实现箭头晃动。检查代码时发现原偏移序列最后停在 -2,可能导致箭头逐渐偏离格子。因此我在序列末尾增加 0,保证动画结束时箭头回到原始位置。

五、测试结果

自动测试命令如下:

python -m unittest discover -s tests -v
编号 测试内容 预期结果 实际结果 结论
T01 点击前方无阻挡的箭头 箭头飞出并消失 返回 SUCCESS,剩余数减 1 通过
T02 点击前方有阻挡的箭头 箭头保留,机会减 1 返回最近阻挡物,机会减 1 通过
T03 点击边缘且朝外的箭头 正常消失,不发生越界 四个方向的边缘用例均正常 通过
T04 消除本关全部箭头 显示通关并进入下一关 状态变为通关,下一关正常加载 通过
T05 失误次数耗尽 显示失败并允许重开 状态变为失败,重开按钮正常 通过
T06 游戏中重新开始 布局和机会恢复 箭头、机会、得分和操作次数均恢复 通过

补充测试还包括:最近阻挡物、空白格点击、撤销、方向编码转换、五关可解性,以及每关是否包含四种方向。

Ran 11 tests in 0.002s
OK

手工测试中,开始界面和关卡选择能够正常显示;第一关在 7 次操作后正常通关;第二关连续点击被阻挡箭头后进入失败页面;通关后的下一关、失败后的重新挑战和返回主页按钮均能使用。

六、PSP 表格

以下时间根据开发过程进行回顾性估算,以 0.1 小时为单位记录。

任务 预估耗时(小时) 实际耗时(小时) 差异(实际-预估)
需求分析与游戏设计 1.0 0.8 -0.2
Python 与 Tkinter 学习 1.5 1.0 -0.5
游戏界面实现 3.0 3.2 +0.2
路径与碰撞逻辑实现 2.0 1.6 -0.4
关卡设计 1.5 1.8 +0.3
AIGC 辅助开发 1.5 1.2 -0.3
测试与修改 2.0 1.5 -0.5
README 与博客撰写 1.5 1.4 -0.1
合计 14.0 12.5 -1.5

实际总耗时比预估少 1.5 小时,主要原因是 AIGC 快速完成了界面框架和测试代码;关卡设计和界面实现略有超时,是因为初版关卡存在死锁,并且动画细节需要实际运行后调整。

七、Git 与项目管理

项目上传至 GitHub 。主要提交包括:

feat: 添加第一次个人作业项目
feat: 完成箭头游戏核心逻辑和图形界面
test: 增加游戏逻辑和关卡可解性测试
docs: 完善第二次作业文档和AIGC记录

仓库级 .gitignore 排除了 .venv.idea、缓存、.env 和构建目录,避免上传本机环境及敏感信息。

八、心得体会

这次作业让我完整经历了从需求分析、模块划分、代码实现到测试和文档整理的过程。游戏规则本身不复杂,但真正实现时需要处理坐标变化、边界判断、状态切换、动画期间的重复点击等细节。

AIGC 最大的帮助是快速搭建项目结构、生成界面代码和补充测试,使我能够把更多精力放在规则检查和运行效果上。不过,初版第 4、5 关不可通关也说明 AI 生成的结果不能直接相信。即使代码语法正确,数据和逻辑仍可能存在问题,必须通过自动测试、求解器和实际试玩验证。

我认为本项目中最有价值的设计是把游戏规则与图形界面分离。路径检测可以直接使用自动测试验证,出现问题时也更容易定位。通过本次实践,我进一步熟悉了 Python、Tkinter、Git、GitHub 和单元测试,也更加理解了 AIGC 在软件开发中的定位:它可以提高开发效率,但最终的判断、测试和责任仍然属于开发者本人。

九、运行方法

git clone https://github.com/mclennonwyms-art/ruangong.git
cd ruangong/one-arrow-after-another
python main.py

项目地址:[https://github.com/mclennonwyms-art/ruangong/tree/main/one-arrow-after-another](https://github.com/mclennonwyms-art/ruangong/tree/main/one-arrow-after-another

posted @ 2026-09-21 09:38  了一声  阅读(9)  评论(0)    收藏  举报