2026秋软件工程个人作业(第二次):用 Python 与 AIGC 开发《箭头小游戏》

项目内容 填写内容
这个作业属于哪个课程 202601 软件工程班级博客
这个作业要求在哪里 第二次个人作业要求
这个作业的目标 使用 Python 和 AIGC 完成“一箭又一箭”小游戏
学号 102401310
GitHub 仓库 https://github.com/Ikunmma/SofwareEngineering/tree/main/work/arrow-escape

前言

最开始看到这个作业,我觉得规则很简单:点一支箭头,前面没东西就让它飞出去。真正做成游戏后才发现,路径判断只是一小步;界面状态、碰撞反馈、动画期间的重复点击、关卡是否有解,以及给别人运行的 EXE 是否兼容,都会影响作品能不能正常玩。

一、项目展示

本项目是一款使用 Python 和 Pygame 独立开发的小游戏。项目提供源码和 Windows 打包版本。Windows 用户可以从 Releases 页面下载游戏 ZIP,解压后运行;源码安装步骤见 README

项目展示如下:

演示视频主要展示随机挑战中的操作。随机挑战与固定关卡共用箭头点击、碰撞、提示和结算等流程

1. 开始界面

开始界面

2. 冒险地图

点击开始游戏后进入冒险地图。玩家可以切换基础模式和进阶模式,查看关卡解锁状态、通关标记和历史最佳星级,也可以进入随机挑战。

关卡选择界面

已解锁的关卡会显示通关标记和历史最佳星级:

image-20260917102055536

3. 游戏过程

游戏页显示生命、剩余箭头、时间和分数,并提供重开、静音、选关、提示和 AI 求解操作。

基础模式使用单格四方向箭头:

基础模式

进阶模式使用多格彩色折线箭头:

进阶模式

随机挑战:

image-20260917000302900

4. 通关与失败

清空本关所有箭头后进入通关页面,可以查看星级、用时和得分:

关卡通关

完成一个模式的最后一关后,还会显示全部通关页面:

全部通关

三条生命全部耗尽后进入失败页面,可以重新挑战或返回选关:

挑战失败

二、项目介绍

1. 游戏规则

玩家点击箭头后,程序沿箭头方向检查它与棋盘边界之间的路径:

  • 如果前方没有其他箭头,当前箭头会播放飞出动画并从棋盘消失;
  • 如果前方存在阻挡,箭头不会消失,并会变红、晃动和触发红色脉冲,同时扣除一条生命;
  • 每关初始有三条生命,清空全部箭头即可通关,生命耗尽则挑战失败;
  • 游戏进行中可以重开本关,恢复初始布局、生命、提示次数、计时和本关得分。

基础模式采用作业要求的单格箭头规则,只判断同一行或同一列。进阶模式把箭头扩展为多格折线,点击路线任意位置都能选中整条箭头,再检查头部前进方向上的射线。

2. 固定关卡

我为两个模式分别设置了五关。基础模式逐关增加行列数,采用满格箭阵;进阶模式逐关扩大折线活动区域。下表中的数量来自当前关卡数据,进阶模式统计的是“整条折线箭头”的数量,不是折线占用的格数。

关卡 基础模式(棋盘/箭头) 进阶模式(棋盘/折线)
第 1 关 5×5/25 支 16×12/24 条
第 2 关 6×6/36 支 18×14/22 条
第 3 关 7×7/49 支 20×16/34 条
第 4 关 8×8/64 支 22×18/31 条
第 5 关 9×9/81 支 24×20/42 条

箭头数量并不是衡量难度的唯一标准。尤其在进阶模式中,折线长度、转弯和头部出口的相互阻挡也会改变消除顺序。固定关卡采用确定的随机种子,重新开始会恢复同一布局;程序求解器验证每关存在完整消除顺序。

3. 主要功能与特色

功能 具体实现
双模式关卡 基础和进阶模式各有五个固定关卡,棋盘随关卡逐步扩大
关卡解锁 每种模式默认开放第一关,通关后解锁下一关,并记录勾选和最佳星级
得分与评价 每关从 0 分开始,消除加分、碰撞扣分,通关后按时间和剩余生命评定 1~3 星
下一步提示 从当前局面寻找可安全飞出的箭头;每次提示消耗一次提示机会和一条生命
随机挑战 两种模式都能生成带独立种子的随机棋盘,生成后先由求解器验证可通关
AI 自动求解 对当前完整棋盘或残局搜索消除顺序,支持自动演示、暂停和重新规划
自动保存 保存累计分数、两种模式的解锁记录、最佳星级、上次选择和静音状态
动画与音效 提供平滑飞出、残影、粒子、碰撞反馈和程序实时合成的短音效
Windows 打包 使用 PyInstaller 生成单文件 EXE,并内置图片和中文字体

