第二次软工作业“我炒,冰!!!”

项目 内容
这个作业属于哪个课程 H202601软件工程与软件工程实践
这个作业要求在哪里 2026秋软件工程个人作业
这个作业的目标 使用 Python 和 AIGC 完成“一箭又一箭”小游戏
学号 102401206
GitHub 仓库 我的仓库

项目展示

我将我的游戏命名为“我炒,冰!!!”,使用 Python 和 pygame-ce 编写。
视频:演示视频
开始界面列出"开始游戏"和"游戏规则"两个按钮,点击"开始游戏"进入第一关。

我炒,冰!!! 2026_9_22 23_45_49

游戏中,背景是空棋盘贴图,箭头按方向摆在格子上;左上角桃粉色气泡显示当前关卡,棋盘正上方两个米白色气泡分别显示剩余箭头和剩余生命,右上角桃粉色气泡是"重开"按钮。

我炒,冰!!! 2026_9_22 23_46_02

点击被挡住的箭头时,箭头原地晃动并显示"哎呀!前面有冰淇淋挡住啦!"的提示,剩余生命减一。清空当前关卡后进入通关页,可进入下一关或返回主菜单

我炒,冰!!! 2026_9_22 23_46_25

生命用完则进入失败页,可重新开始或返回主菜单。

我炒,冰!!! 2026_9_22 23_46_13

我还给它加了个欢快的BGM

项目介绍

游戏规则

棋盘是一个5X5的网格,白底波浪花边的棋盘外框,每格为空,或放置一个朝上、下、左、右的冰激凌。用鼠标左键点击冰激凌所在的格子,让冰激凌沿奶油尖尖的方向离开棋盘。

只有当冰激凌前方到棋盘边界之间有没有其他冰激凌时,冰激凌才可飞出。但如果路径上还有冰激凌,就不能消除,且扣除一调生命,阻挡的冰激凌朝向并不影响判断。每关有三条生命,清空棋盘就通关,用完就失败。

界面和功能

界面使用梦幻的童话背景、浅粉色格子和浅蓝色冰激凌箭头。方向时冰激凌的奶油尖端。全部图像素材由ChatGPT生成。BGM找的是pixabay中免费无版权的音乐

开始页说明规则,游戏页显示棋盘和计数,结果页提供下一关、重玩或返回首页的操作。结果页出现后,底层棋盘不再响应点击。

飞出和碰撞都有动画。点击空格、棋盘外区域和已消除的位置不会扣次数。

三个固定关卡

关卡 棋盘大小 箭头数量 设计内容
第一关 5 × 5 6 认识四方向与基本阻挡顺序
第二关 5 × 5 9 增加隔空格的阻挡与跨行列的依赖
第三关 5 × 5 9 连续解除多组阻挡,需要观察更多箭头

实现思路

箭头、方向、关卡的表示

规则代码放在 game_logic.py,界面、动画和鼠标事件放在 main.py。路径判断不依赖图形库,可以单独运行测试。

每个箭头用一个 Arrow 数据类表示,包含 row、col 和 direction:

`@dataclass(frozen=True)
class Arrow:
row: int
col: int
direction: str

DIRECTIONS = {
"U": (-1, 0),
"D": (1, 0),
"L": (0, -1),
"R": (0, 1),
}`

坐标从零开始,左上角是 (0, 0),向下增加行号,向右增加列号。三个关卡写在 LEVELS 里,每关是一个 (row, col, direction) 元组列表;程序启动时用 can_solve 逐关校验,布局不可解会直接报错。重开时用模板重新构造 Arrow 列表,恢复初始布局;剩余箭头数用 len(self.arrows) + len(self.animations) 实时统计,避免棋盘已经改变、计数却忘记更新。

方向转换为行列增量后,四个方向可以共用一段检测逻辑:

方向 编码 行列增量 (dr, dc)
U (-1, 0)
D (1, 0)
L (0, -1)
R (0, 1)

路径检测

路径检测从箭头前方的相邻格开始,沿方向逐格检查到棋盘边界。先收集其他箭头的坐标集合,遇到占位就返回 False,走出边界仍未遇到箭头就返回 True:

def is_path_clear(arrows, target, grid_size=5): dr, dc = DIRECTIONS[target.direction] occupied = {(a.row, a.col) for a in arrows if a != target} r, c = target.row + dr, target.col + dc while 0 <= r < grid_size and 0 <= c < grid_size: if (r, c) in occupied: return False r += dr c += dc return True

