软件工程课程第二次个人作业

《一箭又一箭》:Python + AIGC 小游戏的诞生过程

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

一 项目展示

《一箭又一箭·箭头乐园》是一款使用 Python 和 Pygame 开发的点击式箭头解谜游戏。玩家需要观察箭头的方向和相互阻挡关系,按照正确顺序点击箭头,使所有箭头依次飞出棋盘。

程序既可以通过 Python 源代码启动,也已经使用 PyInstaller 打包为 Windows 可执行程序。

1 开始界面

开始界面采用蓝天、草地、云朵、木牌和拟人箭头角色组成的可爱风格,包含“开始游戏”“选择关卡”“游戏设置”和“游戏说明”四个入口。

2 游戏过程

游戏界面顶部显示当前关卡、剩余箭头、剩余失误次数和关卡用时。玩家可以重新开始、获取提示或返回主页。箭头成功飞出时会加速离开棋盘,点击受阻箭头时会晃动、变红并播放碰撞音效。

3 通关界面

清空棋盘后,程序会显示本关用时、失误次数和星级评价,并提供“重新挑战”和“下一关”按钮。星星使用 Pygame 图形绘制并依次弹出。

4 失败界面

剩余失误次数变为 0 后进入失败界面,玩家可以重新开始当前关卡。

5 动画演示

下面展示游戏中的实际操作与动画效果:

完整游戏过程录屏可通过网盘查看:

文件名: 一箭又一箭游戏完整版录制.mp4
链接: https://pan.baidu.com/s/1GdMgC80lqCEh73rXvTAVmw?pwd=rj9p
提取码: rj9p

二 项目介绍

1 游戏规则

棋盘中的每个箭头只占一个网格,方向分为上、下、左、右四种。玩家点击箭头后,程序检查该箭头与棋盘边界之间的路径:

  • 如果前方没有其他箭头,箭头飞出棋盘并被删除;
  • 如果前方存在其他箭头,箭头不能消失,并产生碰撞反馈;
  • 点击受阻箭头会消耗一次失误机会;
  • 清除当前关卡的所有箭头即可通关;
  • 失误次数耗尽后本关失败,可以重新开始。

2 主要功能

在完成作业基础要求后,我继续增加了多项扩展功能:

  • 完整的开始、游戏、关卡选择、设置、说明、通关和失败界面;
  • 10 个难度逐步增加的原创关卡;
  • 每关最多使用 3 次的提示功能;
  • 实时计时和通关星级评价;
  • 箭头加速飞出、速度线、碰撞晃动、提示呼吸光圈和星级回弹动画;
  • 按钮、飞出、碰撞和通关四种原创音效;
  • 动画、提示文字和音效开关;
  • 游戏过程中返回主页;
  • 18 项自动化测试;
  • 使用 PyInstaller 打包为 Windows EXE 程序。

3 关卡难度设计

关卡整体按照箭头数量和阻挡关系逐步增加复杂度。随着关卡推进,箭头数量由 6 个增加至 26 个,后续关卡包含更多需要按照一定先后顺序消除的情况。

关卡 名称 箭头数量 设计定位
第 1 关 初箭启程 6 教学关
第 2 关 左右逢源 8 熟悉规则
第 3 关 四向交错 10 简单
第 4 关 箭路迷踪 12 开始需要观察
第 5 关 环环相扣 14 普通
第 6 关 先后有序 16 普通
第 7 关 进退两难 18 较难
第 8 关 箭阵重重 20 较难
第 9 关 步步为营 22 困难
第 10 关 万箭归零 26 最终挑战

所有关卡在加入正式关卡列表前均通过 solve() 自动求解器验证,确保至少存在一种完整消除顺序;同时我从第一关到第十关进行了人工试玩,进一步检查自动求解无法覆盖的界面交互、动画和实际游玩体验。

三 开发环境

项目 环境
操作系统 Windows 10
Python 3.11.8
图形界面库 Pygame 2.6.1
开发工具 PyCharm 2025.2.6.2
版本控制 Git
代码托管 GitHub
自动化测试 Python unittest
程序打包 PyInstaller 6.22.3

四 实现思路

1 程序结构

项目将核心规则、关卡数据、图形界面和测试代码分开管理:

  • core.py:箭头数据结构、路径检测和自动求解;
  • levels.py:10 个关卡的数据;
  • game.py:界面绘制、鼠标事件、动画、音效和状态切换;
  • generate_sounds.py:生成四个原创 WAV 音效;
  • tests/:核心规则和完整游戏流程测试。

这样做的好处是核心算法不依赖窗口,可以单独测试;界面修改时也不会影响关卡数据。

2 箭头和方向表示

