2026软件工程第二次个人作业
| 这个作业属于哪个课程 | H202601软件工程与软件工程实践 |
|---|---|
| 这个作业要求在哪里 | 2026秋软件工程第二次个人作业 |
| 这个作业的目标 | 利用 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | 102401422 |
| GitHub仓库 | arrow-arrow |
一、项目展示
本项目基于 Python + Pygame 开发,完整实现了开始界面、游戏界面、通关/失败界面。以下为各界面运行截图。
1.开始界面:

2.游玩界面截图:
进入关卡后会显示:
- 当前关卡
- 剩余可失误机会
- 剩余箭头数量
- 重新开始按钮
- 游戏棋盘
![游玩时]()
3.成功界面截图:

4.失败界面截图:

二、项目介绍
1.项目结构:
ArrowArrow/
│
├── main.py
│ └── 程序入口
│
├── constants.py
│ └── 全局常量与配置
│
├── arrow.py
│ └── Arrow 数据类
│
├── board.py
│ └── Board 棋盘类
│ ├── is_blocked() # 路径检测
│ ├── remove() # 移除箭头
│ └── clone() # 深拷贝棋盘
│
├── levels.py
│ └── 关卡数据与解析
│ ├── RAW_LEVELS # 5 关字符画
│ └── parse_level() # 字符画 → Board
│
├── solver.py
│ └── 贪心求解器 solve(),验证关卡可解性
│
├── session.py
│ └── 游戏状态机 GameSession
│
├── animations.py
│ └── 动画模块
│
├── ui.py
│ └── 渲染工具(字体、按钮、坐标换算、箭头多边形)
│
├── game.py
│ └── 主游戏类
│ ├── run() # 主循环
│ ├── handle_event() # 事件处理
│ ├── update() # 状态更新
│ └── draw() # 界面绘制
│
│
└──README.md
└── 项目说明
2.游戏规则:
棋盘上放置若干带方向的箭头,方向分为上、下、左、右四种。玩家点击任意箭头后,程序会沿箭头前进方向扫描至棋盘边界,判定规则如下:
- 若前进路径无任何箭头阻挡,该箭头飞出棋盘并消失;
- 若前进路径存在其他箭头,箭头弹回并抖动,同时扣除一次失误次数;
- 清空当前关卡所有箭头即可通关,自动进入下一关;
- 失误次数耗尽时本关挑战失败,支持重新开始本关游戏。
3.界面设计:
-
开始界面
展示游戏标题、简易游戏规则说明,搭配「开始游戏」功能按钮,界面简洁直观。 -
游戏主界面
顶部信息栏:实时显示当前关卡、剩余箭头数量、剩余失误次数;
中部区域:游戏棋盘主体,为核心游玩区域;
底部区域:设置「重新开始」按钮,支持随时重置本局游戏。 -
通关/失败界面
采用半透明遮罩+弹窗卡片样式弹出,清晰展示对局结果,搭配对应操作按钮,支持进入下一关或重新挑战。 -
交互视觉反馈
箭头默认以蓝色三角形展示,鼠标悬停格子自动高亮;
箭头碰撞受阻时,自动变红并抖动,给出明确报错反馈;
箭头成功消除时,播放缩放+位移动画,交互反馈流畅清晰。
4.主要功能:
- 完整支持上、下、左、右四个方向箭头的识别与精准路径检测;
- 精准判定箭头通行状态,无阻挡正常消除、有阻挡触发碰撞反馈;
- 完善的失误次数统计、扣减与失败重试机制;
- 支持关卡自动切换、手动重新开始,游戏过程可随时重置;
- 内置贪心求解器,自动验证关卡可解性,杜绝无解死局;
- 配备快捷键操作:
Esc退出游戏。
5.项目特色:
- 模块化架构:采用多文件拆分开发,代码解耦,结构清晰,便于后续维护与功能扩展;
- 轻量化关卡设计:通过字符画定义关卡数据,直观易懂、修改便捷,搭配独立脚本完成关卡合法性校验;
- AIGC 辅助开发:全程借助 AIGC 工具辅助编码、调试、设计,所有内容均经过人工校验、修改优化,保障程序稳定可用;
- 关卡设计:游戏内置 5 个递进难度关卡,箭头数量逐关递增(5、8、12、16、20),难度循序渐进,游玩体验层层升级;
- 完善质量校验:配备自动化测试、关卡可解性校验,全方位保障游戏运行稳定、关卡合理。
三、实现思路
本项目采用面向对象模块化的思想进行开发,将数据模型、棋盘逻辑、状态机、动画、UI渲染相互解耦,各个模块职责单一。下面分别介绍箭头、方向、关卡的数据表示,以及核心的路径检测算法。
1. 箭头的表示
箭头使用 Arrow 类(arrow.py)进行封装:
class Arrow:
__slots__ = ('row', 'col', 'direction')
def __init__(self, row, col, direction):
self.row = row
self.col = col
self.direction = direction
2. 方向的表示
在constants.py中定义全局字典DIRS,把方向映射为行增量、列增量、旋转角度:
DIRS = {
'up': (-1, 0, 270),
'down': (1, 0, 90),
'left': (0, -1, 180),
'right': (0, 1, 0),
}
同时定义字符映射字典CHAR_TO_DIR,用于关卡字符画解析:
CHAR_TO_DIR = {'^': 'up', 'v': 'down', '<': 'left', '>': 'right'}
3. 关卡的表示
关卡原始数据存放在levels.py的RAW_LEVELS,使用字符画描述棋盘布局。parse_level()解析字符画生成Arrow对象,交给Board棋盘类;Board内部使用二维网格grid存储棋盘,格子存有箭头则存放Arrow实例,空格子为None。Board提供统计剩余箭头、棋盘深拷贝clone()等方法,load_all_levels()批量解析全部关卡,深拷贝用于求解器模拟推演,保护原始关卡数据。
RAW_LEVELS = [
# 第1关,5个箭头
[
">..v",
".v..",
"....",
"<..>",
],
...
]
4. 路径检测方法
文件位置:board.py
- 功能:接收一个箭头对象,沿着箭头前进方向,从箭头相邻的第一格开始向棋盘边界逐格扫描:
- 如果扫描途中遇到任意其他箭头,返回
True,代表存在阻挡,箭头不能飞出; - 如果一直走到棋盘边界都没有遇到其他箭头,返回
False,代表无阻挡,可以飞出棋盘。
源码:
def is_blocked(self, arrow):
"""沿箭头方向逐格扫描,遇到其他箭头即被阻挡"""
dr, dc, _ = DIRS[arrow.direction]
r = arrow.row + dr
c = arrow.col + dc
while 0 <= r < self.rows and 0 <= c < self.cols:
if self.grid[r][c] is not None:
return True
r += dr
c += dc
return False
执行流程:
- 根据箭头
direction从DIRS取出方向增量dr、dc; - 起点坐标:
r = arrow.row + dr,c = arrow.col + dc,从箭头前方第一格开始扫描,不包含箭头自身格子; while循环:坐标在棋盘合法范围内就持续向前走一格;- 循环内部判断:如果当前格子
grid[r][c]不为None,说明该格子存在箭头 → 直接返回True(被阻挡); - 如果循环退出(坐标越界,走到棋盘边界外面),全程没有碰到其他箭头,返回
False(无阻挡)。
四、AIGC 使用过程
本次开发全程使用 DeepSeek 作为主要AIGC辅助工具,完成框架搭建、核心算法编写、动画实现,后续人工阅读代码、调试Bug、修正逻辑,下表记录3次代表性协作过程:
| 子任务 | 借助何种 AIGC 技术 | AI 实现或提供了什么 | 效果如何 | 人工修改 |
|---|---|---|---|---|
| 路径检测 | DeepSeek | 根据我的要求,生成四个方向的路径检测代码,使用 while 循环沿箭头方向逐格扫描,遇到箭头返回 True,否则返回 False | 基本逻辑正确,但向上检测时边界条件写成了 r > 0,导致第一行漏判,箭头无法正常飞出 |
将边界条件改为 r >= 0,并补充了四个方向的测试用例,验证向上、向下、向左、向右均能正确判断阻挡与边界 |
| 关卡设计 | DeepSeek | 根据“5 个关卡、箭头数递增至 20”的要求,生成 5 组字符画关卡数组,并给出对应的箭头数量统计 | 前三关可正常通关,但第四、五关存在循环阻挡,贪心求解器返回无解,实际无法通关 | 手动查看第4关,第5关找出无法通过的问题所在并作出修改 |
| Pygame动画与状态机设计 | DeepSeek | 提出模块化拆分方案,生成GameSession状态机、ShakeManager抖动、FlyOut飞出动画代码,定义菜单/游玩/通关/失败状态 |
动画能够运行,但抖动幅度偏大、飞出动画时间不合理 | 调整动画时长参数FLY_TIME、SHAKE_TIME;修改通关触发逻辑 |
五、测试结果
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 箭头播放飞出动画后消失 | 通过 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,可失误次数减1 | 箭头变红抖动,可失误次数 -1 | 通过 |
| T03 | 点击位于边缘且朝向棋盘外的箭头 | 箭头正常消失,不发生越界错误 | 正常飞出,无报错 | 通过 |
| T04 | 消除本关全部箭头 | 显示通关并进入下一关 | 弹出“本关通关”,点击进入下一关 | 通过 |
| T05 | 失误次数耗尽 | 显示失败并允许重新开始 | 弹出“挑战失败”,可重试本关 | 通过 |
| T06 | 游戏进行中重新开始 | 箭头布局和失误次数恢复 | 棋盘重置,可失误次数恢复为 5 | 通过 |
| T07 | 启动时自动校验所有关卡可解性 | 5 个关卡均返回有效移除顺序 | 控制台无“无解”警告,全部通过 | 通过 |
六、PSP 表格
PSP 个人软件过程表
| 任务 | 预估耗时(小时) | 实际耗时(小时) | 差异(小时) |
|---|---|---|---|
| 需求分析与游戏设计 | 0.5 | 1 | +0.5 |
| Python 与图形库学习 | 3 | 2.5 | -0.5 |
| 游戏界面实现 | 3 | 3.5 | +0.5 |
| 路径与碰撞逻辑实现 | 4 | 4.5 | +0.5 |
| 关卡设计 | 2 | 3 | +1.0 |
| AIGC 辅助开发 | 2 | 1.5 | -0.5 |
| 测试与修改 | 3 | 4 | +1.0 |
| README 与博客撰写 | 2 | 2 | 0 |
| 合计 | 19.5 | 22 | +2.5 |
七、心得体会
- 本次作业是我第一次独立从零开发一个功能完整的小游戏项目,也是我初次系统学习并使用pygame等开发工具。项目起步阶段,我对整体项目架构没有清晰概念。各类问题会同时出现,例如环境配置、代码逻辑等问题。
- 在开发过程中,AIGC起到了很好的辅助开发作用。AI能够快速生成代码框架、基础算法、动画实现思路,节省了大量编写基础模板代码的时间,在路径检测、动画逻辑、关卡字符画生成等任务上快速给出方案,提升了项目开发效率。
- 但AI生成的代码也会出现各种问题:生成的关卡可能存在无解死局;动画参数、交互时序不符合预期,不能直接交付使用。所以AI只能作为辅助工具,输出内容必须人工仔细阅读、调试、测试与修正,不能直接照搬。


浙公网安备 33010602011771号