2026 秋软件工程个人作业(第二次)

2026 秋软件工程个人作业(第二次)

这个作业属于哪个课程 H202601软件工程与软件工程实践
这个作业要求在哪里 2026秋软件工程个人作业(第二次)
这个作业的目标 使用 Python 和 AIGC 完成"一箭又一箭"小游戏
学号 102401425
GitHub 仓库 https://github.com/SuCylinder/arrow_game

一、项目展示

视频演示

视频演示(百度网盘)

项目截图

开始界面
img

游玩界面
img

AI演示功能
img

关卡选择
img

游戏失败界面
img

通关界面
img

二、项目介绍

  • 玩法:5x5 棋盘上放若干单格箭头(上 / 下 / 左 / 右),点击某支箭头后检查它前进方向到边界之间是否还有别的箭头;无阻挡则飞出消失,有阻挡则碰撞,扣 1 次失误。
  • 流程:开始界面 → 关卡选择 → 游戏界面 → 通关 / 失败界面;共 6 关,箭头数 6 / 8 / 10 / 12 / 14 / 16,每关失误次数 3 次。
  • 界面:HUD 显示当前关卡、剩余箭头数、剩余失误次数(圆点)、重开按钮;支持 Esc / R 快捷键。
  • 扩展功能(7 项):
    • 关卡选择(含锁定 / 解锁、星级与最好成绩)
    • 计时得分与三星评价
    • 提示(H 键)
    • 撤销上一步成功飞出(Z 键)
    • AI 演示自动通关
    • 随机挑战
    • 进度存档到 save.json
  • 环境:Python 3.11 + pygame(见 game/requirements.txt),入口 game/main.py。

三、实现思路

1. 数据表示

  • 关卡定义:每关是一个列表,元素为(方向, 行, 列),方向用常量 UP/DOWN/LEFT/RIGHT(1~4),行列 0~4 对应 5×5 棋盘,见 arrow/levels/level1.py。
  • 运行时展开:build_arrows(defs) 生成 board[5][5](存箭头 id 或 EMPTY=0)和 arrows 列表、arrow_by_id 字典;单格箭头用 Arrow 类记录 id、方向、head 坐标和 alive 状态,方向非法、越界或重叠抛 ValueError。

2. 路径检测(核心规则)

  • can_fly(board, arrow_by_id, r, c) 按作业要求“同一行或同一列、箭头与边界之间是否还有别的箭头”逐格判断:取方向向量 DIRS = {UP:(-1,0), DOWN:(1,0), LEFT:(0,-1), RIGHT:(0,1)},从起点下一格 r+dr, c+dc 开始 while 0<=nr<N 扫描,遇到非 EMPTY 立即返回 False,一路扫到越界返回 True。先判边界再索引,不会越界。
  • 触发:点击时把鼠标坐标换算为格子,空位忽略;可飞则启动 FlyAnim 滑出,不可飞则启动 ShakeAnim 晃动变红并 mistakes_left -= 1。

关键代码(arrow/core/logic.py):

def can_fly(board, arrow_by_id, r, c):
    value = board[r][c]
    if value == EMPTY:
        return False
    arrow = arrow_by_id[value]
    dr, dc = DIRS[arrow.direction]      # UP:(-1,0) DOWN:(1,0) LEFT:(0,-1) RIGHT:(0,1)
    nr, nc = r + dr, c + dc
    while 0 <= nr < N and 0 <= nc < N:  # 先判边界,再索引,不会越界
        if board[nr][nc] != EMPTY:      # 路径上遇到别的箭头 → 碰撞
            return False
        nr += dr
        nc += dc
    return True                          # 一路扫到出界 → 可飞

3. 状态机与交互

  • 五状态:STATE_START 开始界面、STATE_SELECT 关卡选择(锁定/解锁、星级与最好成绩)、STATE_PLAY 游戏中、STATE_WIN/STATE_LOSE 结果界面,见 arrow/config/rules.py。
  • 胜负:count_arrows 为 0 进 WIN;失误归零后锁定点击(防止抢点)、进 LOSE;两状态均可重开本关(按钮/R 键)或返回。
  • 输入:鼠标点棋盘与 HUD 按钮;键盘 Esc 返回、R 重开、H 提示可飞箭头、Z 撤销上一步成功飞出。

