【问题标题】:Sudoku solver with Javascript使用 Javascript 的数独求解器
【发布时间】:2020-06-10 17:38:06
【问题描述】:

我尝试使用 Javascript 构建数独求解器。该代码确实解决了它,但仍然存在一些空白点。 我使用 Javascript、回溯和递归。

在第一个函数中,我检查一个空白点 (0) 上的数字是可能的,在第二个函数中,我调用第一个函数来检查空白点并尝试在该点放置一个介于 1 和 9 之间的数字

p>

谁能看出我做错了什么?

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


function possible(y, x, n) {
  for (let i = 0; i <= 8; i++) {
    if (userInput[y][i] === n) {
      return false;
    }
  }
  for (let i = 0; i <= 8; i++) {
    if (userInput[i][x] === n) {
      return false;
    }
  }
  let xSquare = Math.floor(x / 3) * 3;
  let ySquare = Math.floor(y / 3) * 3;
  for (let i = 0; i <= 2; i++) {
    for (let j = 0; j <= 2; j++) {
      if (userInput[ySquare + i][xSquare + j] === n) {
        return false;
      }
    }
  }
  return true;
}


function solve() {
  for (let y = 0; y <= 8; y++) {
    for (let x = 0; x <= 8; x++) {
      if (userInput[y][x] === 0) {
        for (let n = 1; n <= 9; n++) {
          if (possible(y, x, n)) {
            userInput[y][x] = n;
            solve();
          }
        }
      }
    }
  }
}

【问题讨论】:

  • 为什么solve 在最里面的 if 中调用自己,而不是前进到下一个 x?
  • 这似乎遗漏了非常重要的逻辑。对于这种类型的解决方案,您确实需要能够在遇到死胡同时回溯。您还需要一些方法来检查您是否已完成拼图。

标签: javascript recursion backtracking sudoku


【解决方案1】:

您正在编写回溯算法,但这里没有回溯。当前算法假设每个猜测的值都是完美的——如果有任何不完美(这是保证的,因为这些值是从 1 到 9 依次猜测的),则无法取得进展。

要回溯,您需要将无法扩展为已解决状态的单元格归零,并在单元格的所有可能性都耗尽时将 false 返回到父状态。

另外,最好让函数接受参数和返回值,而不是改变全局状态。

应用这些最小的修改会产生以下结果。仍有改进的空间;例如,solve 函数必须反复“寻找”下一个空方格。

function possible(board, y, x, n) {
  for (let i = 0; i < 9; i++) {
    if (board[y][i] === n || board[i][x] === n) {
      return false;
    }
  }

  const xSquare = Math.floor(x / 3) * 3;
  const ySquare = Math.floor(y / 3) * 3;

  for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
      if (board[ySquare+i][xSquare+j] === n) {
        return false;
      }
    }
  }

  return true;
}

function solve(board) {
  for (let y = 0; y < 9; y++) {
    for (let x = 0; x < 9; x++) {
      if (board[y][x] === 0) {
        for (let n = 1; n <= 9; n++) {
          if (possible(board, y, x, n)) {
            board[y][x] = n;
            
            if (solve(board)) return board;
          }
        }
        
        board[y][x] = 0;
        return false;
      }
    }
  }
  
  return board;
}

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

console.log(solve(puzzle).map(e => "" + e));

【讨论】:

  • 谢谢!仍然很难理解这一点,但我仍在学习很多东西!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
相关资源
最近更新 更多