You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为回溯法求解数独的递归函数设置setTimeout延迟执行?

数独回溯求解器的可视化延迟问题

问题描述

我想展示回溯算法求解数独棋盘的过程,但不知道怎么让递归的solveBoard函数每隔500ms才执行一次。直接在函数里加setTimeout后,求解器完全失效,所有位置都被填成了9。首次调用是通过点击事件触发的,相关代码如下:

原求解函数代码

function solveBoard(board) {
// 我试过把下面的代码都包在setTimeout里,但求解器会失效,所有位置都填9
    let empty = findEmpty(board);
    if (!empty) return true;
    let row = empty[0];
    let col = empty[1];
    for (let i = 1; i < 10; i++) { 
        board[row][col] = i;
        console.log(board[row][col]);
        document.getElementById(`${row}-${col}`).value = i;
        if (checkValid(board, row, col)) {
            if (solveBoard(board)) {
                return true;
            }
        }
        board[row][col] = 0;
    }
    return false;
}

触发代码

solveBtn.addEventListener("click", () => {
    solveBoard(boardArray);
});

问题原因

直接套setTimeout会破坏回溯的同步逻辑:

  • 递归原本是同步执行,每一步的验证、回溯都依赖上一步的结果,但setTimeout会把代码放到异步队列,导致还没等当前数字验证完成,就开始循环下一个数字,甚至递归调用下一层。
  • 异步函数里的return无法被上一层递归捕获,导致回溯的终止条件失效,最终所有位置都会被循环到最后一个数字9。

解决方案

把solveBoard改成异步函数,用async/await配合setTimeout实现延迟,确保每一步都等待延迟完成后再继续执行:

修改后的代码

// 封装一个延迟函数
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function solveBoard(board) {
    let empty = findEmpty(board);
    if (!empty) return true;
    let row = empty[0];
    let col = empty[1];

    for (let i = 1; i < 10; i++) { 
        // 填充当前数字并更新UI
        board[row][col] = i;
        document.getElementById(`${row}-${col}`).value = i;
        // 等待500ms
        await delay(500);

        if (checkValid(board, row, col)) {
            // 递归调用,等待递归完成
            if (await solveBoard(board)) {
                return true;
            }
        }
        // 回溯,清空当前位置并更新UI
        board[row][col] = 0;
        document.getElementById(`${row}-${col}`).value = "";
        // 回溯时也加延迟,让过程更清晰
        await delay(500);
    }
    return false;
}

// 修改触发事件,适配异步函数
solveBtn.addEventListener("click", async () => {
    await solveBoard(boardArray);
});

关键改动说明

  • 延迟函数:用Promise封装setTimeout,让await可以等待延迟完成,保证步骤的顺序执行。
  • 异步递归:把solveBoard声明为async函数,递归调用时用await等待结果,确保上一层递归能正确捕获返回值,维持回溯的逻辑正确性。
  • UI同步:填充和回溯操作后都更新UI并等待延迟,让可视化过程连贯可观察。
  • 触发逻辑:点击事件回调改为async,等待solveBoard执行完成,避免异步操作导致的逻辑混乱。

这样修改后,就能看到数独求解的每一步过程,每隔500ms更新一次,同时保持回溯算法的正确性。

内容的提问来源于stack exchange,提问作者plauwh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:30:59