4. 开发与运行环境

项目 环境
开发语言 Python 3.10 及以上
图形库 Pygame 2.6.1
测试环境 Windows 11、Python 3.12
测试框架 unittest
打包工具 PyInstaller 6

源码运行命令如下:

cd work/arrow-escape
py -m pip install -r requirements.txt
py main.py

三、实现思路

1. 项目结构

arrow-escape/
├── main.py                       # 游戏入口、界面、交互、动画、音效和存档
├── game_logic.py                 # 基础模式路径判断、消除逻辑和 DFS 求解器
├── levels.py                     # 基础模式方向定义、关卡数据和随机生成
├── advanced_logic.py             # 进阶模式折线箭头逻辑和求解器
├── advanced_levels.py            # 进阶模式关卡数据和随机生成
│
├── tests/
│   ├── __init__.py
│   ├── test_game_logic.py        # 基础模式与路径检测测试
│   ├── test_advanced_logic.py    # 进阶模式与关卡可解性测试
│   └── test_app_state.py         # 页面、动画、存档和完整流程测试
│
├── assets/
│   ├── LICENSES.md               # 素材与字体许可说明
│   ├── fonts/
│   │   ├── NotoSansSC-Regular.otf
│   │   └── OFL.txt
│   └── kenney_ui/
│       ├── Blue/                 # 蓝色按钮、箭头和图标
│       ├── Green/                # 绿色按钮、箭头和图标
│       ├── Grey/                 # 灰色按钮、箭头和图标
│       ├── Red/                  # 红色按钮、箭头和图标
│       ├── Yellow/               # 黄色按钮、箭头和图标
│       ├── Kenney Future.ttf
│       └── License.txt
│
├── README.md                     # 项目介绍和运行说明
├── BLOG.md                       # 本次课程作业博客
├── requirements.txt              # 游戏运行依赖
├── requirements-build.txt        # EXE 打包依赖
├── ArrowEscape.spec              # PyInstaller 打包配置
└── build_exe.bat                 # Windows 一键打包脚本

2. 箭头和棋盘表示

基础棋盘使用二维列表保存。每个单元格是 updownleftrightNone,其中 None 表示空白。方向被统一转换成行列增量:

DIRECTION_VECTORS = {
    "up": (-1, 0),
    "down": (1, 0),
    "left": (0, -1),
    "right": (0, 1),
}

固定关卡使用不可变数据保存,进入游戏时再复制成可修改列表。这样既能安全删除箭头,也能在重开时从原始数据恢复棋盘。

进阶模式把一支折线箭头表示成一串相邻坐标,同时保存方向和颜色。当前仍存在的折线使用编号集合记录,消除时删除对应编号即可。

3. 路径检测

路径检测是基础玩法的核心。它只回答一个问题:这支箭头与边界之间,是否还有任何箭头? 假设同一行是 → · · ↑ ·,从最左边的 向右扫描,虽然中间隔了两个空格,仍会遇到 ,所以不能飞出;阻挡者自己的朝向不影响结果。

实现时从当前箭头前方的相邻格开始,沿方向向量逐格检查:遇到非空单元格就返回“被阻挡”;直到走出棋盘仍未遇到箭头,就返回“无阻挡”。关键代码来自 game_logic.py

row_step, col_step = DIRECTION_VECTORS[direction]
check_row = row + row_step
check_col = col + col_step

while 0 <= check_row < self.rows and 0 <= check_col < self.cols:
    if self.board[check_row][check_col] is not None:
        return True
    check_row += row_step
    check_col += col_step
return False

四个方向共用这一段代码,避免分别编写四套判断。每次先检查坐标是否在棋盘内,再读取格子,避免向上或向左时误用 Python 的负索引。边缘朝外箭头的下一格已经在棋盘外,循环不会执行,直接返回无阻挡。is_blocked() 只判断,不改棋盘;remove_arrow() 仅在无阻挡时把该格设为 None。一次检测最多扫描所在的一行或一列,因此时间复杂度是 O(max(行数, 列数)),不需要额外保存整条路径。

