深色模式
5.2 第一次迁移:做一个离线可用的算法可视化页
讲冒泡排序时,老师很容易在黑板上忙成一团:刚圈出正在比较的两个数,又要擦掉旧位置、写上新位置,还得提醒学生右边哪一段已经排好。学生看起来一直在点头,真正让他解释“这一轮为什么结束”,答案往往只剩一句“相邻两个数比较”。
问题不在于学生没有背过步骤,而在于比较对象、交换结果和有序区的变化没有同时留在眼前。
上一节,我们用项目迁移表区分了单 HTML、本地数据工具和完整校园 Web 项目。冒泡排序可视化页不需要保存共享数据,也没有多人协作流程,最合适的不是照搬排座系统的后端、数据库和登录,而是主动选择最轻的单 HTML 路线。
这次迁移只服务一个教学目标:学生看完一次完整演示后,能够解释相邻元素怎样比较、什么时候交换,以及每一轮结束后为什么会扩大有序区。
冒泡排序来自信息科技课堂,但这一篇示范的是更通用的“课堂单页”路线。数学函数变化、历史时间线排序、古诗句序重排和科学实验步骤演示,都可以沿用“聚焦一个目标、展示状态变化、用固定数据验收”的方法。
先删掉这个工具不需要的东西
教学页不是功能越多越好。第一版如果同时加入自动播放、速度滑块、自定义数组、音效和多种算法,老师很难判断错误到底来自排序逻辑、按钮状态,还是动画时间。
先把项目迁移表中的几个关键问题填清楚。
| 判断项 | 本项目的答案 |
|---|---|
| 谁来使用 | 老师在算法课上投影演示,学生观察并回答问题 |
| 要解决什么误区 | 学生只记住“相邻比较”,看不见当前比较对象和每轮形成的有序区 |
| 是否保存数据 | 不保存;关闭或刷新页面后回到同一组固定数组 |
| 是否多人共享 | 不需要 |
| 是否涉及敏感数据 | 不涉及学生姓名、成绩、账号等数据 |
| 最轻技术形态 | CSS、HTML 和 JavaScript 全部写在一个 index.html 中 |
| 运行位置 | 教室电脑本地浏览器,断开外网仍能打开 |
| 明确删除 | 后端、数据库、登录、在线接口、外部 CDN 和在线字体 |
单 HTML 不是“低配版网站”。它刚好满足课堂演示的真实条件:文件少、打开快、容易带走,也不会因为校园网临时不可用而卡死。
把必做与选做彻底分开
这一版的停止条件很明确:五项必做通过验收就停,不顺手加功能。
| 范围 | 内容 | 本文是否实现 |
|---|---|---|
| 必做 | 固定数组 | 是 |
| 必做 | 单步 | 是 |
| 必做 | 重置 | 是 |
| 必做 | 当前比较 | 是 |
| 必做 | 有序区 | 是 |
| 选做 | 自动播放、暂停、继续 | 否 |
| 选做 | 速度调节 | 否 |
| 选做 | 自定义输入 | 否 |
这里的“暂停思考”不依赖暂停按钮。每点一次“单步”,页面只推进一个可观察状态,然后自然停住,学生有时间先判断再回答。只有以后加入自动播放时,暂停和继续才成为需要实现的新按钮。
自定义输入同样不属于第一版。必做版只显示代码中预先写好的固定数组;重复数字和已排序数组通过更换这组固定测试数据来验收,不在页面上增加输入框、预设切换或随机生成。
写成一页最小 PRD
先把下面这份 PRD 放进独立项目目录。它不是给 Agent 的装饰性说明,而是后面判断“能不能停”的依据。
markdown
# 冒泡排序可视化页最小 PRD
## 教学目标
学生能够根据一次完整演示,解释相邻比较、交换和每轮最大值归位。
## 使用场景
老师在教室电脑上双击打开页面并投影,页面断开外网也能运行。
## 必做功能
1. 页面载入一组固定数组。
2. 单步按钮每次只推进一个可观察状态。
3. 页面突出当前比较的两个元素。
4. 每轮结束后标出已经有序的区域。
5. 重置按钮把数组、比较位置、有序区和按钮状态全部恢复到起点。
## 明确不做
不做自动播放、暂停、继续、速度调节、自定义输入、多算法切换、后端、
数据库、登录、在线接口、外部 CDN 和在线字体。
## 验收数据
默认固定数组:[5, 1, 4, 2, 8]
重复数字数组:[4, 2, 4, 1]
已排序数组:[1, 2, 3, 4, 5]
## 停止条件
五项必做通过算法正确性、投影可读性、重置完整性和断网验收后停止开发。这份 PRD 只认一个算法:冒泡排序。选择排序、快速排序和算法证明都留在本篇之外,避免一个 10 分钟课堂工具变成算法大全。
先把状态变化讲明白
页面不是“点一下就整段演完”的动画。为了让学生能预测,每次单步只推进一个状态。
| 状态 | 页面应该显示什么 | 下一次单步做什么 |
|---|---|---|
| 初始 | 显示固定数组;没有当前比较;有序区为空 | 进入第一对相邻元素的比较状态 |
| 比较 | 只突出当前相邻的两个元素,数组位置暂不改变 | 判断是否需要交换 |
| 交换 | 左边大于右边时交换位置,仍保留本次比较焦点 | 移向下一对相邻元素 |
| 不交换 | 左边小于或等于右边时保持位置不变 | 移向下一对相邻元素 |
| 单轮结束 | 本轮最大值到达右侧,右侧有序区扩大一格 | 从未排序区左端开始下一轮 |
| 全部完成 | 整个数组进入有序区,不再产生新的比较 | 单步按钮禁用,只允许重置 |
| 重置 | 恢复最初固定数组,清空比较位置和有序区 | 重新从第一对元素开始 |
重复数字的判断规则也要写清:只有左边数字大于右边数字时才交换,相等时不交换。这里不展开算法证明,只把页面必须遵守的行为交代清楚。
两个按钮的规则
第一版页面只有“单步”和“重置”两个按钮。
- 初始状态下,“单步”可用;“重置”点击后仍保持初始状态。
- 比较、交换、不交换和单轮结束后,页面都停住,等待下一次单步。
- 全部完成后,“单步”禁用,防止索引继续越界;“重置”保持可用。
- 任意中间状态点击“重置”,都必须恢复原数组、比较索引、轮次、有序区和按钮状态。
- 连续点击时,一次点击只触发一次状态推进,不因为动画叠加而跳过比较。
这张表和按钮规则,是老师确认 Agent 计划时最重要的依据。页面颜色是否好看可以后调,状态走错一步就不能进入课堂。 让 IDE Agent 先解释,不要立即写代码
新建一个独立项目目录,例如 bubble-sort-visualizer,在 IDE 中单独打开。不要把它塞进排座系统目录,也不要让 Agent 顺手复用原项目的框架和依赖。
先把 PRD 保存为 PRD.md,再把下面这段交给 IDE Agent。此时只允许它阅读和解释。
text
请先阅读当前目录中的 PRD.md,不要立即写代码,不要创建文件,
不要初始化 Git,也不要执行命令。
请用非技术背景老师能看懂的中文说明:
1. 冒泡排序在这个页面里需要经过哪些状态。
2. 每次单步将从什么状态走到什么状态。
3. 单步和重置两个按钮分别在什么情况下可用。
4. 页面怎样只用“当前比较”和“有序区”帮助学生观察。
5. 怎样把 HTML、CSS 和 JavaScript 放进一个 index.html,且不使用外部资源。
6. 怎样用固定数组、重复数字数组和已排序数组验收。
7. 准备创建哪些文件,Git 准备在哪些节点提交。
必做范围只有:固定数组、单步、重置、当前比较、有序区。
自动播放、暂停、继续、速度调节和自定义输入全部是选做,本阶段不要实现。
请先输出实现计划、状态变化表、按钮规则、测试用例和文件清单,
等我确认后再执行任何修改。Agent 回答后,老师不需要先审查语法细节,只检查下面几件事:
- 它有没有偷偷加入输入框、自动播放、速度滑块或其他算法。
- 一次单步是不是只推进一个可观察状态。
- 有序区是不是每轮结束后才扩大。
- 重置是否恢复所有状态,而不只是把数字改回去。
- 页面是否完全离线,不读取 CDN、字体、接口或远程图片。
- 文件清单是否围绕单 HTML 项目,没有引入框架和包管理器。
有一项说不清,就继续追问。全部符合 PRD 后,老师再明确回复“计划确认,可以执行第一阶段”。
确认后再建立需求基线
老师确认计划后,先让 Agent 建立项目基线,还不写功能页面。
text
计划已确认。现在只执行需求基线阶段:
1. 在当前独立项目目录初始化 Git。
2. 生成适合单 HTML 项目的 .gitignore,不加入无关框架配置。
3. 检查 PRD.md 与刚才确认的计划一致;如需改动,先说明差异。
4. 查看 Git 状态,确认没有目录外文件和敏感信息。
5. 提交一次需求基线。
本阶段不要创建 index.html,不要实现任何功能。
完成后报告新增文件、检查结果和提交信息。这个提交保存的是“我们已经确认要做什么”。以后 Agent 想扩大范围,老师可以直接回到 PRD 和需求基线核对,而不是凭印象争论。
第一阶段只实现五项必做
需求基线建立后,再允许 Agent 创建 index.html。CSS 和 JavaScript 都内嵌在这个文件里,不安装依赖,不启动后端。
text
需求基线已确认。现在实现第一阶段,并严格遵守 PRD:
1. 只创建一个可直接双击打开的 index.html。
2. 使用固定数组 [5, 1, 4, 2, 8]。
3. 只实现单步、重置、当前比较和有序区。
4. 每次单步只推进状态表中的一个状态,并在每步后停住。
5. 不实现自动播放、暂停、继续、速度调节、自定义输入和多算法切换。
6. 不使用后端、数据库、外部 CDN、在线字体、接口和远程图片。
7. 数字与两种状态在教室投影下要清楚,但不要加入与教学目标无关的效果。
完成后先自行检查算法状态、按钮状态、重置和外部依赖,
报告检查结果和代码差异。先不要提交 Git,等我完成课堂动作验收。这一步仍然由 IDE Agent 执行代码修改,老师负责确认页面行为。不要把整段代码复制到聊天窗口反复拼接,也不要在看不懂差异时直接接受一次大改。
用三组固定数组验收算法
页面没有自定义输入框,因此测试其他数组时,让 Agent只修改代码中的固定数组常量。每组测试结束后刷新页面,从初始状态完整单步到完成;最后再恢复默认数组。
| 验收项 | 操作 | 通过标准 |
|---|---|---|
| 默认固定数组 | 使用 [5, 1, 4, 2, 8] 完整单步 | 最终为 [1, 2, 4, 5, 8],比较位置和有序区按轮次变化 |
| 重复数字 | 将固定数组改为 [4, 2, 4, 1] | 最终为 [1, 2, 4, 4],相等元素比较时不交换 |
| 已排序数组 | 将固定数组改为 [1, 2, 3, 4, 5] | 数组顺序不变,页面能够正常到达完成状态 |
| 当前比较 | 逐步观察每一对元素 | 每次只突出未排序区中的一对相邻元素,不同时突出无关元素 |
| 有序区 | 观察每轮最后一次比较之后的页面 | 右侧有序区每轮扩大,未提前把未确认元素标为有序 |
| 单步状态 | 缓慢点击,再尝试连续点击 | 一次点击只推进一个状态,不跳步、不越界 |
| 重置完整性 | 在比较、交换、单轮结束和完成状态分别重置 | 数组、索引、轮次、有序区和按钮状态全部回到起点 |
由于必做版没有自定义输入,空输入、非法字符和数量过多不属于本轮验收。以后真正实现自定义输入时,再为这些新入口补边界测试,不能拿尚不存在的功能拖长第一版。
再做课堂与离线验收
算法结果正确,不代表课堂上就能用。把页面投到真实大屏,站到教室后排看一次。
| 验收项 | 通过标准 |
|---|---|
| 投影可读性 | 后排能看清数字,当前比较与有序区可以被明显区分 |
| 暂停思考 | 每次单步后页面保持不动,学生有时间判断是否交换 |
| 操作稳定 | 单步和重置位置稳定,点击后页面不跳动,文字不互相遮挡 |
| 重置完整 | 演示到任意位置都能一键回到同一组固定数组的起点 |
| 断网运行 | 断开外网后双击 index.html,全部必做功能仍然可用 |
| 外部依赖 | Agent 检查源码,确认没有 CDN、远程字体、接口和远程图片请求 |
断网验收要真的做一次。不要只听 Agent 说“理论上可以”,也不要用仍在缓存资源的开发服务器代替本地文件。关闭页面、断开外网、重新双击 index.html,再完整走一轮单步和重置。
全部通过后,让 Agent 恢复默认固定数组,说明最终差异,再提交经过验收的 Git 节点。 text
老师已经完成算法、按钮、投影和断网验收,结果通过。
请先确认固定数组已经恢复为 [5, 1, 4, 2, 8],并检查:
1. Git 差异只包含本项目预期文件。
2. 必做仍然只有固定数组、单步、重置、当前比较和有序区。
3. 没有外部依赖、敏感信息和临时测试代码。
4. PRD.md 与最终实现一致。
请先解释最终差异,再提交一个“必做版验收通过”的 Git 节点,
最后报告提交信息和当前 Git 状态。不要推送到未经确认的远程仓库。把页面放进 10 分钟课堂活动
工具做完后,还要证明它服务于观察、预测和讨论,而不是让学生看一段热闹动画。
| 时间 | 老师做什么 | 学生做什么 |
|---|---|---|
| 0—1 分钟 | 展示固定数组,提出“第一步比较谁” | 指出第一对相邻元素 |
| 1—3 分钟 | 点一次单步,只显示当前比较 | 先预测是否交换,并说明理由 |
| 3—5 分钟 | 再点一步显示结果,继续推进两到三对 | 核对预测,口头描述“大于才交换” |
| 5—7 分钟 | 完成第一轮,指向右侧有序区 | 解释为什么本轮最大值已经归位 |
| 7—9 分钟 | 继续到全部完成,中途随时停在单步状态 | 轮流说出当前比较对象和有序区范围 |
| 9—10 分钟 | 在黑板给出另一组固定数据 [3, 1, 3, 2] | 不操作页面,预测第一轮结果并迁移刚才的规律 |
最后一分钟使用另一组数据,但不需要为页面增加输入框。学生能离开原数组继续解释规律,才说明可视化帮助他们理解了状态变化,而不是记住了某一段动画。
选做功能要另开一轮
必做版提交后,如果真实课堂确实需要老师腾出双手,再把自动播放、暂停、继续和速度调节写成新的 PRD;如果学生需要反复尝试不同数据,再单独评估自定义输入及其空值、非法字符和数量限制。
这些都是选做,不是本篇的完成条件。新增任何一项,都要重新经历“Agent 先解释、老师确认、分阶段修改、单独验收、Git 存档”,不能把已经通过的必做版一次改成无法定位问题的大杂烩。
这个项目不保存业务数据,因此不需要数据库备份。页面刷新后的演示状态也没有保留价值,但 index.html、PRD 和验收通过的代码仍然需要 Git 保护。Git 在这里保存的不是学生数据,而是老师已经验证过的教学工具版本。
第一次迁移到这里就完成了。成熟的 Vibe Coding 不是每次都把系统做得更大,而是知道什么时候应该删掉后端、数据库和登录,把一个教学目标做清楚、验收到位。
下一篇,我们会从“不保存数据”的单 HTML 再走一步,做一个数据留在老师自己电脑里的机房故障台账。那时需要重新判断数据放在哪里、怎样备份,以及什么时候才值得升级成多人共享的完整 Web 项目。
封面