每个箭头使用一个不可变的数据类表示:

@dataclass(frozen=True)
class Arrow:
    row: int
    col: int
    direction: str

其中 rowcol 表示网格坐标,direction 使用 UDLR 表示四个方向。方向对应的行列增量为:

DIRECTIONS = {
    "U": (-1, 0),
    "D": (1, 0),
    "L": (0, -1),
    "R": (0, 1),
}

关卡使用字典保存名称、棋盘大小、初始失误次数和箭头列表,因此增加或修改关卡不需要改动游戏主循环。

3 路径检测

路径检测是本项目最核心的部分。程序遍历棋盘中的其他箭头,通过行列差判断它是否位于当前箭头的前进射线上:

row_delta = other.row - arrow.row
col_delta = other.col - arrow.col

if row_delta * dc == col_delta * dr:
    distance = row_delta * dr + col_delta * dc
    if distance > 0:
        candidates.append((distance, other))

这里使用了两个条件:

  1. row_delta * dc == col_delta * dr:相当于判断二维向量叉积为 0,说明两个箭头位于同一直线上;
  2. distance > 0:相当于判断点积为正,说明另一个箭头位于当前箭头的前方,而不是后方。

最后从候选箭头中选择距离最近的一个作为阻挡物。如果没有候选箭头,blocker_for() 返回 None,当前箭头就可以飞出。

这种写法将四个方向统一为一套算法,减少了分别编写上下左右四段判断代码时可能出现的边界错误。

4 游戏状态管理

游戏使用 state 管理不同页面和流程,主要状态包括:

start         开始界面
level_select  关卡选择
settings      游戏设置
help          游戏说明
playing       游戏进行中
level_clear   当前关卡通过
failed        当前关卡失败
finished      全部关卡通过

鼠标事件根据当前状态进行处理。例如,游戏进行中点击棋盘会查找箭头,而结果界面的点击会重新挑战或加载下一关。状态分离可以避免同一个点击事件在多个页面中同时生效。

5 提示功能和自动求解

solve() 使用深度优先搜索和回溯寻找一种完整消除顺序:

for arrow in state:
    if can_escape(arrow, state):
        rest = tuple(item for item in state if item != arrow)
        answer = dfs(rest)
        if answer is not None:
            return [arrow, *answer]

每次递归都会从当前状态中删除一个可以飞出的箭头,因此待处理的箭头数量不断减少。当箭头集合为空时,说明已经找到一种完整的消除顺序;如果当前选择最终无法清空棋盘,则回溯并尝试其他可以飞出的箭头。提示按钮调用 solve(self.arrows),然后高亮返回结果中的第一个箭头。提示不会直接替玩家操作,并且每关最多使用 3 次。次数用完后会显示提醒,让提示功能起到辅助作用而不是代替思考。

6 计时和星级评价

计时只在 playing 状态下累加,通关或失败后立即冻结。重新开始关卡时计时归零。

星级规则只根据失误次数计算:

0 次失误      三星
1 次失误      两星
2 次及以上    一星

计时作为额外展示信息,不参与星级计算。

7 动画和原创音效

动画没有使用外部美术素材。箭头、角色、云朵、木牌、棋盘和按钮均由 Pygame 图形 API 绘制。箭头成功飞出时使用加速曲线改变位置,碰撞时使用正弦函数产生逐渐减弱的晃动,提示箭头则使用周期函数产生呼吸缩放效果。

为了避免使用来源不明确的网络音效,我编写 generate_sounds.py,使用正弦波、扫频、确定性噪声和音量包络生成:

  • click.wav:按钮点击;
  • whoosh.wav:箭头飞出;
  • hit.wav:碰撞失败;
  • win.wav:关卡通过。

这些 WAV 文件没有复制或改编商业游戏音效。程序还处理了电脑没有可用音频设备的情况,音效加载失败时会静默降级,不影响游戏继续运行。

五 AIGC 使用过程

本项目主要使用 ChatGPT / Codex 辅助开发。AI 参与了代码生成、调试、界面设计和测试,但每一次输出都经过了实际运行,人工检查和需求分析。下面记录本项目中具有代表性的真实协作过程。

