基础三消逻辑需用二维数组管理状态,仅检测横纵连续3相同值并标记,下落时从底向上遍历填充,消除后重新扫描但限制迭代次数,动画用requestAnimationFrame+CSS transform批量更新,避免setTimeout和重排。

怎么用纯 HTML + CSS + JavaScript 实现基础三消逻辑
不能只靠 div 堆格子,核心是“状态管理 + 消除判定 + 下落填充”三步闭环。浏览器原生能力完全够用,不需要框架或 Canvas——但得放弃“逐帧动画”幻想,用 DOM 批量更新 + requestAnimationFrame 控制节奏。
- 棋盘用二维数组(如
board[i][j])存颜色/类型编号,别直接操作 DOM 节点判断匹配 - 消除检测只扫行和列:连续 3 个相同值就标记,**不递归找 L 形或 T 形**(那是进阶需求,基础版先砍掉)
- 下落必须从底部向上处理,否则上层空洞没被填上;用
for (let row = height - 2; row >= 0; row--)遍历更安全 - 每次消除后要重新扫描——因为新下落可能拼出新 3 连,但别无限循环,加个最大迭代次数(比如 5 层)防卡死
为什么 setTimeout 做动画会卡顿甚至错位
DOM 更新不是即时生效的,setTimeout 时间不准、任务队列堆积,导致“消除→下落→渲染”不同步。常见现象:方块闪一下又回原位、两个消除组叠在一起没分开。
- 改用
requestAnimationFrame驱动每一步:先标记待消除格子,再批量移除对应 DOM 节点,最后统一重绘 - 下落动画用 CSS
transition: transform 0.3s,但必须给每个格子设position: absolute或用 Grid +transform,别用margin-top——它会触发重排 - 关键:所有 DOM 写操作(
classList.remove、style.transform)尽量合并在单次 rAF 回调里,避免强制同步布局
checkMatch() 函数总漏判斜向或跨行组合
标准三消(Match-3)规则里,**官方只认横向和纵向连续 3+,不认对角线**。如果你发现漏判,大概率是循环边界写错了,不是算法问题。
- 横向扫描:对每行
for (let j = 0; j ,比 <code>board[i][j] === board[i][j+1] && board[i][j] === board[i][j+2] - 纵向扫描:对每列
for (let i = 0; i ,比 <code>board[i][j] === board[i+1][j] && board[i][j] === board[i+2][j] - 别在同一个双层循环里混着判——容易 index 越界;先扫行,再扫列,用 Set 存坐标去重(
new Set(['0-2', '0-3', '0-4'])) - 如果真要支持 T/L 形(非标准),得用连通域搜索(DFS/BFS),但性能敏感,小屏手机容易掉帧
生成随机初始棋盘时老出现预设三连
直接用 Math.random() 填值,大概率开局就触发消除,游戏还没开始就结束了。这不是 bug,是概率问题。
立即学习“前端免费学习笔记(深入)”;
- 生成后立刻跑一遍
checkMatch(),有匹配就重做整行/整列——但别整个重刷,太慢;只重生成含匹配的那几格 - 更稳做法:先填满,再对每个位置检查“放这个色会不会形成 3 连”,如果会,换一个色;最多试 5 次,还不行就填默认色(比如 0)
- 注意边界:角落格子只有 2 个邻居,边格子只有 3 个,中心才有 4 个——判断时得动态算邻接方向,别硬写死
i±1, j±1
真正难的不是第一次消除,而是连锁反应中“哪些格子该保留状态、哪些要清空、动画结束时如何精准同步数据与视图”。很多实现崩在这里:DOM 显示已下落,但数组还留着旧值,下一步检测就错乱。动手前先画张表格,把“数据态→动作→DOM 态”的映射写清楚。


















