我编写了一个 Javascript 程序,它使用隐性技术来解决益智游戏。
也就是说,函数 solvePuzzle()
调用函数 solvePuzzle()
来解决更简单的难题,直到找到解决方案。它改变了棋盘对象中的数据。
我还有一个函数 board.draw()
可以显示拼图的状态
它按照我的预期绘制了初始游戏板,一旦我单击按钮(触发 solvePuzzle()
的执行),它就会按照我的预期再次绘制已解决的游戏板。
但是,我想展示中间的谜题状态。
最初,我在 solvePuzzle()
函数中插入了对 board.draw()
的调用,但这没有执行任何操作。
研究 Javascript 动画让我创建并执行这个函数
function animationLoop(timestamp) {
// 1 - Clear
ctx.clearRect(0, 0, c.width, c.height);
// 2 Draw
board.draw();
pieces.draw();
// call again mainloop after 16.6 ms (60 frames/s)
requestId = requestAnimationFrame(animationLoop);
}
requestId = requestAnimationFrame(animationLoop);
我相信这是有效的,因为这是我现在调用 board.draw() 的唯一地方,它显示初始状态,并在我按下求解按钮后切换到显示已求解的状态,但是......仍然没有显示中间状态.
然后我假设问题是解决方案太快了,以至于它发生在帧之间,但通过将这个“延迟”放在solvePuzzle 中来打消这一点
if (solutionCount%1000 == 0) {
confirm("Are you sure you wish to continue?");
};
我现在假设solvePuzzle 必须在animationLoop 进行之前运行完成。
这个假设正确吗?
如果是这样,我该如何解决我的问题?
我想我需要在每个状态下不断结束和恢复我的隐居功能,但无法弄清楚我该如何做到这一点。
注意:我确信动画正常工作的另一个原因是,如果我用类似
的语句从控制台更改棋盘board.layout[7].available = true;
对显示进行了预期的更改
最佳答案
JavaScript 是单线程的,并且与 UI 更新共享该线程。因此,当一个函数从顶层启动时,浏览器不会执行任何其他操作,直到该函数退出。这包括动画帧 - 只要页面线程空闲并且可以安排动画,动画就会发生,但在代码执行时则不能。
如果你的计算需要时间,你需要将其分成离散的部分,如果你想更新 UI,则需要让浏览器在中间呼吸(通常使用 setTimeout(f, 0)
,或者在 >requestAnimationFrame
处理程序)。
另一种可能性是使用 Web Workers。它们是一种在单独的线程中启动 JavaScript 的方法。然而,它们根本无法与 DOM 交互,只能通过消息进行通信。因此,您可以在 Web Worker 中启动计算,然后从 Worker 定期向您的主 JS 代码发送消息,以便使其根据结果(临时结果和最终结果)更新 DOM。
感谢 Alexander O'Mara 和 Kaiido 让我涵盖了我忘记的案例。
关于Javascript 动画和递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33772511/