软件工程第二次个人作业——光阴似箭,四季如梭
软件工程第二次个人作业——“一箭又一箭”小游戏开发博客
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice |
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice/homework/16718 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | <102401302> |
| GitHub 仓库 | https://github.com/irisG1115/arrow-game |
一、项目展示
开始界面

游戏进行中(春夏秋冬四个关卡)




通关界面

失败界面

重新开始

二、项目介绍
1. 游戏规则
“一箭又一箭”是一款点击式箭头解谜游戏。棋盘为 5×5 网格,每个格子可能放置一个箭头,方向分为上、下、左、右四种。玩家点击某个箭头后,程序会检查该箭头前进方向到棋盘边界之间是否还有其它箭头:
- 若前方无阻挡,箭头飞出棋盘并消失;
- 若前方有阻挡,箭头不能消除,并消耗一次失误机会;
- 清除本关全部箭头即可通关;
- 失误次数耗尽则失败,可重新开始。
2. 界面设计
游戏包含三个主要界面:
- 开始界面:显示游戏标题、操作提示和“开始游戏”按钮。
- 游戏界面:顶部信息栏显示当前关卡、季节、剩余箭头数、剩余失误次数(以心形显示)和“重新开始”按钮;中部为棋盘;底部为随季节变化的草地和花朵装饰。
- 结果界面:通关时弹出“关卡通过!”或“全部通关!”卡片;失败时弹出“挑战失败”卡片,并提供“重试”按钮再次开始当前关卡。
3. 主要功能和特色
- 完整支持上、下、左、右四种方向的箭头;
- 路径检测正确,边界处理无越界;
- 箭头飞出时有动画和粒子尾迹;
- 箭头被阻挡时有晃动、变红、屏幕震动等反馈;
- 失误次数以心形图标直观显示;
- 四个关卡分别对应春、夏、秋、冬四个季节主题;
- 每个季节有各自的天空渐变色、粒子效果、花朵装饰和箭头配色;
- 加入了飘动云朵、太阳、季节小图标等装饰元素。
三、实现思路
1. 箭头、方向和关卡的表示
方向编码:用四个整数表示四个方向,方便比较和查找:
UP, RIGHT, DOWN, LEFT = 1, 2, 3, 4
棋盘表示:用二维列表表示,0 表示空格,其它值表示箭头方向。例如第 1 关:
"grid": [
[0, 0, RIGHT, 0, 0],
[0, 0, UP, 0, 0],
[RIGHT, RIGHT, RIGHT, RIGHT, RIGHT],
[0, 0, DOWN, 0, 0],
[0, 0, LEFT, 0, 0],
]
关卡数据:每个关卡用一个字典表示,包含棋盘、失误上限、季节主题:
{
"grid": [...],
"mistakes": 3,
"season": "spring",
}
2. 路径检测方法(重点)
这是整个游戏最核心的逻辑,实现放在 is_blocked(r, c, direction) 里:
def is_blocked(self, r, c, direction):
if direction == UP:
for rr in range(r - 1, -1, -1):
if self.grid[rr][c] != 0:
return True
elif direction == DOWN:
for rr in range(r + 1, GRID_H):
if self.grid[rr][c] != 0:
return True
elif direction == LEFT:
for cc in range(c - 1, -1, -1):
if self.grid[r][cc] != 0:
return True
elif direction == RIGHT:
for cc in range(c + 1, GRID_W):
if self.grid[r][cc] != 0:
return True
return False
思路是:
- 向上:从
r-1一直查到0,只要该列上任何一格非零,就返回True; - 向下:从
r+1一直查到GRID_H-1; - 向左:从
c-1一直查到0; - 向右:从
c+1一直查到GRID_W-1。
关键在于 range 的起止范围:
range(r-1, -1, -1)的最后一个参数是-1,意味着它可以正确取到0,又不会越界到负数;range(r+1, GRID_H)保证最多取到GRID_H-1。
这样四个方向都只检查同一行或同一列,不需要处理二维数组越界,也不需要额外判断坐标是否合法。
3. 飞出与碰撞
click_board 里点击某个箭头后:
- 若
is_blocked返回False,把grid[r][c]置为 0,并往self.animations里追加一条飞出动画; - 若返回
True,失误次数加 1,并往self.collision_effects里追加一条碰撞反馈。
动画与粒子的每帧更新放在 update 里,画面绘制放在 draw_playing 里,形成完整的“点击 → 逻辑 → 反馈 → 动画”的闭环。
4. 四季主题
每个季节定义了一套配色和粒子类型,通过 SEASONS 字典配置:
SEASONS = {
"spring": {...},
"summer": {...},
"autumn": {...},
"winter": {...},
}
切换关卡时调用 _setup_season,重新生成该季节的底部花朵和天气粒子。
四、AIGC 使用过程
整个开发过程中,我主要使用了 DeepSeek(DS) 和 Trae CN 两类 AIGC 工具。下面记录 5 次具有代表性的协作过程。
记录 1:生成基础游戏框架与核心逻辑
| 项目 | 内容 |
|---|---|
| 子任务 | 基础框架、棋盘与箭头显示、四个方向的路径检测、碰撞反馈与失误次数、关卡切换 |
| 借助何种 AIGC | DeepSeek |
| AI 实现或提供了什么 | 生成 Pygame 主循环、棋盘与箭头绘制、is_blocked 四方向路径检测、碰撞晃动与失误计数、关卡切换与重新开始等基础代码 |
| 效果如何 | 核心逻辑基本可用。这一版界面比较朴素,只有纯色背景和基础箭头,没有四季和装饰元素。运行时 SysFont("simhei") 在部分环境下会报错 |
| 人工修改 | 调整 range(r-1, -1, -1) 确保向上检测不越界;试玩后确认 3 个关卡均可通关;把 SysFont 的问题留到后面单独处理 |
记录 2:优化 UI 设计,加入四季、天气与花朵
| 项目 | 内容 |
|---|---|
| 子任务 | 四季主题、天气粒子、花朵装饰、云朵与季节图标 |
| 借助何种 AIGC | Trae CN |
| AI 实现或提供了什么 | 提供四季配色方案、SEASONS 字典结构、WeatherParticle 类、Flower 类、Cloud 类以及手绘季节图标的绘制函数,并给出 _setup_season 切换逻辑 |
| 效果如何 | 界面明显丰富,四季主题运行正常;但 emoji 字符在 Windows 下显示为方框 |
| 人工修改 | 用 Pygame 手绘图标替代 emoji;微调花朵密度与云朵速度;把 WEATHER 统一为 SEASONS,新增 self.dir_colors 按季节取箭头颜色 |
记录 3:修复字体加载报错
| 项目 | 内容 |
|---|---|
| 子任务 | 字体加载 Bug |
| 借助何种 AIGC | 豆包 |
| AI 实现或提供了什么 | 分析报错 TypeError: expected str, bytes or os.PathLike object, not int,指出这是 Pygame 在 Python 3.13 环境下 SysFont 读取注册表失败导致的 |
| 效果如何 | 建议改用字体文件路径直接加载:pygame.font.Font("C:/Windows/Fonts/msyh.ttc", 28),四套字号均正常显示 |
| 人工修改 | 将原来的 SysFont 全部替换为 Font 加载方式,并确认中文字体正常渲染 |
记录 4:修复动画 KeyError
| 项目 | 内容 |
|---|---|
| 子任务 | 飞出动画 KeyError |
| 借助何种 AIGC | DeepSeek |
| AI 实现或提供了什么 | 分析报错 KeyError: 'draw_x',指出动画字典在首次 update() 时还没有 draw_x 键,因为该键原本只在 draw_playing() 中赋值 |
| 效果如何 | 给出两种修复方案:一是创建动画字典时就写入 draw_x/draw_y,二是在 update 中用 .get() 兜底 |
| 人工修改 | 采用第一种:在 click_board 的 self.animations.append({...}) 里加上 "draw_x": cx, "draw_y": cy;同时在 update 中补 .get() 兜底,双重保证 |
记录 5:再次优化 UI 设计,修复显示栏排版重叠
| 项目 | 内容 |
|---|---|
| 子任务 | 顶部信息栏排版优化 |
| 借助何种 AIGC | DeepSeek |
| AI 实现或提供了什么 | 分析“剩余箭头”与“重新开始”按钮重叠的原因,给出重新分配 x 坐标、缩小字号、调整为“关卡 / 剩余箭头 / 重新开始”三栏布局的方案 |
| 效果如何 | 排版问题解决,顶部信息栏不再重叠,心形失误次数与季节图标也清晰可见 |
| 人工修改 | 手动调整各元素坐标与字号,把重新开始按钮放到右上角,将“失误”改为“失误次数”,并适当缩短文字宽度 |
五、测试结果
测试环境:Windows + Python 3.13.9 + Pygame 2.6.1,手工测试。
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 箭头飞出棋盘,产生粒子尾迹后消失 | 通过 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,失误次数减 1 | 箭头晃动变红,顶部心形少一个 | 通过 |
| T03 | 点击位于边缘且朝向棋盘外的箭头 | 箭头正常消失,不发生越界错误 | 箭头飞出画面,无报错 | 通过 |
| T04 | 消除本关全部箭头 | 显示通关并进入下一关 | 弹出“关卡通过!”,点击“下一关”进入第 2 关 | 通过 |
| T05 | 失误次数耗尽 | 显示失败并允许重新开始 | 弹出“挑战失败”,点击“重试”恢复本关 | 通过 |
| T06 | 游戏进行中重新开始 | 箭头布局和失误次数恢复 | 棋盘与失误次数均恢复初始状态 | 通过 |
六、PSP 表格
| 任务 | 预估耗时(小时) | 实际耗时(小时) | 差异(小时) |
|---|---|---|---|
| 需求分析与游戏设计 | 1.0 | 1.0 | 0.0 |
| Python 与图形库学习 | 2.0 | 3.0 | +1.0 |
| 游戏界面实现 | 2.0 | 3.5 | +1.5 |
| 路径与碰撞逻辑实现 | 1.5 | 2.0 | +0.5 |
| 关卡设计 | 0.5 | 1.0 | +0.5 |
| AIGC 辅助开发 | 2.0 | 3.0 | +1.0 |
| 测试与修改 | 1.0 | 2.0 | +1.0 |
| README 与博客撰写 | 1.5 | 2.5 | +1.0 |
| 合计 | 11.5 | 18.0 | +6.5 |
说明:差异主要出现在环境配置、Bug 修改和界面细节调整上,实际耗时比预期更长。
七、心得体会
这次作业让我第一次完整地使用 AIGC 工具参与了一个小型软件项目的开发,从需求分析、代码编写、调试到最终整理,整个过程都和 AI 紧密配合。
AI 带来的帮助:
- 缩短了从零开始的成本。像 Pygame 主循环、粒子系统、渐变绘制这些“模板化”的代码,AI 一次性就能给出可运行的版本,让我把精力集中在游戏逻辑本身。
- 帮助定位问题。比如字体报错和
KeyError这两个 Bug,如果自己查文档可能要花很久,AI 看了报错后很快指出了原因和修改方向。 - 提供了多种实现方案。比如路径检测,AI 给出了用
range逐格检查的写法,并提醒range(r-1, -1, -1)可以正确处理向上方向。
出现的问题:
- AI 生成的代码并不总是可以直接运行,会引用未定义的变量、遗漏某些键、或者在不同 Python 版本下报错。需要自己运行、观察报错、再去排查。
- AI 有时会使用 emoji 或
SysFont,但在 Windows + Python 3.13 的环境下会显示成方框或直接报错,说明最终还是要审查并修改AI呈现的结果。 - AI 生成的关卡不保证一定能通关,必须自己实际试玩,确认每一关都有解。
自己的收获:
- 学会了用 Pygame 组织一个完整的交互式程序:状态机、事件循环、动画更新与绘制分离。
- 理解了路径检测中边界处理的重要性,也第一次意识到“看起来简单”的数组访问其实很容易出错。
- 掌握了和 AI 协作的正确姿势:不是直接抄,而是把它当作一个反应很快的“同事”,让它出方案、给提示,然后自己验证、修改、负责。
总的来看,AIGC 让一个人也能完成以往需要小型团队才能做的项目,但前提是自己要能看懂代码、要能判断对错,并且在 AI 出错的时候能及时修正。

浙公网安备 33010602011771号