如何使用递归生成器为Boggle求解算法的执行步骤添加动画效果
Boggle求解算法动画实现方案
问题根源
- 原生成器版本仅对根递归调用执行了一次
next(),所有嵌套的yield逻辑未按预期执行 - JS主线程同步执行时DOM更新会被批量合并,不会触发逐帧渲染,因此看不到中间状态
- 直接使用
setTimeout未做执行顺序控制,导致高亮/取消高亮操作时序错乱
解决方案
采用异步递归+延迟等待的方案,控制每一步操作的执行时序,保证浏览器有足够时间渲染DOM状态变化。
工具函数与核心代码
// 延迟工具函数,控制动画速度 const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // 动画间隔,单位毫秒,可根据需求自行调整 const ANIMATION_SPEED = 100; export const findWords = async (matrix) => { const words = []; const iterate = async (i, j, word, visited, color) => { if (matrix[i] && matrix[i][j]) { const cellKey = `${i}_${j}`; if (!visited[cellKey]) { visited[cellKey] = true; word += matrix[i][j]; const cellIndex = j + size * i; // 高亮当前单元格 inputs[cellIndex].classList.add(color); // 等待浏览器完成高亮渲染 await delay(ANIMATION_SPEED); if (trie.find(word).length) { if (trie.contains(word)) { words.push(word); // 找到单词时可额外增加停留时间,突出展示 await delay(ANIMATION_SPEED * 2); } const moves = movements(i, j); for (let move of moves) { const { row, column } = move; await iterate( row, column, word, { ...visited }, column % 2 === 0 ? "blue" : "red" ); } } // 所有子路径遍历完成后再取消当前单元格高亮 inputs[cellIndex].classList.remove(color); // 等待取消高亮的渲染完成 await delay(ANIMATION_SPEED); } } }; for (let i = 0; i < matrix.length; i++) { for (let j = 0; j < matrix[i].length; j++) { await iterate(i, j, "", {}, j % 2 === 0 ? "blue" : "red"); } } return words; };
调用方式调整
原同步调用逻辑需要改为异步调用,示例如下:
// 原同步调用写法 // const result = findWords(matrix); // 改为异步调用写法 findWords(matrix).then(foundWords => { // 单词查找完成后的后续逻辑 console.log("查找完成,找到的单词:", foundWords); })
优化建议
- 若需要更快的动画速度,可降低
ANIMATION_SPEED数值,最低可设为16(对应浏览器单帧渲染时长) - 若需要突出展示找到的单词,可在
trie.contains(word)分支中为当前路径单元格额外添加专属高亮类,延长展示时长 - 避免在递归过程中重复查询DOM元素,可提前将单元格DOM引用缓存为数组,提升执行效率
内容的提问来源于stack exchange,提问作者hakaman
相关产品推荐
相关产品推荐