进阶模式沿用同一思路,但从折线箭头头部开始检查,并把其他折线身体占用的全部格子组成集合。头部射线与集合相交时,整条箭头不能飞出。

4. 可通关关卡生成

如果直接随机填充方向,很容易生成相互阻挡的死局。因此基础模式采用“正向构造合法消除顺序”的方式:从满格坐标集合开始,每次只选择当前能够直接飞出剩余棋盘的坐标和方向,再将它从集合中移除。全部坐标都被处理后,记录下来的选择顺序就是一条已知解。

进阶模式先生成出口射线畅通的路线,再随机延长尾部,并限制身体不能破坏必须保留的出口。生成器会尝试多张候选棋盘并选择覆盖率较高的一张,使画面更密集。固定关卡在自动化测试中逐关求解验证;随机挑战则在进入游戏前调用求解器验证。

5. AI 自动求解

求解器采用深度优先搜索。每个状态中先找出所有当前可消除箭头,再分别尝试移除并递归搜索。无解状态会加入失败缓存,避免重复搜索。

基础模式使用不可变二维元组作为状态键,进阶模式使用剩余路线编号的不可变集合。求解器只负责返回步骤序列,界面负责逐步播放原有飞出动画。暂停求解后允许玩家手动操作;再次继续时会根据最新残局重新计算答案。

6. 页面状态、动画与存档

程序使用一个主事件循环管理开始、选关、游戏、通关、失败、随机通关和全部通关等页面。动画期间锁定会破坏状态的操作,动画结束后再真正修改棋盘。

存档使用 JSON 格式。源码版保存在项目目录,EXE 版保存在 %LOCALAPPDATA%\ArrowEscape\save_data.json。程序会检查存档字段和取值范围,内容损坏时使用默认进度启动。清除进度必须经过二次确认,避免误操作。

四、AIGC 使用过程

本项目使用 Codex 辅助分析、编码、调试和测试。下面记录的是我在开发过程中提出的问题、AI 给出的修改,以及我对结果的检查;不是把 AI 一次生成的代码直接当成最终作品。

子任务 使用工具 提出的要求 AI 提供的帮助 实际效果与人工调整
需求拆分与项目结构 Codex 把作业按天拆开,每完成一个独立功能提醒我 Commit 给出按页面、核心逻辑、关卡、测试和文档划分的开发计划 后续根据实际进度继续调整功能安排,并由我决定何时提交和推送
界面重构 Codex 不使用复杂主页,保留彩色标题、动态箭头、开始和玩法说明,并美化游戏页 将界面重构为 Pygame,绘制渐变背景、按钮、冒险地图、状态栏和结果页 初版页面过空、按钮颜色不统一;我根据运行截图多次提出修改,最终确定当前布局
密集且可解的关卡 Codex 两种模式都要像参考图一样密集和随机,同时必须能通关 设计按合法消除步骤生成棋盘的方法,并加入 DFS 可解性验证 初版进阶棋盘空白较多且出现难以判断的布局;我试玩并反馈后,提高生成密度并保留出口射线
AI 求解暂停 Codex 自动求解能够暂停,暂停后玩家还可以手动完成 增加暂停状态、操作解锁和残局重新规划 调整为先完成当前飞行动画再暂停,避免箭头停在半空;手动操作后不复用旧答案
EXE 兼容修复 Codex 解决其他电脑启动时 pygame.font.SysFont 扫描系统字体崩溃 定位字体注册表兼容问题,改为内置 Noto Sans SC,并增加回归测试 重新打包并完成启动检查,同时把字体许可证加入项目

以下选择其中三次具有代表性的协作过程,分别展示功能完善、交互优化和兼容性修复:

AIGC 代表过程一:增加关卡通关标记

我提出“已通关的关卡可以在冒险地图上做些标记”,AI 根据要求为已通关节点增加了绿色对勾、金色外圈和最佳星级,并分别保存基础模式与进阶模式的通关记录。

image-20260917142826357

AIGC 代表过程二:完善 AI 求解暂停功能

我提出“暂停 AI 求解后还可以手动求解”,AI 修改了自动求解的状态控制:暂停后允许玩家继续点击箭头、使用提示或重新开始;再次继续求解时,会根据当前棋盘重新计算步骤,避免执行已经失效的旧方案。

image-20260917134616604

