无法回溯以使用递归 javascript 数独求解器

Posted

技术标签:

【中文标题】无法回溯以使用递归 javascript 数独求解器【英文标题】:Can't get backtrack to work on recursive javascript sudoku sovler 【发布时间】:2021-08-12 18:18:01 【问题描述】:

我绞尽脑汁,但看不出哪里出了问题,从控制台日志看来,回溯无法正常工作是个问题,我认为这与我的方式有关正在使用位置对象,我们将不胜感激,

它一直有效,直到回溯应该起作用,我可以看到它确实回溯了 6 次,但该位置实际上并没有返回并改变以前的数字

let grid = [];

const solve = function (pos) 
  while (pos.x < 9 && pos.y < 9 && grid[pos.x][pos.y].value) 
    pos = incrementPos(pos);
   // skip non-empty cells
  if (pos.y == 9) return true;

  for (let m = 1; m < 10; m++) 
    grid[pos.x][pos.y].value = m;
    console.log(pos, m);
    if (isValid(m, pos)) 
      if (solve(incrementPos(pos))) 
        return true;
      
    
  
  console.log("start backtrack", pos);
  grid[pos.x][pos.y].value = "";
  return false;
;

function isValid(n, pos) 
  let valid = true;
  let row = checkRow(n, pos);
  let col = checkCol(n, pos);
  let block = checkBlock(n, pos);
  if (!row || !col || !block) 
    return false;
   else 
    return true;
  


function checkBlock(n, pos) 
  let startX = parseInt(pos.x / 3) * 3;
  let startY = parseInt(pos.y / 3) * 3;

  for (let x = startX; x < startX + 3; x++) 
    for (let y = startY; y < startY + 3; y++) 
      if ((grid[x][y].value === n) & (x !== pos.x) & (y !== pos.y)) 
        return false;
      
    
  
  return true;


function checkRow(n, pos) 
  for (let t = 0; t < 9; t++) 
    if (grid[t][pos.y].value === n && t !== pos.x) 
      return false;
    
  
  return true;


function checkCol(n, pos) 
  for (let t = 0; t < 9; t++) 
    if ((grid[pos.x][t].value === n) & (t !== pos.y)) 
      return false;
    
  
  return true;


function incrementPos(pos) 
  if (pos.x < 8) 
    pos.x++;
   else 
    pos.y++;
    pos.x = 0;
  

  return pos;


const initGrid = function () 
  for (let x = 0; x < 9; x++) 
    let col = [];

    for (let y = 0; y < 9; y++) 
      let el = ;
      el.locked = false;
      el.value = "";
      el.location = document.querySelector("#r" + (y + 1) + "c" + (x + 1));
      col.push(el);
    

    grid.push(col);
  
  displayGrid();
;

const displayGrid = function () 
  for (let x = 1; x < 10; x++) 
    for (let y = 1; y < 10; y++) 
      document.querySelector("#r" + y + "c" + x).textContent =
        grid[x - 1][y - 1].value;
    
  
;

【问题讨论】:

没有简单的方法来运行这段代码,而且它太复杂以至于无法看清。也许您可以使用所需的 html/CSS 创建一个工作代码 sn-p,其中包括一个显示问题的示例数独。 嗨詹姆斯,我确定我已经在 J​​SFiddle 上创建了:jsfiddle.net/87qnoyum/1 【参考方案1】:

我真的不知道你在做什么,这太多了,但是我看不出你实际上在哪里重置位置。我正在寻找这样的东西:

const getBlock = (block) => 
  if (block === 9) 
    return true
  
  // you can use a total variable here to try it a couple of times before backtracking
  const valid = false

  ...

  if (valid) 
    getBlock(++block)
   else 
    getBlock(--block)
  

该代码根本不完美,但它只是为了向您展示这个想法,如果它有效,您应该增加块,并且经过几次迭代之后您找不到另一个块,您应该重置块返回上一个并重试。回溯的结果是,如果您在控制台记录块,您应该会看到如下内容: 1 -> 2 -> 3 -> 4 -> 3 -> 4 -> 5 -> 4 -> 3 -> 4 -> 5 - > 6 -> ... 来来回回,直到最终找到解决方案。

在您自己的代码中,我希望它是这样的:

if (solve(incrementPos(pos)))           
  return true
 else 
  solve(decrementPos(pos)) // or something
  // otherwise you're not actually backtracking

旁注,您可以使用模算术而不是循环。如果您知道自己处于特定块中,则可以立即验证/无效并检查值是否存在于相关行/列/对角线中而没有任何循环。只是一个提示。

【讨论】:

谢谢!你是对的,我所要做的就是在返回 false 之前添加一个递减 pos 并且这解决了它。我是 *** 的新手,但我会尽快弄清楚如何选择这是正确的答案,再次感谢您 更新:“工作”原来还为时过早,不幸的是更新后的代码现在改变了预设元素,它回到了绘图板

以上是关于无法回溯以使用递归 javascript 数独求解器的主要内容,如果未能解决你的问题,请参考以下文章

Java中的数独求解器,使用回溯和递归

优化回溯算法求解数独

Gui 可视化递归回溯数独

数独回溯 无效数独

求解数独的回溯算法

数独求解器回溯算法不起作用