我正在尝试在javascript中创建一个回溯算法的实时演示(使用简单的前向检查)。我已经以递归的形式对算法进行了下调,但现在我不得不尝试使用javascript的setTimeout
或setInterval
来设置动画,我假设它需要我转换递归解决方案一个迭代的。这是函数(重写为更一般):
function solve(model) {
if (model.isSolved()) return true;
var chosen = chooseVariable(model); //could be random or least constrained
var domain = model.getDomain(chosen);
var i, assn;
for (i = 0; i < domain.length; i++) {
assn = domain[i];
model.set(chosen, assn);
if (solve(model)) return true;
else model.undo();
}
return false;
}
正如你所看到的,我已经做到这一点,模型可以撤消它自己的动作,而不是在每个递归级别都有一个单独的动作堆栈或克隆模型。有没有办法将上面的函数转换为可以与setTimeout
或setInterval
一起使用的函数?我是否必须显着更改模型/添加另一个堆栈以跟踪所选变量/尝试的分配?我需要一个带变异变量的闭包吗?我主要是在寻找伪代码,指出我正确的方向。
答案 0 :(得分:1)
我假设这需要我将递归解决方案转换为迭代解决方案。
不,反过来说。你的某些部分仍然是迭代的(for
- 循环)。
您必须使步骤异步,以便每个步骤都进行一次回调,该回调在动画完成后触发,您可以继续。由于您希望为每个迭代步骤设置动画,因此您必须使它们与类似递归的回调异步 - continuation passing style。
以下是:
function solve(model, callback) {
if (model.isSolved())
return callback(true);
var chosen = chooseVariable(model); // could be random or least constrained
var domain = model.getDomain(chosen);
var i = 0, assn;
(function nextStep() {
if (i < domain.length) {
assn = domain[i];
model.set(chosen, assn);
solve(model, function(solved) {
if (solved)
callback(true);
else {
model.undo();
i++;
nextStep();
}
});
} else
callback(false);
})();
}
现在你可以通过在你需要的地方引入setTimeout
来简单地使这个递归变量异步(通常在显示model
状态之后):
function solve(model, callback) {
if (model.isSolved())
return callback(true);
var chosen = chooseVariable(model); // could be random or least constrained
var domain = model.getDomain(chosen);
var i = 0, assn;
(function nextStep() {
if (i < domain.length) {
assn = domain[i];
model.set(chosen, assn);
solve(model, function(solved) {
if (solved)
callback(true);
else {
model.undo();
i++;
setTimeout(nextStep, 100);
}
});
} else
setTimeout(callback, 100, false);
})();
}
答案 1 :(得分:0)
您可以使用例如deferreds异步编程。 jQuery提供了延迟的实现,你可以看看这个使用超时的例子:
http://api.jquery.com/deferred.promise/#example-0
当然,您只需要一次超时,它总能解决(成功)。