第 8 周:2048 网页游戏逻辑与最终验收

本周目标

本周完成后,应能够:

  • 在第 7 周静态页面基础上接入第 6 周的 2048 核心逻辑
  • 使用 JavaScript 数据驱动 DOM 渲染棋盘
  • 使用键盘方向键控制棋盘移动
  • 正确处理有效移动、无效移动、随机生成数字和重新开始
  • 正确累计当前分数,并使用本地存储保存最高分
  • 判断胜利和失败状态,避免游戏结束后继续修改状态
  • 为核心规则设计并执行明确的测试用例
  • 整理代码结构、Git 提交、README 和 GitHub 项目说明
  • 独立讲解 2048 的状态、移动算法和渲染流程

项目基础

本周从第 7 周完成的 2048 静态页面继续开发,不重新设计页面结构。第 7 周的 HTML 和 CSS 作为视觉基础,本周重点是 JavaScript 状态管理、DOM 渲染、交互流程、测试和最终交付。

需要掌握的知识点

状态建模

  • 使用二维数组表示 4×4 棋盘
  • 使用变量保存当前分数、最高分和游戏状态
  • 区分数据状态和页面显示
  • 页面只根据数据渲染,不把 DOM 当作游戏状态来源
  • 设计初始化、移动、生成数字、胜负判断和重新开始的状态流转

逻辑复用

  • 复用第 6 周的 moveLeft()、moveRight()、moveUp() 和 moveDown()
  • 复用第 6 周的 hasTarget() 进行胜利判断
  • 复用第 6 周的 isGameOver() 进行失败判断
  • 复用空位查找、随机索引和棋盘复制函数
  • 保持核心移动规则不变,避免在 DOM 接入阶段改坏算法

DOM 渲染

  • 根据棋盘二维数组生成或更新 16 个格子
  • 根据数字值设置方块文本和样式类
  • 当前分数、最高分和状态提示由数据统一驱动
  • 渲染函数只负责显示,不负责修改游戏规则
  • 处理数字位数变化时的字体大小和居中问题

输入与游戏流程

  • 使用键盘方向键触发四个方向移动
  • 根据移动结果中的 changed 判断是否生成新数字
  • 无效移动不生成新数字、不增加分数
  • 重新开始时重置棋盘、当前分数和游戏状态
  • 游戏结束后阻止继续移动
  • 避免重复绑定键盘事件

分数与本地存储

  • 仅在数字合并时增加当前分数
  • 每次合并增加新方块对应的数值
  • 当前分数变化后更新页面显示
  • 使用 localStorage 保存和恢复最高分
  • 首次访问、存储值不存在或存储值异常时使用合理默认值
  • 重新开始不清空最高分

胜负状态

  • 出现 2048 方块时显示胜利状态
  • 棋盘填满且不存在可合并数字时显示失败状态
  • 胜利和失败提示应显示在第 7 周预留的状态区域
  • 游戏结束后按钮仍可重新开始
  • 胜负判断应发生在有效移动并生成新数字之后

测试与调试

  • 为移动函数准备确定的棋盘输入和预期输出
  • 分别测试正常情况、边界情况和无效操作
  • 测试分数累计、最高分恢复、胜利、失败和重新开始
  • 记录实际结果与预期结果的差异
  • 修复问题后重新执行全部规则测试
  • 最终提交前移除临时测试入口和调试日志

代码与项目整理

  • 将状态、移动、渲染、输入和存储逻辑合理拆分
  • 函数和变量名称能够表达实际用途
  • 删除重复代码、无用资源和临时文件
  • README 包含项目介绍、功能、运行方式、操作方法和截图
  • 最终代码推送至 GitHub

必做任务

  1. 复查第 7 周页面结构,确认分数、棋盘、状态提示和按钮都有可操作的 DOM 标记。
  2. 整理第 6 周核心函数,复制或模块化接入第 8 周项目。
  3. 建立游戏状态对象或状态变量,保存棋盘、当前分数、最高分和游戏状态。
  4. 实现 renderBoard(),根据二维数组更新 4×4 棋盘。
  5. 实现 renderScore() 和 renderStatus(),更新分数和状态提示。
  6. 使用键盘方向键调用四向移动函数。
  7. 仅在有效移动后生成新数字,并重新渲染页面。
  8. 实现当前分数累计,并保证无合并时分数不增加。
  9. 使用 localStorage 保存并恢复最高分。
  10. 实现重新开始按钮,重置棋盘、当前分数和状态提示。
  11. 实现胜利和失败判断。
  12. 执行规则测试、交互测试和刷新恢复测试。
  13. 整理代码、README、截图和 Git 提交记录。
  14. 准备一次 5 分钟项目讲解。

功能验收

  • 使用 HTML、CSS 和原生 JavaScript 开发,未使用游戏框架
  • 使用第 7 周静态页面作为视觉基础
  • 使用 4×4 棋盘,通过键盘方向键控制移动
  • 开始游戏时随机生成两个数字方块
  • 仅在有效移动后于空白位置生成新数字
  • 相同数字按照 2048 规则合并并正确累计分数
  • 支持胜利、失败判定和重新开始
  • 使用本地存储保存并恢复最高分

规则测试

  • [2, 2, 2, 2] 向左移动后得到 [4, 4, 0, 0]
  • [4, 4, 8, 0] 向左移动后得到 [8, 8, 0, 0]
  • [2, 2, 4, 0] 向左移动后得到 [4, 4, 0, 0],不能连续合并为 8
  • [4, 0, 4, 4] 向左移动后得到 [8, 4, 0, 0]
  • 向右、向上、向下移动时遵守相同合并规则
  • 仅移动位置但未合并时,分数不增加
  • 棋盘状态没有变化时,不生成新数字
  • 棋盘填满且不存在可合并的相邻数字时,游戏失败
  • 出现 2048 方块时,显示胜利状态
  • 重新开始后,棋盘和当前分数正确重置
  • 刷新页面后,最高分能够正确恢复

工程验收

  • 使用 Git 管理项目,提交记录能够体现主要开发过程
  • 最终代码已推送至 GitHub
  • 仓库包含项目介绍、运行方式、操作说明和截图
  • HTML、CSS 和 JavaScript 文件职责清晰
  • 核心移动和合并逻辑已拆分为独立函数
  • DOM 渲染、事件输入、本地存储和状态判断职责清晰
  • 页面无明显错位、遮挡、溢出或控制台报错
  • 能够独立讲解棋盘状态、移动合并算法和渲染流程

视觉验收

  • 页面仍保持第 7 周蓝湖设计图还原效果
  • 动态数字变化不会导致棋盘格子尺寸跳动
  • 当前分数、最高分和状态提示变化时布局稳定
  • 重新开始和胜负状态不会破坏页面结构
  • 桌面端和移动端布局均可正常操作
  • 已提供最终页面截图

Git 提交要求

本周至少通过独立提交体现以下开发步骤:

  • 接入第 6 周核心移动逻辑
  • 建立游戏状态和初始化流程
  • 完成棋盘 DOM 渲染
  • 完成键盘方向键控制
  • 完成分数和最高分逻辑
  • 完成胜利、失败和重新开始流程
  • 完成规则测试和问题修复
  • 完成 README、截图和最终整理

本周产出

  • 2048 最终可玩版本
  • 完整的规则测试记录
  • 最高分本地存储实现
  • 最终页面截图
  • 包含说明和截图的 GitHub 仓库
  • 一份阶段一知识复盘和待补强清单
  • 两个阶段项目的口头讲解提纲