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

二维数组赋值后未更新:为何board[y][x]更新但board本身无变化?

问题原因与解决方案

你的代码核心问题是未使用let/const声明变量,导致全局变量被递归调用意外覆盖,进而造成控制台输出的迷惑现象。

具体问题点

  1. solve_board中的empty_pos全局变量
    你在solve_board里写了empty_pos = find_empty(board);,没有用let声明,这个变量变成了全局变量。递归调用solve_board时,后续的递归会修改这个全局的empty_pos,上层函数的y、x虽然是之前赋值的,但当你后续查看控制台输出时,empty_pos已经被下层递归修改,导致你误以为board[y][x]更新了但board整体没变化——实际上是你查看的y、x已经不是当初赋值的位置了。

  2. is_valid中的box_start_y和box_start_x全局变量
    同样,这两个变量没有用let声明,属于全局变量,递归过程中会被不同的调用覆盖,破坏数独的校验逻辑。

修改后的代码

const puzzle = [
    [0, 0, 7, 0, 0, 6, 2, 0, 0],
    [1, 0, 0, 8, 9, 0, 7, 6, 0],
    [8, 0, 2, 0, 7, 3, 0, 5, 0],
    [0, 0, 0, 1, 0, 9, 5, 0, 6],
    [0, 1, 0, 0, 0, 0, 0, 8, 0],
    [7, 0, 3, 6, 0, 8, 0, 0, 0],
    [0, 7, 0, 2, 4, 0, 6, 0, 3],
    [0, 4, 1, 0, 6, 7, 0, 0, 5],
    [0, 0, 9, 3, 0, 0, 1, 0, 0]
];

function find_empty(board) {
    for (let y = 0; y < 9; ++y) {
        for (let x = 0; x < 9; ++x) {
            if (board[y][x] === 0) {
                return [y, x];
            }
        }
    }
    return null;
}

function is_valid(board, num, pos) {
    let y = pos[0];
    let x = pos[1];

    // Horizontal checking...
    for (let i = 0; i < 9; ++i) {
        if (board[y][i] === num && x !== i) {
            return false;
        }
    }

    // Vertical checking
    for (let i = 0; i < 9; ++i) {
        if (board[i][x] === num && y !== i) {
            return false;
        }
    }

    // 3*3 box checking
    let box_start_y = (Math.floor(y / 3)) * 3;
    let box_start_x = (Math.floor(x / 3)) * 3;

    for (let i = box_start_y; i < box_start_y + 3; ++i) {
        for (let j = box_start_x; j < box_start_x + 3; ++j) {
            if (board[i][j] === num && y !== i && x !== j) {
                return false;
            }
        }
    }

    return true;
}

function solve_board(board) {
    console.log("start", board);
    let empty_pos = find_empty(board);
    console.log("empty_pos", empty_pos)
    if (empty_pos === null) {
        return board;
    }
        
    let y = empty_pos[0];
    let x = empty_pos[1];

    for (let num = 1; num < 10; ++num) {
        console.log(board)
        if (is_valid(board, num, empty_pos)) {
            console.log(true, num)
            console.log("Before assignment", board[y][x]);
            board[y][x] = num;
            console.log("y", y, ", x", x);
            console.log("After true", board[y][x])
            console.log("After true", board);
            let solved_board = solve_board(board)
            console.log("solved", solved_board);
            if (solved_board !== false) {
                return solved_board;
            }
            console.log(num, "did not work!!")
            board[y][x] = 0;
        }
        console.log(false, num)
    }
    return false;
}

console.log("result", solve_board(puzzle))

关键修改说明

  • 在solve_board中给empty_pos加上let声明,使其成为函数局部变量,避免递归调用时被覆盖。
  • 在is_valid中给box_start_y和box_start_x加上let声明,确保每次校验的是当前位置对应的3x3宫格。

修改后,递归过程中每个函数调用的变量都是独立的,board[y][x]的修改会正确反映到board数组中,控制台输出也会和实际修改一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:20:53