子任务 使用的 AIGC 我提出的要求 AI 提供的内容 实际效果 我的检查和修改
项目框架与路径检测 ChatGPT / Codex 使用 Python 和 Pygame 实现基础点箭头玩法,并正确判断四个方向的阻挡 将规则逻辑、关卡数据和界面逻辑拆分到 core.pylevels.pygame.py,使用方向向量以及箭头之间的相对坐标判断前方阻挡,并将核心规则与界面逻辑分离。 完成基础游戏循环和四方向路径判断 我重点检查了边缘箭头和相邻阻挡两类边界情况,验证边缘朝外箭头能够正确判定为可飞出,同时检查最近阻挡物的判断是否正确;之后补充单元测试,对“无遮挡可飞出”“有阻挡不可飞出”和四个方向分别进行验证。
提示功能 Codex 利用已有 solve() 增加提示按钮并高亮下一步 调用求解结果确定推荐箭头,并通过高亮动画提示玩家 基础提示功能可正常给出下一步 我检查提示结果是否对应当前棋盘仍然存在的箭头,并测试连续使用提示的状态变化;考虑到无限调用会破坏玩法,因此增加 MAX_HINTS = 3 的次数约束,同时验证重新开始关卡后提示次数能够恢复
动画和原创音效 Codex 不使用商业游戏素材,通过程序增强动画并自行生成 WAV 音效 增加箭头飞出动画、碰撞反馈、速度线和结算动画,并通过 Python 生成 click.wavwhoosh.wavhit.wavwin.wav 动画和大部分音效正常,首次测试时碰撞反馈偏弱 我检查 pygame.mixer 初始化状态和不同事件对应的音效触发路径,并分别测试点击、飞出、碰撞和通关事件;发现 hit.wav 实际播放但听感不明显后,调整音量及生成参数并重新测试,同时保留音频设备初始化失败时的异常处理,避免无音频设备导致游戏直接崩溃
EXE 打包 ChatGPT / Codex 使用 PyInstaller 将项目打包成可直接运行的 Windows 程序,并保证音效资源可访问 使用 --add-data "assets/sounds;assets/sounds" 将资源加入打包结果,并生成 PyInstaller .spec 配置 成功生成 Windows 可执行程序 我没有以“成功生成 EXE”作为完成标准,而是进入 dist 目录直接启动打包后的程序,检查开始界面、关卡加载、箭头交互和音效播放;确认运行时不依赖 PyCharm 启动环境后,再将 build/ 作为临时构建目录加入 .gitignore,只保留最终 dist/ 成品和 .spec 配置

通过这些协作过程,我发现 AIGC 在代码框架设计、功能扩展和问题定位方面能够明显提高开发效率,但“代码能够生成”并不等于“功能已经完成”。例如路径检测需要进一步验证边界坐标,提示功能需要考虑次数和状态重置,计时功能需要检查不同游戏状态下的生命周期,音效不仅要确认文件能够加载,还需要实际验证触发时机和播放效果。

因此在本项目中,我没有直接把 AIGC 生成的代码作为最终结果,而是采用“提出需求 → 获取实现 → 阅读和运行代码 → 发现问题 → 修改需求或代码 → 自动化测试 → 手工回归测试”的方式反复迭代。AIGC 主要承担方案生成和辅助编码,我则负责需求取舍、运行验证、异常定位和最终结果判断。

六 测试结果

1 自动化测试

项目使用 Python 内置 unittest,运行命令为:

python -m unittest discover -s tests -v

测试运行结果如下:

自动化测试结果
最终共执行 **18 项自动化测试,全部通过(OK)**。

老师要求的 T01 到 T06 已全部编写为完整游戏流程测试:

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 动画结束后箭头从棋盘数据中删除 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 箭头保留并进入碰撞动画,失误次数减少 1 通过
T03 点击边缘且朝向棋盘外的箭头 正常消失,不发生越界错误 箭头正常删除,程序未出现异常 通过
T04 消除本关全部箭头 显示通关界面,点击“下一关”后进入下一关 进入通关状态,点击“下一关”后正确加载下一关 通过
T05 失误次数耗尽 显示失败并允许重新开始 进入失败状态,点击按钮后恢复本关 通过
T06 游戏进行中重新开始 布局和失误次数恢复 布局、失误次数、提示次数和计时全部恢复 通过

其他自动化测试还包括:

  • 检查最近阻挡箭头;
  • 检查 10 个关卡的名称和箭头数量梯度;
  • 检查每一关是否包含四种方向;
  • 检查箭头坐标不重复且位于棋盘范围内;
  • 使用 solve() 验证 10 个关卡均存在完整解法;
  • 检查计时格式;
  • 检查星级评价规则;
  • 检查四个 WAV 文件存在且格式正确。

2 手工测试

我在 Windows 10、Python 3.11.8 和 Pygame 2.6.1 环境中,从第一关到第十关进行了完整试玩,测试了正确飞出、碰撞失败、提示次数耗尽、重新开始、返回主页、关卡切换、计时、星级、动画和音效。

之后我使用 PyInstaller 6.22.3 将程序打包为文件夹形式的 Windows 可执行程序,并直接运行 dist/一箭又一箭/一箭又一箭.exe。最终 EXE 可以正常打开,游戏界面、鼠标操作、关卡、字体和音效均正常。

