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

JavaScript for循环let声明致数独求解数组修改行为异常问题

问题描述

编写数独谜题求解算法时遇到异常行为:

  • 第一版代码运行时无报错,但会直接修改传入的原始数组
  • 给for循环的row、col变量添加let关键字声明后,代码不再修改传入的puzzle形参数组,无法理解let关键字导致该行为差异的原因
    复现代码如下:
test = [
  [8, 0, 6, 0, 1, 0, 0, 0, 0],
  [0, 0, 3, 0, 6, 4, 0, 9, 0],
  [9, 0, 0, 0, 0, 0, 8, 1, 6],
  [0, 8, 0, 3, 9, 6, 0, 0, 0],
  [7, 0, 2, 0, 4, 0, 3, 0, 9],
  [0, 0, 0, 5, 7, 2, 0, 8, 0],
  [5, 2, 1, 0, 0, 0, 0, 0, 4],
  [0, 3, 0, 7, 5, 0, 2, 0, 0],
  [0, 0, 0, 0, 2, 0, 1, 0, 5]
]

let result = solve(test)
console.log(result)
printPuzzle(test)

function solve(puzzle) {

  for (row = 0; row < 9; row++) {
    for (col = 0; col < 9; col++) {

      if (puzzle[row][col] === 0) {

        for (number = 1; number < 9; number++) {

          if (isValidPlacement(puzzle, number, row, col)) {

            puzzle[row][col] = number

            if (solve(puzzle)) {
              return true
            } else {
              puzzle[row][col] = 0
            }

          }

        }

        return false

      }

    }
  }

  return true

}
问题原因

不加let/const声明直接赋值的变量,会自动成为全局作用域共享变量,这是两种行为差异的核心原因:

  • 无变量声明的版本中,所有递归调用的solve函数共用同一套全局的row/col/number变量。递归进入下一层求解时,会直接覆盖全局的循环索引值,等回溯返回上一层时,row/col已经不是当初填数的位置坐标,回溯逻辑puzzle[row][col] = 0无法命中之前填入的数字,不能完成状态回退,最终原始数组会残留递归过程中填入的所有临时值,表现为“传入的数组被修改”。
  • 加let声明循环变量的版本中,let会为每一层循环、每一次函数调用生成独立的块级作用域变量,各层递归的row/col/number互不干扰。回溯时能准确定位到之前填数的格子,执行回退操作把临时填入的数字改回初始的0,整个递归流程跑完后,数组状态和传入时完全一致,看起来就像“没有修改传入的形参数组”,本质是所有临时修改都被正确回滚了。

另外代码还存在一个逻辑bug:最内层枚举填数的循环条件写的是number < 9,只会尝试1-8共8个数字,漏掉了数字9,需要改成number <= 9才能正常求解数独。

修复后的核心逻辑
function solve(puzzle) {
  // 所有循环变量用let声明,绑定独立块级作用域
  for (let row = 0; row < 9; row++) {
    for (let col = 0; col < 9; col++) {
      if (puzzle[row][col] === 0) {
        // 修正循环边界,覆盖1-9所有可填数字
        for (let number = 1; number <= 9; number++) {
          if (isValidPlacement(puzzle, number, row, col)) {
            puzzle[row][col] = number
            if (solve(puzzle)) {
              return true
            } else {
              // 回溯时用当前作用域的独立坐标,准确回退状态
              puzzle[row][col] = 0
            }
          }
        }
        return false
      }
    }
  }
  return true
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:01:11