关键代码(arrow/config/rules.py 状态常量):

STATE_START = "start"
STATE_SELECT = "select"
STATE_PLAY = "play"
STATE_WIN = "win"
STATE_LOSE = "lose"

关键代码(arrow/game.py 点击与胜负,节选):

def try_click(self, r, c):
    value = self.board[r][c]
    if value == EMPTY:
        return
    arrow = self.arrow_by_id[value]
    if self.mistakes_left <= 0:
        return  # 失误用完:锁定,等动画结束进失败界面
    if self.can_fly(r, c):
        self.anims.append(FlyAnim(arrow))   # 可飞 → 滑出动画
    else:
        self.anims.append(ShakeAnim(arrow))  # 被挡 → 晃动变红
        self.mistakes_left -= 1

# 胜负切换(节选)
self.state = STATE_WIN    # count_arrows() == 0 时
self.state = STATE_LOSE   # 失误归零且动画播完时

4. 动画与渲染

  • 飞出:按方向用 fly_distance 计算完整滑出距离(头中心到边界 0.5 格 + 三角形底边 + 安全余量 FLY_MARGIN),插值平移至完全出界后清盘面数据。
  • 碰撞:原地左右晃动 + 变红,结束后恢复原色。
  • 绘制:view 层负责渐变背景、HUD 圆角面板(关卡/剩余/失误圆点)、消息胶囊、棋盘外框、箭头三角形(gfxdraw 抗锯齿)与按钮投影描边,arrow/game.py 只做薄封装。

5. 关卡与可通关保证

  • 规模:共 6 关,箭头数 6/8/10/12/14/16,每关失误 3 次(MISTAKES_PER_LEVEL)。
  • 生成:用“倒序摆盘”生成器反向构造——从空盘开始逆向放置箭头,保证每步都有可飞的,再反向得到正向参考解(如第 1 关 (4,3)→(2,3)→(2,0)→(1,3)→(1,1)→(1,2)),不合格盘面自动丢弃并用参考解复验逐关清空、不扣失误。

6. 项目结构

  • core 零 pygame(logic/generator/solver/scoring/save,可单测)、view 负责表现、config 集中常量、levels 每关一文件聚合为 LEVELS,Game 在 arrow/game.py 串联状态、计时得分三星与存档 save.json。

四、AIGC 使用过程

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
需求分析 Hermes Agent (muse spark 1.3) 梳理作业要求,拆出规则判定、状态机、关卡、测试博客等功能点,定单文件 Tkinter/Pygame 方案 拆解可用,但关卡可解性没考虑到 定 Pygame 方案,补上倒序摆盘保证可通关的要求
路径检测 can_fly opencode (deepseek v4.1flash) 四个方向逐格扫描 + 边界判断 初版方向向量行列写反,自测即暴露 按反馈修正为 UP:(-1,0)、LEFT:(0,-1) 等,并补下一关越界保护
关卡设计 opencode (deepseek v4.1flash) “倒序摆盘”生成器,保证每关必有通关顺序 首版有解但偏简单 定筛选标准并人工筛选盘面,参考解逐关复验
回归单格 opencode (deepseek v4.1flash) 对照作业原文,把逻辑改为沿方向扫到边界,关卡改为 6/8/10 支 验证通过,代码精简 决定回归单格方案,定规模与失误 3 次
扩展功能 opencode (deepseek v4.1flash) 关卡扩到 6 个,加得分计时三星、提示撤销、存档随机挑战、AI 演示 评分公式与 AI 演示两处缺陷,修复后通过 选定 7 项,定撤销提示存档规则
飞出 / 碰撞动画 opencode (deepseek v4.1flash) 滑出插值 + 晃动变色动画 结尾空转、失败判定有抢点窗口 按几何精算滑出距离,失误归零后锁定操作
界面美化 opencode (deepseek v4.1flash) 渐变背景、HUD 圆角面板、消息胶囊、结果徽章 两处撞色(按钮描边、徽章与箭头色) 选定克制专业风,改深色描边

