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

项目 内容
这个作业属于哪个课程 H202601软件工程与软件工程实践
这个作业要求在哪里 2026 秋软件工程个人作业(第二次
这个作业的目标 使用 Python 和 AIGC 完成“一箭又一箭”小游戏
学号 102401304
GitHub 仓库 https://github.com/Sakura-x000/arrow-game

一、项目展示

1. 关卡选择界面

select

一开始只能选第 1 关,其他关卡灰色“未解锁”。通关后自动解锁下一关。每关显示已获得的星数和最快用时,限时模式显示最高分。

2. 游戏界面

play

顶部显示当前关卡、剩余箭头、失误次数、用时。下面两行按钮:暂停、撤销、提示、重新开始、返回。棋盘是彩色箭头,四方向。

3. 通关界面

win

弹出“太棒了!”,按失误次数显示 1~3 星,并显示本关用时。第 1~5 关有“下一关”和“返回选关”。

4. 失败界面

lose

失误达到 3 次时弹出“再试一次吧!”,可以“重来”或“返回选关”。返回不会解锁下一关。

5. 限时模式

timed
屏幕截图 2026-09-20 160508

第 6 关是限时模式,进关前弹出玩法说明。地图随机生成,30 秒内点击箭头得分,连续 3 连击 +2 秒,点到被挡箭头 -2 秒。结算显示连击、用时、分数和最高分。


二、项目介绍

游戏规则

  • 棋盘是网格,每个格子里可能有一个箭头,方向为上、下、左、右。
  • 点击箭头,程序检查它前进方向上有没有别的箭头。
  • 前方没有阻挡 → 箭头飞出棋盘并消失。
  • 前方有阻挡 → 箭头原地晃动变红,失误次数 +1。
  • 清空全部箭头 → 通关,按失误次数获得 1~3 星。
  • 失误达到 3 次 → 失败,可以重来或返回选关。
  • 通关当前关卡解锁下一关。

关卡设计

关卡 网格 类型
第 1 关 4x4 普通
第 2 关 4x4 普通
第 3 关 4x4 普通
第 4 关 5x5 普通
第 5 关 6x6 普通
第 6 关 7x7 限时模式,随机生成

界面设计

  • 深蓝渐变背景,带装饰圆点
  • 顶部深色圆角卡片显示关卡信息
  • 棋盘用浅色卡片包住
  • 按钮圆角 + 阴影 + 悬停变色
  • 结算弹窗居中,带圆角和阴影

主要功能

  • 四个方向的箭头
  • 鼠标点击交互
  • 路径阻挡判断
  • 飞出动画(渐隐)
  • 碰撞反馈(晃动 + 变红)
  • 失误计数
  • 6 个关卡(3 个 4x4、1 个 5x5、1 个 6x6、1 个限时模式)
  • 关卡选择与解锁
  • 星级评价
  • 每关用时记录
  • 限时模式:倒计时、连击、加分、最高分
  • 撤销(限 3 次)
  • 提示(限 3 次,高亮可飞箭头)
  • 暂停、保存进度、继续存档
  • 重新开始、返回选关

三、实现思路

1. 箭头怎么表示

每个关卡是一个二维列表,每个格子要么是 0(空),要么是 'U' / 'D' / 'L' / 'R'

['R', 0, 0, 'U'],

表示第 0 行第 0 列是朝右的箭头,第 0 行第 3 列是朝上的箭头。

2. 方向怎么表示

用一个字典把方向字母翻译成“行变化、列变化”:

DIRS = {
    'U': (-1, 0),   # 上:行 -1,列不变
    'D': (1, 0),    # 下:行 +1,列不变
    'L': (0, -1),   # 左:行不变,列 -1
    'R': (0, 1),    # 右:行不变,列 +1
}

因为 Pygame 和二维列表的 y 轴都向下,所以“上”对应行 -1,“下”对应行 +1。

3. 路径检测

点一个箭头时,沿它的方向一格一格往外走,只要遇到非空格子就说明被挡:

def is_blocked(r, c, direction):
    dr, dc = DIRS[direction]
    nr, nc = r + dr, c + dc
    while 0 <= nr < ROWS and 0 <= nc < COLS:
        if board[nr][nc] != 0:
            return True
        nr += dr
        nc += dc
    return False

比如朝右 R,就从 c+1 一直看到最右列;朝上 U,就从 r-1 一直看到最上行。

4. 飞出方向

飞出速度直接用同一个 DIRS

dr, dc = DIRS[cell]
vx = dc * 22   # 列变化 → 横向
vy = dr * 22   # 行变化 → 纵向

这样箭头指向哪,就飞向哪,不会错。

5. 画箭头

为了不出错,四个方向分别写死顶点坐标,不做旋转:

  • 朝右:箭头指向 +x
  • 朝左:箭头指向 -x
  • 朝上:箭头指向 -y
  • 朝下:箭头指向 +y

6. 撤销

每次点击箭头前,把当前棋盘、失误、用时存进一个栈:

def push_undo():
    undo_stack.append({
        "board": [[cell for cell in row] for row in board],
        "mistakes": mistakes,
        "elapsed_ms": get_elapsed_ms(),
    })

点“撤销”时弹出栈顶恢复。每关限 3 次。

7. 提示

找出当前所有前方无阻挡的箭头,随机选一个高亮:

def find_free_arrows():
    result = []
    for r in range(ROWS):
        for c in range(COLS):
            cell = board[r][c]
            if cell != 0 and not is_blocked(r, c, cell):
                result.append((r, c))
    return result

高亮闪烁 2 次,每关限 3 次。

8. 限时模式

  • 每关进前先弹玩法说明
  • 30 秒倒计时,点掉箭头 +1 分,3 连击 +2 秒
  • 点到被挡箭头 -2 秒,连击清零
  • 时间到结算,分数 = 箭头数 + 剩余秒数 ÷ 2
  • 地图随机生成时避免面对面箭头,保证有解

四、AIGC 使用过程

记录 1:路径检测

项目 内容
子任务 路径检测
AIGC 工具 DeepSeek
提问 请帮我解释一下 Python 里 is_blocked 函数是怎么判断箭头前方有没有阻挡的。
AI 提供 解释了 DIRS 字典的作用、while 循环怎么沿方向走、anyrange 怎么用。
效果 帮助我理解了代码逻辑,确认方向字典用 (dr, dc) 是对的。
人工修改 原本想用 any 简写,后来改成 while 循环,更容易看懂。

记录 2:飞出动画

项目 内容
子任务 飞出渐隐动画
AIGC 工具 ChatGPT
提问 我想给这个 Pygame 小游戏加一个箭头飞出时的渐隐动画,请给我代码。
AI 提供 pygame.SurfaceSRCALPHA 画半透明箭头,每帧增加 fade 值。
效果 基本可用,箭头飞出时慢慢消失。
人工修改 调整了每帧位移量和渐隐速度,让动画更自然。

记录 3:关卡设计

项目 内容
子任务 第 3 关设计
AIGC 工具 Kimi
提问 请帮我设计一个 4x4 的“一箭又一箭”关卡,要求有解,并给出通关顺序。
AI 提供 给出布局和通关顺序。
效果 第一次给的布局有死局,同一行两个相对箭头互相挡。
人工修改 手工调整布局,把相对箭头放到不同行,最终确定第 3 关。

记录 4:撤销功能

项目 内容
子任务 撤销
AIGC 工具 DeepSeek
提问 用 Python 实现撤销上一步,保存棋盘和状态,限 3 次。
AI 提供 用一个 list 当栈,每次点击前 append 当前状态,撤销时 pop
效果 可用。
人工修改 加了最多 50 步限制,防止内存太大;每关重置次数。

记录 5:限时模式

项目 内容
子任务 限时模式
AIGC 工具 ChatGPT
提问 用 Pygame 做一个 30 秒倒计时模式,点箭头加分,3 连击加时。
AI 提供 pygame.time.get_ticks() 记录每帧间隔,扣倒计时。
效果 基本可用。
人工修改 加了结算界面、最高分记录、地图随机生成。

记录 6:界面排版

项目 内容
子任务 顶部按钮排版
AIGC 工具 Kimi
提问 游戏顶部有 5 个按钮和 3 行信息,怎么排不重叠。
AI 提供 建议按钮分两行靠右,信息靠左动态排。
效果 可用。
人工修改 按窗口宽度动态算按钮位置,信息按渲染宽度依次排。

五、测试结果

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 箭头沿指向飞出,渐隐后消失 ✅ 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 箭头原地晃动变红,失误 +1 ✅ 通过
T03 点击位于边缘且朝向棋盘外的箭头 箭头正常消失,不发生越界错误 箭头正常飞出,无越界、无报错 ✅ 通过
T04 消除本关全部箭头 显示通关并进入下一关 弹出“太棒了!”弹窗,显示星数 ✅ 通过
T05 失误次数耗尽 显示失败并允许重新开始 弹出“再试一次吧!”弹窗,可重来 ✅ 通过
T06 游戏进行中重新开始 箭头布局和失误次数恢复 布局恢复初始,失误归零 ✅ 通过
T07 通关第 1 关后返回选关 第 2 关解锁 第 2 关从灰色变为可点击 ✅ 通过
T08 通关时按失误次数计算星数 失误 0 次 3 星,1 次 2 星,2 次 1 星 星数与失误次数对应正确 ✅ 通过
T09 第 5 关通关后 进入限时模式弹窗 弹窗显示玩法说明 ✅ 通过
T10 失败后返回选关 不解锁下一关 下一关仍为灰色 ✅ 通过
T11 点撤销 恢复上一步,次数 -1 棋盘、失误、用时都恢复 ✅ 通过
T12 点提示 高亮可飞箭头,闪两次 黄色高亮闪烁 ✅ 通过
T13 暂停并保存 存档,选关界面显示“有存档” 存档生效 ✅ 通过
T14 继续存档 恢复棋盘、失误、用时 状态恢复 ✅ 通过
T15 限时模式倒计时 30 秒倒计时,3 连击 +2 秒 倒计时正常 ✅ 通过
T16 限时模式结算 显示连击、用时、分数、最高分 符合预期 ✅ 通过

六、PSP 表格

任务 预估耗时(小时) 实际耗时(小时) 差异(小时)
需求分析与游戏设计 1 1 0
Python 与图形库学习 2 2 0
游戏界面实现 3 4 +1
路径与碰撞逻辑实现 2 2.5 +0.5
关卡设计 1 2 +1
撤销、提示、暂停、存档 2 2.5 +0.5
第 4、5 关扩大网格 1 1 0
限时模式 2 3 +1
界面排版优化 1 2 +1
AIGC 辅助开发 2 2 0
测试与修改 2 2.5 +0.5
README 与博客撰写 2 2 0
合计 21 26.5 +5.5

七、心得体会

这次作业让我第一次完整地做了一个小游戏,也第一次真正用 AIGC 工具辅助开发。

AI 带来的帮助:

  • 帮我搭出了游戏框架,省去了从零开始写界面的时间。
  • 帮我解释了路径检测的逻辑,让我理解了方向字典的用法。
  • 帮我设计了关卡、动画、撤销、提示、限时模式。
  • 界面美化时给了不少建议。

遇到的问题:

  • 方向判断一开始总出错,箭头指向和飞出方向不一致。后来发现问题出在方向字典的元组顺序上,统一改成 (dr, dc) 后就好了。
  • 关卡设计很容易出现死局,同一行两个相对箭头会互相挡。后来学会先手工验证一遍再写进关卡数据。
  • 限时模式随机生成箭头时,第一次也出现了面对面箭头,后来加了生成前的检测。
  • 界面一开始很简陋,后来一步步调颜色、加卡片、加圆角。按钮太多时还会遮挡,最后改成两行靠右排列。
  • 窗口尺寸和关卡网格大小相关,进不同关卡要重新调整窗口,一开始忘了处理,导致闪退。

收获:

  • 理解了二维网格游戏的基本结构:数据、方向、路径检测、动画、状态管理。
  • 学会了怎么和 AI 协作:AI 给代码,我负责运行、测试、发现问题、让它改。
  • 知道了 AI 生成的代码不能直接用,必须自己跑一遍,尤其是方向、边界、布局这些地方。
  • 学会了把一个大功能拆成几个小步骤,每步跑通再继续。

总的来说,这次作业让我对 Python 和游戏开发有了直观的认识,也让我更清楚 AI 能帮什么、不能帮什么。

posted @ 2026-09-20 16:33  Sakurax  阅读(14)  评论(0)    收藏  举报