2026 秋软件工程个人作业(第二次)
| 这个作业属于哪个课程 | H202601 软件工程与软件工程实践 |
|---|---|
| 这个作业要求在哪里 | 2026 秋软件工程个人作业(第二次) |
| 这个作业的目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | 102401115 |
| GitHub 仓库 | https://github.com/Yi-shang0101/arrow_game.git |
一、项目展示
本项目是一款基于 Python 和 Pygame 开发的箭头解谜游戏。玩家需要观察箭头方向,判断箭头前方是否存在阻挡,并按照正确顺序点击箭头。游戏加入了计时评级、关卡解锁、最佳成绩保存、音乐音效、主题切换、自动求解和提示功能。实现上,我将项目分为关卡数据、游戏逻辑、进度存档和界面控制几个模块,并通过状态机管理首页、选关页、游戏页和结果页之间的跳转。
完整视频演示:https://github.com/Yi-shang0101/arrow_game/blob/main/演示视频.mkv
1、菜单界面
菜单界面有着“开始游戏”、“选择关卡”、“设置”和“退出游戏”选项

2、游戏过程
游戏成功流程如下(成功会有掌声)😊

游戏失败流程如下(失败会有罐头笑声)🤣

二、项目介绍
1、游戏玩法
游戏棋盘由若干带方向的箭头组成,箭头方向包括上、下、左、右四种。
玩家需要观察箭头前方的路径,并按照合适的顺序点击:
- 如果箭头与棋盘边界之间没有其他箭头,箭头可以飞出棋盘;
- 如果前方存在其他箭头,箭头会被阻挡并播放碰撞反馈;
- 点击被阻挡的箭头会消耗一次失误机会;
- 每关初始有 3 次失误机会;
- 清空棋盘中的全部箭头后,本关通关;
- 失误次数耗尽或超过时间限制后,本关失败。
2、关卡和评级
游戏目前包含 5 个固定关卡:
| 关卡 | 名称 | 棋盘大小 | 箭头数量 | 难度 |
|---|---|---|---|---|
| 1 | 初识方向 | 4×4 | 10 | 普通 |
| 2 | 交错路径 | 5×5 | 19 | 普通 |
| 3 | 层层解锁 | 6×6 | 30 | 普通 |
| 4 | 纵横迷阵 | 7×7 | 40 | 困难 |
| 5 | 极限交织 | 8×8 | 51 | 专家 |
普通难度的评级规则如下:
| 完成时间 | 结果 |
|---|---|
| ≤15 秒 | A |
| ≤25 秒 | B |
| ≤35 秒 | C |
| >35 秒 | 失败 |
困难和专家关卡会根据棋盘规模增加允许时间。只有前一关获得 A 或 B 评价,才能解锁下一关。已经解锁的关卡可以通过“选择关卡”页面反复挑战,并保存最佳成绩。
3、主要功能
本项目实现了以下功能:
- 开始界面和独立的关卡选择界面;
- 上、下、左、右四种方向箭头;
- 箭头路径阻挡判断;
- 箭头飞出动画和碰撞反馈;
- 失误次数和重新开始功能;
- 游戏成功和失败页面;
- A、B、C 时间评级;
- 最佳成绩保存和关卡解锁;
- 音乐音量和音效音量调节;
- 白天、护眼和夜间三种显示模式;
H键提示当前可以消除的箭头;A键和“自动求解 A”按钮;- 首页背景箭头悬停高亮和点击发射;
- 成功、失败、按钮和箭头操作音效;
4、页面组成
| 页面 | 主要功能 |
|---|---|
| 首页 | 开始游戏、选择关卡、设置和退出游戏 |
| 选择关卡页 | 查看关卡难度、解锁状态和最佳成绩 |
| 规则说明页 | 显示当前关卡规则和评级要求 |
| 游戏页 | 显示棋盘、计时、剩余箭头和失误次数 |
| 通关页面 | 显示完成时间、评级和后续操作 |
| 失败页面 | 显示失败原因并提供重新开始等操作 |
| 设置页面 | 调节音乐、音效和显示主题 |
5、项目特色
本项目在基础玩法上增加了以下功能:
- 根据关卡难度设置不同的评级时间;
- 支持反复挑战并保存最佳成绩;
- 提供当前关卡自动求解功能;
- 支持音乐、音效和主题设置;
- 首页背景箭头具有悬停和点击交互效果;
- 使用独立模块管理游戏逻辑、关卡、存档和界面;
- 使用自动化测试验证核心功能。
三、程序结构与实现思路
1、关卡数据表示
关卡数据保存在 levels.py 中,使用二维列表表示棋盘,U/D/L/R 分别表示上、下、左、右,None 表示空格。
LEVELS = [
{
"name": "初识方向",
"difficulty": "normal",
"description": "先找朝向边界的箭头,逐步打开通路。",
"board": [
[None, "D", None, "R"],
["L", None, "U", None],
["L", "L", "U", "U"],
[None, None, "D", "U"],
],
},
]
项目一共设计了 5 个固定关卡,关卡规模从 4×4 逐渐增加到 8×8。
2、方向和时间评级
logic.py 中使用方向增量统一处理四种箭头
DIRECTIONS = {
"U": (-1, 0),
"D": (1, 0),
"L": (0, -1),
"R": (0, 1),
}
不同难度拥有不同的评级时间:
DIFFICULTY_RULES = {
"normal": {
"label": "普通",
"A": 15.0,
"B": 25.0,
"C": 35.0,
"time_limit": 35.0,
},
"hard": {
"label": "困难",
"A": 25.0,
"B": 40.0,
"C": 55.0,
"time_limit": 55.0,
},
"expert": {
"label": "专家",
"A": 35.0,
"B": 55.0,
"C": 75.0,
"time_limit": 75.0,
},
}
评级函数如下:
def time_grade(seconds, rules=None):
rules = rules or DIFFICULTY_RULES["normal"]
if seconds <= rules["A"]:
return "A"
if seconds <= rules["B"]:
return "B"
if seconds <= rules["C"]:
return "C"
return None
3、箭头路径检测
核心函数 can_exit() 位于 logic.py 中。
它从当前箭头的下一格开始,沿箭头方向逐格扫描。如果扫描到其他箭头,就说明当前箭头被阻挡。
def can_exit(board, row, col):
"""沿射线检查到边界;阻挡者的方向不影响判断。"""
if not (0 <= row < len(board) and
0 <= col < len(board[0])):
return False
direction = board[row][col]
if direction is None:
return False
dr, dc = DIRECTIONS[direction]
r, c = row + dr, col + dc
while 0 <= r < len(board) and 0 <= c < len(board[0]):
if board[r][c] is not None:
return False
r += dr
c += dc
return True
4、点击箭头和碰撞处理
Game.click() 负责处理玩家点击:
def click(self, row, col, automatic=False):
if (
self.state != "PLAYING"
or self.animation
or (self.auto_solving and not automatic)
):
return "ignored"
if not (
0 <= row < len(self.board)
and 0 <= col < len(self.board[0])
):
return "ignored"
direction = self.board[row][col]
if direction is None:
return "ignored"
self.hint = None
kind = "exit" if can_exit(
self.board, row, col
) else "bump"
if kind == "bump":
self.mistakes -= 1
self.animation = Animation(
row, col, direction, kind
)
return kind
如果箭头可以飞出,就创建 exit 动画;如果被阻挡,就创建 bump 动画并扣除一次失误机会。
箭头不会在点击瞬间删除,而是在动画完成后删除:
if animation.kind == "exit":
self.board[animation.row][animation.col] = None
if self.remaining == 0:
self.grade = time_grade(
self.elapsed,
self.level_rules
)
self.progress.record(
self.level_index,
self.elapsed,
self.time_limit
)
self.state = (
"ALL_CLEAR"
if self.level_index == len(self.levels) - 1
else "LEVEL_CLEAR"
)
这样可以防止动画播放过程中重复删除棋盘数据。
5、自动求解算法
自动求解函数也位于 logic.py:
def solve(board):
"""返回一种解法;死锁返回 None。"""
validate_board(board)
work = [row[:] for row in board]
result = []
while any(
cell is not None
for row in work
for cell in row
):
moves = available_moves(work)
if not moves:
return None
for r, c in moves:
work[r][c] = None
result.append((r, c))
return result
算法会复制一份临时棋盘,在临时棋盘上不断删除当前可以飞出的箭头,并记录删除顺序。
游戏实际运行时,自动求解仍然按照普通飞出动画执行:
def auto_solve(self):
if (
self.state != "PLAYING"
or self.animation
or self.auto_solving
):
return False
solution = solve(self.board)
if not solution:
return False
self.auto_queue = list(solution)
self.auto_solving = True
self.auto_step_started = False
self.hint = None
self.hint_time = 0.0
return True
自动求解期间会锁定玩家的手动棋盘点击,但仍然可以重新开始或返回首页。
四、AIGC 使用过程
4.1 使用工具
本项目主要使用 ChatGPT/Codex 辅助完成需求分析、代码编写、调试、测试和文档整理。
AIGC 主要参与了以下工作:
- 分析游戏规则和功能需求;
- 设计项目文件结构;
- 编写路径检测和游戏状态逻辑;
- 生成和验证关卡数据;
- 编写界面、动画和音频代码;
- 编写自动化测试;
- 根据运行结果定位和修复问题;
- 整理 README、测试报告和博客内容。
4.2 代表性协作记录
4.2 AIGC 协作过程总览
| 阶段 | 使用的 AIGC 工具 | 我的需求 | AI 完成内容 | 实际效果 | 人工修改或验证 |
|---|---|---|---|---|---|
| 需求拆解与基础架构 | ChatGPT/Codex | 先分析“一箭又一箭”的玩法,再设计 Python 游戏结构 | 设计 main.py、logic.py、levels.py 和 progress.py 的模块划分 |
项目形成了逻辑、界面、关卡和存档分离的结构 | 我确认采用 Pygame、二维棋盘和状态机,并根据课程要求调整功能范围 |
| 路径判断 | ChatGPT/Codex | 实现上、下、左、右四个方向的箭头检测 | 生成 DIRECTIONS、can_exit() 和阻挡判断逻辑 |
四个方向均可正确判断,箭头能够区分畅通和阻挡 | 我补充边界、隔空阻挡、身后箭头、空格点击和越界测试,并要求修正坐标处理问题 |
| 基础关卡 | ChatGPT/Codex | 设计至少 3 个可以正常通关的关卡 | 生成基础关卡棋盘和 solve() 求解器 |
初始三关均能够通过求解器找到合法通关顺序 | 我根据作业要求检查关卡数量,并使用求解器和实际运行验证关卡可解 |
| 计时和评级 | ChatGPT/Codex | 加入 A≤15 秒、B≤25 秒、C≤35 秒和超时失败 | 增加计时器、time_grade() 评级函数和结果页用时显示 |
普通关卡能够按时间显示 A、B、C 或失败 | 我要求计时从“开始挑战”后才开始,并补充低帧率、评级边界和最后一支箭头动画测试 |
| 首页布局调整 | ChatGPT/Codex | 根据截图重新调整标题、按钮和背景元素 | 修改按钮尺寸、居中布局、悬停高亮和背景箭头颜色 | 首页布局更加集中,文字和按钮没有明显重叠 | 我提供界面截图并提出具体调整要求,通过重新渲染截图检查位置、颜色和高亮效果 |
| 音乐和音效 | ChatGPT/Codex | 加入主菜单音乐、游戏音乐、成功、失败和按钮音效 | 编写 AudioManager,统一加载、播放和停止音频 |
页面切换时能够切换音乐,操作时播放对应音效 | 我整理并提供音频资源,验证音频设备不可用时能够自动静音,并检查结果音效能及时停止 |
| 困难和专家关卡 | ChatGPT/Codex | 增加 7×7 困难关和 8×8 专家关,并根据难度调整评级时间 | 生成第 4、5 关,并配置困难和专家评级阈值 | 五个关卡均能通过求解器验证,旧版存档可以继续使用 | 我检查关卡规模、难度和评分要求,并要求增加旧存档迁移测试 |
| 自动求解 | ChatGPT/Codex | 增加“自动求解 A”按钮和 A 键快捷键 | 调用当前棋盘的 solve(),按照正常动画自动完成 |
自动求解会逐支播放飞出动画,并正常进行计时和结算 | 我要求自动求解时锁定手动棋盘点击,但保留重开和返回首页功能,并通过测试验证 |
代表性协作过程
1、首页ui调整

