软件工程第二次作业
一箭又一箭 — 开发博客
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice |
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice/homework/16718 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成"一箭又一箭"小游戏 |
| 学号 | 102402146 |
| GitHub 仓库 | https://github.com/508236985/arrow |
一、项目展示
1.1 开始界面
启动游戏后进入开始菜单,四个方向的装饰箭头围绕标题旋转,中心有脉动蓝色光晕,下方为"开始游戏"按钮和玩法提示。

1.2 游戏过程
棋盘为 7×7 网格,蓝色箭头带发光效果和呼吸动画。点击前方无阻挡的箭头时,箭头沿方向飞出棋盘并留下蓝色粒子尾迹;点击被阻挡的箭头时,箭头变红并随机抖动,同时出现橙色扩散闪烁环,失误次数减 1。

1.3 通关界面
清空全部箭头后弹出通关面板,包含"进入下一关"和"返回主菜单"两个按钮。

1.4 失败界面
失误次数耗尽后弹出失败面板,提供"重新开始"按钮。

二、项目介绍
2.1 游戏规则
- 棋盘中有上、下、左、右四种方向的箭头
- 点击箭头后,沿其方向检查到棋盘边界之间是否有其他箭头
- 无阻挡 → 箭头飞出棋盘并消除
- 有阻挡 → 箭头不能消除,消耗 1 次失误机会
- 清空全部箭头 → 通关,进入下一关
- 失误耗尽 → 失败,可重新开始
2.2 界面设计
- 配色:深蓝紫渐变背景 + 霓虹青蓝箭头 + 红色碰撞提示
- 顶栏:标题、关卡名称、心形失误计数(参数方程绘制)
- 棋盘:7×7 网格,棋盘格交替配色
- 底栏:重开本关 / 下一关 两个圆角按钮
- 弹窗:半透明遮罩 + 圆角面板 + 顶部色带
2.3 主要功能
- 鼠标点击箭头进行消除尝试
- 四方向路径检测(同行/同列扫描到边界)
- 碰撞反馈(变色 + 抖动 + 闪烁环 + 粒子爆发)
- 飞行动画(加速飞出 + 粒子尾迹)
- 失误次数显示与耗尽判定
- 3 个关卡的加载与切换
- 开始菜单 / 通关 / 失败 / 全部通关 四种状态界面
2.4 特色
- 使用
pygame.draw.polygon绘制箭头形状,不依赖字体符号 - 完整粒子系统(爆发 + 尾迹 + 重力下落 + 透明度衰减)
- 箭头呼吸动画与出场缩放动画
- 开始界面四向装饰箭头绕标题旋转
三、实现思路
3.1 数据表示
方向使用字符串表示,映射为坐标增量:
DIRS = {
"up": (0, -1),
"down": (0, 1),
"left": (-1, 0),
"right": (1, 0),
}
关卡用二维列表表示,每个元素为方向字符串或 None(空格):
grid = [
[None, None, None, None, "left", None, None],
[None, None, "up", None, "left", None, None],
...
]
箭头用 Arrow 类封装,包含行列坐标、方向、飞行状态、碰撞计时器等。
3.2 路径检测方法
核心函数 is_blocked(arrow, grid):
def is_blocked(arrow, grid):
dx, dy = DIRS[arrow.direction]
x = arrow.col + dx
y = arrow.row + dy
while 0 <= x < COLS and 0 <= y < ROWS:
if grid[y][x] is not None:
return True
x += dx
y += dy
return False
思路:从箭头所在格子出发,沿方向逐格扫描,直到出界。若途中遇到任何非空格(其他箭头),则返回 True(被阻挡);若顺利到达边界仍无阻挡,返回 False。
由于使用 while 0 <= x < COLS and 0 <= y < ROWS 作为循环条件,位于边缘且朝向棋盘外的箭头会立即退出循环,不会发生数组越界。
3.3 点击处理
def arrow_clicked(arrow, grid, mistakes, particles):
if is_blocked(arrow, grid):
arrow.shake()
particles.burst(...)
mistakes -= 1
return mistakes, False
arrow.flying = True
grid[arrow.row][arrow.col] = None
return mistakes, True
3.4 关卡求解验证
三个关卡均通过回溯法验证存在通关顺序:对每个可消除的箭头尝试移除,若最终 grid 为空则关卡有解。
四、AIGC 使用过程
4.1 核心逻辑与初版界面
| 项目 | 内容 |
|---|---|
| 子任务 | 实现游戏核心逻辑(路径检测、点击消除、失误计数、关卡切换)+ 初版图形界面 |
| 借助何种 AIGC 技术 | Trae IDE 内置 AI 编程助手(基于大语言模型) |
| AI 实现或提供了什么 | 生成了完整的单文件游戏代码,包括:Arrow 类定义、四个方向的路径检测函数、3 个关卡数组、主事件循环、初版网格和箭头绘制 |
| 效果如何 | 核心逻辑正确,游戏可运行。但箭头使用 Unicode 字符 ↑↓←→,在默认字体下显示为方块;中文文字同样无法显示 |
| 人工修改 | 后续专门针对字体问题进行了修复(见 4.2) |
4.2 中文字体与箭头显示修复
| 项目 | 内容 |
|---|---|
| 子任务 | 修复箭头和中文文字显示为方块的问题 |
| 借助何种 AIGC 技术 | Trae IDE 内置 AI 编程助手 |
| AI 实现或提供了什么 | 编写了 find_chinese_font() 函数,遍历系统字体目录候选列表(msyh.ttc、simhei.ttf 等),逐个尝试加载并渲染测试文本;将 FONT_BIG/MED/SM 改为使用找到的中文字体 |
| 效果如何 | 中文文字和箭头符号能正常显示。但箭头仍为字体字符,样式单一且不同系统下字形可能不一致 |
| 人工修改 | 后续在 UI 重写中改用多边形绘制箭头(见 4.3),彻底脱离字体依赖 |
4.3 UI 全面重写与粒子系统
| 项目 | 内容 |
|---|---|
| 子任务 | 重写视觉界面,提升美观度并加入动画特效 |
| 借助何种 AIGC 技术 | Trae IDE 内置 AI 编程助手 |
| AI 实现或提供了什么 | 1) 用 pygame.draw.polygon 绘制四方向箭头多边形(主体 + 尾部三角 + 外层发光晕);2) 实现 ParticleSystem 粒子系统(爆发、尾迹、重力、透明度衰减);3) 深蓝紫渐变背景 + 棋盘格配色;4) 箭头呼吸动画、出场缩放、碰撞扩散环;5) 参数方程绘制心形失误计数 |
| 效果如何 | 视觉效果大幅提升,箭头立体感强,粒子特效流畅。但部分按钮和弹窗文字中使用了 emoji(🔄💔🏆 等),在中文字体下显示为方框 |
| 人工修改 | 手动将所有 emoji 替换为纯文字(如"重开本关"、"失败"等),确保全中文环境下正常显示 |
4.4 开始菜单与通关流程完善
| 项目 | 内容 |
|---|---|
| 子任务 | 添加开始界面,通关后提供返回主菜单选项 |
| 借助何种 AIGC 技术 | Trae IDE 内置 AI 编程助手 |
| AI 实现或提供了什么 | 1) 新增 draw_start_menu() 函数,包含四向装饰箭头绕标题旋转、中心脉动光晕、开始按钮;2) 主循环新增 start_menu 状态分支;3) 改造 draw_overlay() 支持双按钮,通关界面添加"返回主菜单"按钮 |
| 效果如何 | 启动后先显示开始菜单,通关后可选择进入下一关或返回主菜单,流程完整 |
| 人工修改 | 无重大修改,测试确认各状态切换正常 |
五、测试结果
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 箭头沿方向加速飞出,留下蓝色粒子尾迹,飞出屏幕后从列表移除 | 通过 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,失误次数减 1 | 箭头变红并随机抖动,出现橙色扩散环,心形失误计数减 1 | 通过 |
| T03 | 点击位于边缘且朝向棋盘外的箭头 | 箭头正常消失,不发生越界错误 | 箭头立即飞出,控制台无报错 | 通过 |
| T04 | 消除本关全部箭头 | 显示通关并进入下一关 | 弹出通关面板,点击"进入下一关"加载下一关布局 | 通过 |
| T05 | 失误次数耗尽 | 显示失败并允许重新开始 | 弹出失败面板,点击"重新开始"恢复关卡初始状态 | 通过 |
| T06 | 游戏进行中重新开始 | 箭头布局和失误次数恢复 | 点击"重开本关"按钮后,箭头布局和失误次数(5)恢复初始值 | 通过 |
六、PSP 表格
| 任务 | 预估耗时(小时) | 实际耗时(小时) | 差异(小时) |
|---|---|---|---|
| 需求分析与游戏设计 | 1.0 | 0.5 | -0.5 |
| Python 与图形库学习 | 1.0 | 0.5 | -0.5 |
| 游戏界面实现 | 3.0 | 4.0 | +1.0 |
| 路径与碰撞逻辑实现 | 2.0 | 1.0 | -1.0 |
| 关卡设计 | 1.5 | 1.0 | -0.5 |
| AIGC 辅助开发 | 2.0 | 3.0 | +1.0 |
| 测试与修改 | 1.5 | 2.0 | +0.5 |
| README 与博客撰写 | 1.0 | 1.5 | +0.5 |
| 合计 | 13.0 | 13.5 | +0.5 |
七、心得体会
7.1 AI 带来的帮助
-
快速搭建框架:AI 一次性生成了可运行的完整游戏骨架(Arrow 类、路径检测、主循环、关卡数据),省去了大量基础代码编写时间,让我能专注于玩法和视觉优化。
-
算法实现准确:路径检测的核心逻辑由 AI 生成,边界条件处理得当(
while 0 <= x < COLS),没有出现数组越界问题。 -
视觉效果丰富:粒子系统、渐变背景、多边形箭头、参数方程心形等效果都由 AI 生成,极大提升了游戏观感,而这些如果纯手写需要花费大量时间调试数学参数。
7.2 出现的问题
-
字体兼容性:AI 最初使用
pygame.font.Font(None, size)默认字体,导致中文和箭头符号显示为方块。需要手动添加字体查找逻辑,并最终改用多边形绘制箭头来彻底解决。 -
Emoji 显示问题:AI 在按钮和弹窗文字中加入了 emoji 字符(🔄💔🏆),但中文字体不支持这些字符,显示为方框。需要手动替换为纯中文文字。
-
UI 迭代次数多:初版 UI 比较简陋,经过多次重写才达到满意效果,实际耗时比预估多。
7.3 收获
- 学会了使用
pygame.draw.polygon绘制任意形状,比依赖字体字符更可靠 - 掌握了粒子系统的基本实现(位置、速度、重力、生命周期、透明度衰减)
- 理解了用参数方程绘制心形等图形的方法
- 体会到 AI 辅助开发中"生成-测试-修改"的迭代流程,AI 提供初稿,人工负责验证和调整细节
- 认识到字体和字符编码是跨平台图形应用中容易踩坑的地方,应优先使用图形绘制而非文字符号

浙公网安备 33010602011771号