七、Git 和项目提交

开发过程中,我按照游戏功能的实现阶段进行了多次 Commit,而不是在项目全部完成后一次性提交。开发过程中,我尽量以一个相对独立、可验证的功能作为一次提交单位。每完成一个阶段,先进行运行或测试,确认当前版本可用后再 Commit。

本项目最终共进行了 9 次 Commit,提交记录如下:

chore: 导入小游戏初始可运行版本
feat: 优化游戏界面与视觉效果
feat: 增加游戏提示功能
feat: 扩展至10个游戏关卡
feat: 增加游戏计时与星级评价
feat: 增加游戏动画与原创音效
test: 补充并完善游戏自动化测试
build: 完成可执行程序打包并完善项目文档
chore: 移除构建临时文件并完善忽略规则

实际 Git 提交记录如下:

实际提交记录

整个提交过程基本对应了项目从“基础可运行版本”到“功能扩展”,再到“测试、打包和项目整理”的开发过程。通过 Git 的版本管理,可以比较清楚地看到每个阶段所完成的主要工作,也方便在出现问题时查看不同版本之间的代码变化。

GitHub 仓库地址:https://github.com/cccch412/one_arrow_game_complete

八 PSP 表格

由于开发过程中功能经过多轮迭代,实际耗时根据开发记录和 Git 提交进行回顾统计,可能存在少量误差。

任务 预估耗时(小时) 实际耗时(小时) 差异(小时)
需求分析与游戏设计 2.0 2.5 +0.5
Python 与图形库学习 3.0 4.0 +1.0
游戏界面实现 2.0 1.5 -0.5
路径与碰撞逻辑实现 1.0 0.5 -0.5
关卡设计 3.0 2.0 -1.0
AIGC 辅助开发 3.0 5.0 +2.0
测试与修改 4.0 4.0 +0.0
README 与博客撰写 1.0 1.5 +0.5
合计 19.0 21.0 +2.0

九 心得体会

这次作业让我第一次比较完整地经历了一个小游戏从需求分析、代码实现、界面迭代、测试到打包发布的过程。项目的核心规则并不复杂,但真正实现时仍然涉及二维坐标、方向向量、事件循环、游戏状态、动画计时、声音加载和自动化测试等多个问题。

也让我更直观地理解了模块化设计的意义。由于核心规则被独立放在 core.py 中,并不依赖 Pygame 窗口,因此路径检测和自动求解可以直接进行单元测试;而修改 UI 时,也不需要同时修改核心规则。相比把所有代码都写在 game.py 中,这种拆分方式更方便后续测试、定位问题和扩展功能。

我对路径检测的理解更加具体。最开始可以分别编写向上、向下、向左和向右的判断,但这种写法容易重复,也容易在边界条件上出错。最终通过方向向量、叉积和点积将四个方向统一处理,代码更短,也更容易测试和解释。

AIGC 明显提高了开发效率。它能够快速给出代码框架、算法思路和调试方向,还可以帮助生成测试用例和文档。但是 AI 输出并不等于最终结果。例如早期字体加载在 Windows 上报错,提示功能一开始没有次数限制,生成的部分关卡需要验证,碰撞音效第一次也不够明显。如果只复制代码而不实际运行,这些问题很容易被忽略。

我认为这次开发中最重要的工作不是“让 AI 写出多少代码”,而是不断提出更具体的要求、运行程序、发现问题并继续修改。我通过多次试玩调整了界面布局、云朵位置、角色表情、字体、提示次数和声音效果;又使用自动求解器和 18 项自动化测试检查关卡与流程。这个过程让我更熟悉了如何判断 AI 代码是否正确,也体会到测试和人工试玩各自不可替代的作用。

最后,我使用 PyInstaller 将项目打包为可以直接运行的 Windows 程序。看到自己设计的界面、规则、关卡、动画和音效最终组合成一个完整应用,是这次作业中最有成就感的部分。

十 素材来源与版权说明

  • 本项目只参考“一箭又一箭”类游戏的基础玩法,没有复制原商业游戏的代码、素材、音效或关卡。
  • 箭头、角色、云朵、木牌、按钮、棋盘和动画均由 Pygame 图形 API 绘制。
  • click.wavwhoosh.wavhit.wavwin.wavgenerate_sounds.py 使用 Python 自行合成,没有使用网络音效。
  • 项目中未包含密码、Cookie、API Key、Token 等敏感信息。
  • 本项目仅用于课程学习和软件开发实践,不用于商业用途。
posted @ 2026-09-19 19:05  陈瑀涵  阅读(7)  评论(0)    收藏  举报