软件工程作业二——完成“一箭又一箭”小游戏
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice/ |
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice/homework/16718 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | 102402121 |
| GitHub 仓库 | https://github.com/Rong-hub1/homework |
用 AIGC 完成“一箭又一箭”小游戏
一、项目展示
1. 开始界面
深色主题、圆角按钮、装饰箭头环绕的标题页。
[开始界面]

2. 游戏界面
顶部显示关卡、剩余箭头、失误心形;中央为棋盘;底部为操作按钮。
[游戏界面]

3. 通关界面
覆盖式半透明面板,圆形图标 + 提示文字 + 操作按钮。
[通关界面]

4. 失败界面
失误机会耗尽时弹出。
[失败界面]

演示 GIF:
二、项目介绍
游戏规则
“一箭又一箭”是一款点击式解谜小游戏。棋盘上摆放着朝上、下、左、右四个方向的箭头。玩家点击某一箭头:
- 若它到棋盘边界之间的路径上没有其他箭头阻挡,则该箭头沿自己的方向飞出棋盘并消失;
- 若路径上存在其他箭头,则箭头不能飞出,给出明显的碰撞反馈,并扣除一次失误机会;
- 清空全部箭头即通关;失误机会耗尽即失败。
界面设计
整体采用深色主题(深蓝背景 + 半透明网格 + 顶部光晕),箭头使用三层叠加(阴影 / 主色 / 内高光)形成立体感。鼠标悬停时箭头外围出现淡绿光晕,飞出时变为蓝色,碰撞时变为红色并左右抖动。
主要功能
- 开始 / 游戏 / 结算三类界面;
- 四个方向的箭头与路径检测;
- 点击飞出动画、碰撞抖动反馈;
- 失误次数(心形图标显示);
- 3 个可通关关卡、自动进入下一关;
- 重新开始 / 返回主菜单。
特色
- 心形失误图标由数学公式绘制(
x = 16sin³t, y = -(13cos t - 5cos2t - 2cos3t - cos4t)),未使用的失误显示为空心轮廓; - 结算使用覆盖式面板,不需要额外窗口;
- 关卡名称带有“初出茅庐 / 渐入佳境 / 登峰造极”的渐进感。
三、实现思路
1. 箭头和方向的表示
每个箭头用一个字典表示:
{'row': r, 'col': c, 'dir': d, 'alive': True}
方向与增量通过一张表映射(值为 (行增量 dr, 列增量 dc)**):
DIRS = {'up': (-1, 0), 'down': (1, 0),
'left': (0, -1), 'right': (0, 1)}
绘制箭头时使用另一个映射表,将方向映射为旋转角度,然后对一个归一化的多边形做旋转,这样任意方向都复用同一套绘制代码:
ARROW_ANGLES = {'right': 0.0, 'down': math.pi/2,
'left': math.pi, 'up': -math.pi/2}
2. 关卡表示
LEVELS = [
{'name': '初出茅庐', 'cols': 3, 'rows': 3, 'lives': 3,
'arrows': [(0,0,'right'), (0,1,'up'), ...]},
...
]
每个关卡记录棋盘尺寸、失误次数和箭头列表,切换关卡时直接重新读取即可。
3. 路径检测
从被点击的箭头出发,沿它的方向逐格前进,只要在同一行或同一列上还有其它存活的箭头,就判定为“被阻挡”:
def path_clear(self, a):
dr, dc = DIRS[a['dir']]
r, c = a['row'] + dr, a['col'] + dc
while 0 <= r < self.rows and 0 <= c < self.cols:
for other in self.arrows:
if other is a:
continue
if other['alive'] and other['row'] == r and other['col'] == c:
return False
r += dr
c += dc
return True
while 条件同时起到了边界保护的作用——一旦走出去就退出循环,返回 True,因此不会越界。
4. 动画
飞出动画用一个循环逐帧右移/左移/上移/下移箭头,配合颜色切换;碰撞动画则用 ±7px 的左右偏移做抖动,7 帧后恢复。
四、AIGC 使用过程
第 1 次:生成基础游戏框架
我的要求:
“用 Python 做一个‘一箭又一箭’小游戏,要求有开始界面、游戏界面、通关/失败界面,3 个关卡,四个方向的箭头,点击能飞出或被阻挡,有失误次数和重新开始。”
AI 完成:
一次性给出了完整的 Tkinter 实现,包括 LEVELS 数据结构、path_clear() 路径检测、on_click() 点击处理、飞出动画 fly_out()、碰撞反馈 hit_feedback(),以及开始/游戏/结算三类界面切换。
实际效果:
程序可以直接运行,但发现“箭头飞出方向和箭头方向差 90°,箭头飞出方向不对,游戏没有可行解,而且整体视觉比较朴素——纯色块、无阴影、没有悬停反馈。
人工修改:
debug定位到 DIRS常量错误,表被当作 (dr, dc) 使用,但里面填的值实际是 (dc, dr),相当于每个方向都旋转了 90°。给出了修正:
# 错误
DIRS = {'up': (0, -1), 'down': (0, 1),
'left': (-1, 0), 'right': (1, 0)}
# 正确
DIRS = {'up': (-1, 0), 'down': (1, 0),
'left': (0, -1), 'right': (0, 1)}
实际效果:
修改后四个方向的飞出和路径检测都正常了。
人工检查:
我逐关检查了一遍,确认每一关的箭头飞出方向和阻挡判断都符合预期,存在可行解。
第 2 次:初步美化界面
我的要求:
“现在的界面太丑了,做得更好看一点。”
AI 完成:
整体重构为深色主题,引入 round_rect() 圆角矩形工具、三层叠加的立体箭头、悬停光晕、覆盖式结算面板、心形失误图标,以及顶部光晕和网格背景。
实际效果:
视觉上确实接近商业小游戏,圆角、阴影、发光都有了。