AIGC 代表过程三:修复 EXE 跨电脑字体报错

其他电脑运行 EXE 时出现了 pygame.font.SysFont 相关报错,我把完整错误信息交给 AI 分析。AI 判断问题来自 Pygame 扫描 Windows 系统字体时遇到异常记录,于是将字体加载方式改为直接读取程序内置的中文字体,避免依赖不同电脑的字体环境。

image-20260917134545745

五、测试过程与结果

1. 测试方法

核心逻辑和页面状态使用 unittest 自动化测试,命令为:

py -m unittest discover -s tests -v

最后一次执行 py -m unittest discover -s tests -v,共运行 62 项自动化测试,测试结果全部通过,终端结果如下图所示:

image-20260917000632475

2. 基础测试

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 路径判定为畅通,动画结束后箭头从棋盘移除 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 箭头变红并晃动,棋盘内容不变,生命从 3 减为 2 通过
T03 点击边缘且朝向棋盘外的箭头 正常消失,不发生越界错误 边界循环安全结束,箭头成功消除且没有抛出异常 通过
T04 消除本关全部箭头 显示通关并进入下一关 最后一支箭头消除后显示通关页,点击按钮可加载下一关 通过
T05 失误次数耗尽 显示失败并允许重新开始 第三次碰撞后显示失败页,重新挑战可恢复当前关卡 通过
T06 游戏过程中重新开始 布局和失误次数恢复 棋盘、三条生命、提示次数、计时和本关分数全部恢复 通过

3. 扩展测试

编号 测试内容 实际结果
T07 四方向远距离阻挡与空白格 能识别远处箭头,点击空白格不改变状态
T08 所有固定关卡可解性 基础和进阶模式全部固定关卡均得到可执行解
T09 随机挑战 两种模式生成后均通过求解器验证,相同种子可复现
T10 AI 暂停与手动操作 暂停后可手动消除,继续时按最新残局重新规划
T11 存档异常与清除进度 损坏数据安全回退,清除操作必须二次确认
T12 EXE 中文字体 禁止调用系统字体扫描时仍能正常渲染中文

4. 问题修复与人工验收

自动化测试之外,开发时我还根据实际画面和其他电脑的运行反馈修改了两个问题:

发现的问题 修改前 调整与验证
进阶棋盘空白多、可解性不直观 随机折线虽然有颜色,但布局松散,难以确认通关顺序 增加覆盖率筛选和出口射线约束;用求解器验证每关,再查看游戏截图检查密度
别人电脑上的 EXE 启动报字体错误 pygame.font.SysFont 需要读取 Windows 系统字体列表,某些环境中因此异常退出 改为内置 Noto Sans SC,增加“禁用系统字体扫描仍可绘制中文”的回归测试,并对新 EXE 做启动检查

六、PSP 表格

实际耗时是根据开发过程回顾估算的近似值,并非逐分钟计时;界面调整、测试和文档工作有交叉。

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

七、心得体会

这次作业实际做起来比我一开始想象中复杂很多。原本以为只要实现箭头的路径判断就差不多了,后来才发现动画、碰撞反馈、关卡切换、存档、音效和程序打包等细节同样重要。AIGC 在开发过程中帮我快速完成了代码框架、界面和测试,但生成的初版并不一定符合我的要求,例如页面布局不够美观、关卡空白太多以及其他电脑运行 EXE 时出现字体错误等问题,都需要我实际运行程序、查看效果并继续提出修改。通过这次开发,我学习了如何使用二维列表表示棋盘、用方向向量统一处理四种箭头,也接触了 DFS 自动求解、随机可解关卡、JSON 存档、Pygame 动画和 PyInstaller 打包。这个过程让我明白,AI 可以提高开发效率,但不能代替自己的理解、测试和判断。虽然中间遇到了不少问题,也反复修改了很多次,但看到游戏最后拥有完整的界面、关卡和扩展功能,还是让我很有成就感。

八、项目资料与说明

  • 项目运行、下载和完整操作说明见仓库中的 README.md
  • 按钮、箭头和英文字体使用 CC0 授权的 Kenney UI Pack;
  • 中文字体使用 SIL OFL 1.1 授权的 Noto Sans SC;
  • 核心玩法参考微信小游戏《一箭又一箭》,未使用其代码、关卡、图片或音效。
posted on 2026-09-17 14:22  Ziekun  阅读(7)  评论(0)    收藏  举报