二维数组赋值后未更新:为何board[y][x]更新但board本身无变化?
问题原因与解决方案
你的代码核心问题是未使用let/const声明变量,导致全局变量被递归调用意外覆盖,进而造成控制台输出的迷惑现象。
具体问题点
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已经不是当初赋值的位置了。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
相关产品推荐
相关产品推荐