例如某一行是 → · · ↑,点最左边的 → 时检测会经过两个空格再遇到 ↑,判定为阻挡;等 ↑ 被消除后这行变成 → · · ·,再点 → 就能飞出。检测先把目标自己排除掉,避免把自己当成阻挡;循环里先判断坐标在棋盘内、再查占用集合,走出边界自然返回 True,不会越界。这个问题只需沿一条直线检查,一次检测的时间复杂度为 O(n),空间复杂度 O(n)(用于收集其他箭头的坐标集合)。

关卡可解性

验证关卡时,can_solve 复制一份箭头列表,不断找出当前可以飞出的箭头并删除,能清空就说明可解;如果棋盘还有箭头却找不到任何可飞出的箭头,就说明存在无法解除的阻挡:
def can_solve(arrows, grid_size=5): remaining = list(arrows) while remaining: movable = next((a for a in remaining if is_path_clear(remaining, a, grid_size)), None) if movable is None: return False remaining.remove(movable) return True

这里可以用贪心检查,因为删除箭头只会减少阻挡、不会制造新的阻挡,一个原本能飞出的箭头不会因为别的箭头被删而变得不能飞出,所以不需要枚举所有点击顺序。三个内置关卡都通过这项校验,游戏界面没有提供自动求解按钮。

动画和状态切换

程序用 scene 区分开始、游戏、通关、失败、规则等界面。成功点击后先加入飞出动画,动画结束(约 0.42 秒)才把箭头真正从列表移除;如果这时剩余箭头为零,再进入通关页。碰撞在点击时扣一次生命并播放晃动(约 0.28 秒)和提示文字,生命归零进入失败页。动画在 update(dt) 里按帧推进,播放期间不 sleep 阻塞事件循环;重开会丢弃当前动画并重新加载本关模板,旧动画不会继续修改新棋盘。

AIGC 使用过程

本次开发主要借助 Claude Code 完成,一共四轮。

第一次:搭建游戏核心(路径检测 + 关卡 + 界面)

我的要求:用 Python + Pygame 实现"一箭又一箭"基础玩法——四方向路径检测、碰撞扣分、飞出动画、通关/失败判定,并设计至少 3 个可通关关卡。

AI 完成:game_logic.py(Arrow 数据结构、is_path_clear、can_solve)和 main.py(窗口、三关数据、动画、状态切换、主循环)。

实际效果:基础玩法可直接运行,三关都能正常通关。

我的修改:根据试玩结果调整关卡布局与箭头数量。

第二次:整合冰淇淋主题贴图

我的要求:把界面改成冰淇淋主题,尽量使用自制 UI 贴图(起始页、空棋盘、过关、失败等),而不是纯色方块。

AI 完成:用模板匹配和颜色分割定位页面里已有的按钮,用 cv2 连通域去白底生成透明按钮 PNG,把朝上的箭头素材旋转出四个方向,页面按比例缩放居中。

实际效果:界面变成贴图风格,按钮点击区域与贴图对齐。

我的修改:根据实际运行窗口继续调整棋盘位置、按钮热区和素材尺寸。

第三次:修复 BGM 并重排游戏 UI

我的要求:修好消失的 BGM;重排游戏界面——关卡数左上角桃粉气泡、棋盘正上方剩余箭头和剩余生命(米白气泡)、右上角重开按钮;把"失误次数"改名"剩余生命";通关/失败页补上"返回主菜单"按钮并修好"下一关"对齐。

AI 完成:定位到 BGM 文件实为 MP3 却标成 .ogg、SDL 按扩展名解码失败,重命名为 bgm.mp3 后恢复;重写 HUD 气泡绘制与点击逻辑,接入"返回主菜单"按钮。

实际效果:BGM 恢复,游戏界面布局清晰,按钮正常响应。

我的修改:核对气泡配色与按钮位置。

第四次:测试、收尾与提交

我的要求:跑通测试,生成预览图核对界面,更新 README,提交到 GitHub。

AI 完成:运行 tests/test_logic.py 全部通过,生成各界面预览图核对按钮对齐,更新 README(bgm.mp3 等),Git 提交并推送到 GitHub。

实际效果:逻辑测试通过,代码已推送到 GitHub。

我的修改:补充真实试玩记录和截图。