2、音乐和音效的调节

3、困难和专家关卡的设计

五、测试结果
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 动画结束后箭头从棋盘中删除 | 通过 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,失误次数减 1 | 箭头返回原位,失误次数减少 1 | 通过 |
| T03 | 点击位于边缘且朝向棋盘外的箭头 | 箭头正常消失,不发生越界 | 上、下、左、右边缘均能正常处理 | 通过 |
| T04 | 消除本关全部箭头 | 显示通关结果并进入后续流程 | 显示评级和通关页面 | 通过 |
| T05 | 失误次数耗尽 | 显示失败并允许重新开始 | 第三次碰撞后进入失败页面 | 通过 |
| T06 | 游戏进行中重新开始 | 棋盘和失误次数恢复初始状态 | 棋盘、失误次数、提示和动画均被重置 | 通过 |
额外测试:
| 测试项目 | 测试内容 | 实际结果 | 是否通过 |
|---|---|---|---|
| 计时评级 | 测试 15、25、35 秒边界 | A、B、C 评级符合设定 | 通过 |
| 超时失败 | 完成时间超过当前难度限时 | 进入失败页面 | 通过 |
| 关卡解锁 | 前一关获得 B 或 A | 下一关解锁 | 通过 |
| C评价限制 | 前一关只获得 C | 下一关保持锁定 | 通过 |
| 最佳成绩 | 重复挑战并取得更快成绩 | 只保存更快成绩 | 通过 |
| 存档读取 | 关闭游戏后重新启动 | 成绩和解锁状态保留 | 通过 |
| 自动求解 | 点击“自动求解 A” | 按正常动画完成当前关卡 | 通过 |
| 设置页面 | 拖动音乐和音效滑块 | 音量立即生效 | 通过 |
| 主题切换 | 切换白天、护眼和夜间模式 | 页面颜色立即更新 | 通过 |
| 音频切换 | 成功、失败和返回操作 | 对应音效正常播放或停止 | 通过 |
| 背景箭头 | 悬停和点击首页背景箭头 | 箭头高亮并播放装饰动画 | 通过 |
六、PSP 表格
| 任务 | 预计耗时(小时) | 实际耗时(小时) | 差异(小时) |
|---|---|---|---|
| 需求分析与游戏设计 | 0.8 | 1.2 | +0.4 |
| Python 与 Pygame 学习 | 1.5 | 1.0 | -0.5 |
| 游戏界面实现 | 1.0 | 1.5 | +0.5 |
| 路径与碰撞逻辑实现 | 1.5 | 1.5 | 0 |
| 关卡设计与求解验证 | 1.5 | 1.5 | 0 |
| AIGC 辅助开发 | 2.0 | 2.5 | +0.5 |
| 测试与问题修复 | 1.5 | 2.2 | +0.7 |
| README 与博客撰写 | 1.2 | 1.5 | +0.3 |
| 合计 | 11.0 | 12.9 | +1.9 |
七、心得体会
八、心得体会
通过本次“一箭又一箭”小游戏的开发,我认识到一个看似简单的点击游戏,实际上包含了需求分析、数据结构设计、界面设计、事件处理、状态管理、动画、音频、存档和测试等多个软件工程问题。
最开始我认为只需要绘制一个棋盘和几支箭头即可完成游戏,但实际开发后发现,路径判断才是游戏的核心。程序不仅要判断箭头前方是否有阻挡,还要处理边界箭头、隔着空格的阻挡、碰撞反馈、失误次数和动画结束后的棋盘更新。通过将游戏逻辑放在 logic.py 中,将界面和事件处理放在 main.py 中,程序结构更加清晰,也方便单独测试核心规则。
AIGC 在本次开发中提高了我的开发效率。ChatGPT/Codex 可以帮助我快速拆解需求、生成代码框架、设计测试用例和定位错误。例如,在路径检测、计时评级、关卡解锁、音频管理和自动求解等功能中,AI 提供了较多实现思路。但是,AI 生成的代码不能直接作为最终结果,仍然需要通过运行程序、查看截图和执行测试来判断是否正确。
开发过程中也遇到了一些问题。例如,模拟鼠标事件时出现过坐标类型问题;动画期间重复点击可能造成棋盘状态错误;中文字体缺少部分字符时会出现显示异常;成功或失败音效在切换页面时不能立即停止。通过增加边界测试、锁定动画期间输入、增加字体回退机制和使用独立音频通道,这些问题得到了修复。
本项目最终实现了五个不同难度的关卡、A/B/C 时间评级、关卡解锁、最佳成绩保存、音乐音效、主题切换、提示、自动求解和首页背景箭头互动等功能,并完成了 48 项自动化测试。通过这次开发,我进一步理解了二维数组、方向增量、状态机、模块化设计和自动化测试的作用。
不过,我也认识到自己对 Pygame 底层机制、音频系统和游戏架构的理解还不够深入。后续如果继续完善项目,我希望增加随机生成可解关卡、撤销操作、更加详细的成绩统计,并尝试将游戏打包成 Windows 可执行文件。
总体来说,AIGC 可以作为编程学习和项目开发的辅助工具,但不能代替开发者进行思考和验证。只有理解代码的基本原理,并通过测试和实际运行检查结果,才能真正完成一个可靠的软件项目。

浙公网安备 33010602011771号