我使用javascript编写了一个小程序来解决河内塔问题。我用了3座DIV塔,给第一座塔加了黑色,其余的我加了白色。当我希望程序交换2个元素时,它基本上会交换适当DIV的属性。该代码可以正常工作,但是我希望每个步骤都可见,并且在当前状态下,从头到尾只是一闪而过。我已经尝试过为每个步骤使用一个按钮,但是它没有起作用,所以setTimeout()了。 (对不起,我的英格兰不好:c)
var from = 1;
var to = 2;
var help = 3;
function swap(from, to){
while (...){
if (...){
while(...){
if (...){
//swaps the properties of the divs
}
}
}
}
}
function hanoi(n, from, to, help){
if (n == 1){
swap(from, to);
}
else{
hanoi(n-1, from, help, to);
swap(from, to);
hanoi(n-1, help, to, from);
}
}
我已经尝试过了,但这只是将闪光灯延迟了2秒:
function hanoi(n, from, to, help){
if (n == 1){
setTimeout(function(){swap(from, to);}, 2000);
}
else{
hanoi(n-1, from, help, to);
setTimeout(function(){swap(from, to);}, 2000);
hanoi(n-1, help, to, from);
}
}
答案 0 :(得分:1)
我强烈建议您检查setTimeout如何与JavaScript事件堆栈一起使用。 Here's an awesome video。
这是您的过程。
hanoi
,如果它通过if检查,则会自动再次调用自身。hanoi
。 hanoi
并创建更多setTimeouts来将swap
的执行发送到webapi。Jonas Wilms's answer说明了解决方法。
答案 1 :(得分:0)
在您的最后一个代码块中,递归函数以递归方式执行,创建所有超时,并且在2秒后所有超时都在不久之后再次回调,这就是为什么它闪烁(in depth explanation)。相反,您还想延迟递归调用:
function hanoi(n, from, to, help){
if (n == 1){
setTimeout(function(){swap(from, to);}, 2000);
} else{
setTimeout(function() {
hanoi(n-1, from, help, to);
swap(from, to);
hanoi(n-1, help, to, from);
}, 2000);
}
}
尽管可行,但是这段代码并不是很漂亮。可视化和延迟循环并不是河内方法的工作。取而代之的是,我会以一种可以中断的方法来编写Hanoi逻辑,然后可以通过重新渲染和延迟的处理函数来调用它。对于发电机来说,这是一个完美的用例:
function* hanoi(n, from, to, help){
if (n == 1){
swap(from, to);
} else{
yield* hanoi(n-1, from, help, to);
swap(from, to);
yield* hanoi(n-1, help, to, from);
}
yield; // Pass execution back to the "runStepByStep" loop, rerendering & delaying happens here
}
处理程序是:
const timer = ms => new Promise(resolve => setTimeout(resolve, ms));
async function runStepByStep(iterator) {
let done = false;
do {
({ done } = iterator.next());
rerender(); // TODO: Implement this
await timer(2000);
} while(!done);
}
runStepByStep( hanoi(10, 0, 2, 1) );