对话记录截图

1. hermes需求拆解

img

2. 修复存档功能

img

五、测试结果

按 T01~T09 逐项手工实测后填写:

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 与预期一致,箭头滑出消失 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 与预期一致,箭头晃动变红、失误次数减 1 通过
T03 点击位于边缘且朝向棋盘外的箭头 箭头正常消失,不发生越界错误 与预期一致,边缘箭头正常飞出 通过
T04 消除本关全部箭头 显示通关并进入下一关 与预期一致,通关后进入下一关 通过
T05 失误次数耗尽 显示失败并允许重新开始 与预期一致,显示失败界面可重开 通过
T06 游戏进行中重新开始 箭头布局和失误次数恢复 与预期一致,布局与失误次数均恢复 通过
T07 按 H 提示可飞箭头 高亮显示一支当前可飞的箭头 与预期一致,高亮一支且不影响计分 通过
T08 按 Z 撤销上一步 撤销上一次成功飞出的箭头 与预期一致,箭头与得分/步数回退 通过
T09 关卡选择与存档 通关解锁下一关、记录最好成绩与星级 与预期一致,解锁与存档正常 通过

另外,AI 还帮我写了个自动化测试脚本,放在 game/test_smoke.py,在 game/ 目录下跑 uv run python test_smoke.py 就行。它是无头跑的(SDL_VIDEODRIVER=dummy),不用弹窗口,覆盖了通关流程、路径检测、飞出/碰撞动画、渲染、关卡数据、失败窗口、扩展功能、模糊测试和真实入口主循环,刚才跑了一遍是 SMOKE OK:331 项检查全部通过,改完逻辑跑一遍,有 FAIL 直接看那行就行。

六、PSP 表格

〈待填:按自己实际投入填写,开发时顺手计时〉

任务 预估耗时(小时) 实际耗时(小时) 差异(小时)
分析和需求拆解 0.5 0.5 0
Python 与图形库学习 0.5 0.6 +0.1
AI 辅助开发 1.5 1.7 +0.2
测试与修改 0.5 0.6 +0.1
文档撰写(README/博客等) 0.5 0.6 +0.1
合计 3.5 4 +0.5

七、心得体会

这次作业 AI 确实帮我省了不少时间,但也不是全程顺利。搭框架和写 can_fly 这种规则代码时 AI 很快,方向向量写反这种低级 bug 也是跑测试时当场暴露、当场改好的。关卡生成那块我一开始没想到可解性问题,是 AI 提醒要用"倒序摆盘"反向构造,这个思路我觉得挺巧的,后来每关能不能通关全靠它保证。

AI 帮我写的自动化脚本 game/test_smoke.py 也很好用,在 game 目录下跑一下就行,不用开窗口,331 项全过,改完跑一遍很放心。

但 AI 也挖过坑。印象最深的是中间有一版多格蛇形箭头,看着很炫,动画还专门做了贪吃蛇式跟随,结果回头对照作业要求才发现基础版只要单格,等于白做了,只能回退。还有评分公式里时间奖励写反了,超时反而分更高,界面配色也有两处撞色,都是跑测试测出来的。所以我现在的感觉是,AI 写出来的东西一定得跑测试验一遍,不能直接信。

自己学到的东西,一是路径检测这种"沿方向扫到边界"的写法,看着简单但边界条件很容易写错;二是状态机加无头测试这套流程,游戏逻辑和 pygame 渲染分开之后,core 层不用开窗口就能测,改起来心里有底。以后写稍大一点的程序,我应该也会先把能单测的部分拆出来。

posted @ 2026-09-15 16:11  SuCylinder  阅读(30)  评论(0)    收藏  举报