第 3 次:修改与完善
我的要求:
“加计时和评级已经通关胜利特效。”
AI 完成:
无失误:3 星,1 次失误:2 星,≥2 次失误:1 星
计时器:每关从第一次点击开始,或者在关卡加载时立即开始。当关卡完成时,显示用时。
胜利特效:全部通关时,显示烟花/粒子动画。在 canvas 上使用粒子系统。
帧计数器用 self.root.after 来运行,用于计时器。
实际效果:
达到预期

小结
| 子任务 | AIGC 工具 | AI 提供了什么 | 效果 | 人工调整 |
|---|---|---|---|---|
| 基础游戏框架 | DeepSeek | 完整可运行的 Tkinter 实现 | 可运行,框架正确 | 更改参数设置 |
| 界面美化 | DeepSeek | 深色主题 + 圆角 + 立体箭头 + 覆盖式面板 | 视觉大幅提升 | 无 |
| 进一步美化并完善 | DeepSeek | 添加了计时、评价和特效 | 全部正常运行,效果更好了 | 逐关试玩验证 |
五、测试结果
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 箭头沿自身方向飞出并消失 | debug后 ✅ |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,失误次数减 1 | 箭头变红并抖动,失误心形减少 1 个 | ✅ |
| T03 | 点击边缘朝外的箭头 | 箭头正常消失,不越界报错 | 正常飞出,无异常 | ✅ |
| T04 | 消除本关全部箭头 | 弹出通关面板,进入下一关 | 显示“关卡通过”,可进入下一关 | ✅ |
| T05 | 失误次数耗尽 | 弹出失败面板,可重新开始 | 显示“关卡失败”,可选重新挑战 | ✅ |
| T06 | 游戏进行中重新开始 | 箭头布局和失误次数恢复 | 完全恢复初始状态 | ✅ |
测试方法: 手工测试。每一关按预设的通关顺序逐一点击,观察动画和状态;同时故意点击被阻挡的箭头,验证失误扣除逻辑。
六、PSP 表格
| 任务 | 预估耗时(分钟) | 实际耗时(分钟) | 差异(分钟) |
|---|---|---|---|
| 需求分析与游戏设计 | 5 | 3 | -2 |
| Python 与图形库学习 | 10 | 12 | +2 |
| 游戏界面实现 | 20 | 18 | -2 |
| 路径与碰撞逻辑实现 | 20 | 17 | -3 |
| 关卡设计 | 10 | 13 | +3 |
| AIGC 辅助开发 | 10 | 12 | +2 |
| 测试与修改 | 30 | 40 | +10 |
| README 与博客撰写 | 30 | 35 | +5 |
| 合计 | 130 | 145 | +15 |
七、心得体会
AI 带来的帮助:
从零到能运行只花了不到一次对话的时间,尤其是路径检测、动画循环这种“套路化”的代码,AI 写得又快又规范,让我可以把精力放在关卡设计和交互体验上。在美术上也有很大帮助。
出现的问题:
AI 在第二次重构时遗留了重复定义的函数,第三次又在方向常量上写反了 (dr, dc)——两个 bug 都不会导致程序崩溃,但都会让功能“看起来对、其实不对”。如果我不运行、不亲自试玩,是发现不了的。
自己的收获:
- AI 生成≠AI 负责。 代码进项目后,最终责任人是自己。要看懂、要跑、要测。
- 方向常量最好只定义一次。 如果把
DIRS和ARROW_ANGLES合并成一张表,就不会出现两处不一致的问题。 - 视觉美化要留时间回归测试。 界面美化时最容易顺手引入回归问题,必须重跑一遍测试用例。
参考资料:
- Python 官方文档 Tkinter 部分:https://docs.python.org/3/library/tkinter.html
- 心形公式参考:https://mathworld.wolfram.com/HeartCurve.html

浙公网安备 33010602011771号