☹️值得一提的是
我绘制了UI的设计稿,并要求Claude 进行UI优化,但clude有点笨,它做的并不令我满意。于是我转战deepseek,希望它能读懂我的UI设计。

deepseek的确通过试图功能完成了一部分我想要的东西,但还是没达到到我的的预期。我又使用chatGPT,chatGPT AI生成了一份我理想中的UI界面,我意识到可以通过贴图来完成UI 的优化。于是我开启了我崩溃又漫长的UI优化。

我的AI们都太笨了非常的不听话,贴图简直是在捣乱,我十分的崩溃。😭😭😭我在这一步卡了十个小时,没开玩笑

erinnnmrYI
只能说贴图害我!我的原本预期是长这样的
cc5d96731121d752b95bd5b278a8012a
哎,为了赶工砍了很多,我后面还会优化的!

测试结果

运行环境:Windows 11,Python 3.11.7,Pygame 2.6.1(SDL 2.28.4)。

在项目目录下执行:

python tests/test_logic.py

输出 All logic tests passed.。自动化测试覆盖路径检测(无阻挡、有阻挡、边缘朝外)和三关可解性;通关、失败、重开等界面行为通过实际试玩验证。

编号 测试项目 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 飞出后消除,生命不变 路径畅通,箭头飞出 通过
T02 点击被阻挡的箭头 不消失,扣一次生命,晃动 判定阻挡,扣生命并晃动 通过
T03 点击边缘且朝外的箭头 正常飞出,不越界 边界外视为可飞出 通过
T04 清空当前关卡 显示通关并可进入下一关 三关 can_solve 均通过,试玩可通关 通过
T05 生命耗尽 显示失败并可重新开始 生命归零进入失败页 通过
T06 游戏中重新开始 恢复初始布局和生命 重开恢复初始状态 通过

PSP表格

阶段 预计耗时(时) 实际耗时(时) 差异(实际 − 预计)
需求、环境和任务拆分 0.5 0.25 -0.25
规则、关卡与测试;界面并行开发 2 10 8
集成、自动化验收与画面检查 1 2 1
README、截图和测试记录 1 0.75 -0.25
合计 4.5 13 8.5

主要是耗了太多时间在UI上,真是气死我了

心得体会

这次开发我主要做的是给目标和约束。先向 AI 说明要一个冰淇淋主题的"一箭又一箭"游戏,再逐步提出界面贴图、路径检测、关卡、动画、音乐这些具体要求,代码编写、定位问题和修复都由 AI 接着执行。我不需要把每个函数拆成问题、逐段复制代码进项目,而是把精力放在说清楚"要什么、验收标准是什么"上。

指导也需要具体。只说"做一个箭头游戏",很多行为没有确定:动画中能不能继续点击、机会什么时候扣、重开是否保留当前关卡、最后一关结束后去哪里。把这些约定说清楚后,AI 才有依据实现,我核对时也有依据判断。

AI 生成的实现同样会出问题。BGM 消失是因为音乐文件其实是 MP3、却被标成 .ogg,按扩展名解码失败;按钮"下一关"一开始贴歪了;"返回主菜单"按钮最初只贴了图没接点击逻辑。去白底时还踩过一个坑:一开始用亮度阈值判断白色,结果把红色通道恒为 255 的粉色按钮内容也当成白底删掉了,后来改成只删除与图像边框相连的白色连通域才解决。这些问题都靠实际运行、看预览图、试玩才暴露出来,说明交给 AI 的任务要包含运行、检查和修复,不能只停在生成代码。

这几次修复也让我看到测试该怎么补。BGM 的问题要看文件头而不是文件名;按钮对齐要用颜色分割重新量位置;去白底要从"删什么"改成"只删连到边框的白色"。先复现问题,再验证修复是否有效,比单独加几个正常案例更有用。

人的工作还包括决定是否接受结果。AI 可以给出三关布局、路径检测和预览图,我仍需要理解路径为什么这样判断、看功能是否符合要求,并亲自试玩确认能通关。把代码实现交给 AI 后,这些判断没有消失。

以后做类似项目,我会继续先明确需求和验收条件,让 AI 连同实现、测试和问题修复一起完成;反馈时给出操作步骤、预期和实际结果,能写进文档的约定就写进去,能复现的问题就留下记录。这样我可以把时间用在说明需求和判断结果上。

posted @ 2026-09-22 23:51  WinterYew  阅读(4)  评论(0)    收藏  举报