【问题标题】:How to fix: Sudoku solver Stack overflow problem如何解决:数独求解器堆栈溢出问题
【发布时间】:2019-07-02 15:37:39
【问题描述】:

我正在尝试用 Java 创建一个数独求解器,总的来说,我是编程和 Java 的新手。我真的不知道如何处理这种错误。 我不断收到堆栈溢出错误。

我尝试了不同的代码,它们都不起作用,但无论如何这是我最新的:

public class Sudoku {

    private int[][] values;
    private boolean [][] writable;
    private static final int ZERO = 0;
    private static final int SIZE = 9;

    //just a normal constructor that sets which values are changeable and which aren't. only values equal to zero are changeable.
    public Sudoku(int[][] values) {
        this.values = new int[SIZE][SIZE];
        for(int row = 0; row< SIZE ; row++)
        {
            for(int col = 0; col< SIZE; col++)
            {
                this.values[row][col] = values[row][col];
            }
        }

         writable = new boolean[values.length][values[1].length];
         for(int i = 0;i < writable.length;i++)
         {
             for(int j = 0; j<writable[1].length;j++)
             {
                 if(values[i][j] == ZERO)
                 {
                     writable[i][j] = true;
                 }
             }
         }
    }

    public void setValues(int row,int col ,int value) //changes the value if the value was changeable.
    {
        if(writable[row][col])
        {
            values[row][col]= value;
        }

    }

    public int getValue(int row,int col) {
        return values[row][col];
    }

    public boolean isWritable(int row,int col)
    {
        return writable[row][col];
    }
    private boolean ConflictAtRow(int row , int num)
    {
        for(int i = 0;i < SIZE;i++)
            if(getValue(row,i) == num)
                return true;
            return false;
    }
    private boolean ConflictAtCol(int col, int num)
    {
        for(int i = 0;i<SIZE;i++)
            if(getValue(i,col) == num)
                return true;
            return false;
    }
    private boolean ConflictAtBox(int row, int col, int num)
    {
        int r = row - row %3;
        int c = col - col %3;

        for(int i = r;i<r+3;i++)
        {
            for(int j = c;j<c+3;j++)
            {
                if(getValue(i, j) == num && row != i && col != j)
                    return true;
            }
        }
        return false;
    }
    private boolean ConflictAt(int row, int col, int num)
    {
        return ConflictAtBox(row, col, num) && ConflictAtCol(col,num) && ConflictAtRow(row, num);  //line 108
    }

    public boolean solve(int row,int col) 
    {
        int nextRow = (col < 8) ? row:row+1;
        int nextCol = (col +1)%9;
        for (row = nextRow; row < SIZE; row++) {
            for (col = NextCol; col < SIZE; col++) {
                if(isWritable(row,col))
                {
                    for (int num = 1; num <= 9; num++) {
                        if(!ConflictAt(row,col,num)) //line 118
                        {
                            setValues(row,col,num);

                         if(solve(nextRow,nextCol)) //line 122
                             return true;
                         }
                             setValues(row,col,ZERO);

                    }
                }return !ConflictAt(row,col,getValue(row,col)) && 
                  solve(nextRow,nextCol);;

            }

        }return true;
    }

当我运行solve()方法时,我得到堆栈溢出错误

Exception in thread "main" java.lang.StackOverflowError
    at Sudoku.Sudoku.ConflictAt(Sudoku.java:108) 
    at Sudoku.Sudoku.solve(Sudoku.java:118) 
    at Sudoku.Sudoku.solve(Sudoku.java:122) 
    at Sudoku.Sudoku.solve(Sudoku.java:122) 
    at Sudoku.Sudoku.solve(Sudoku.java:122) 
    at Sudoku.Sudoku.solve(Sudoku.java:122) 

等等……

【问题讨论】:

  • 看了一眼,有些疑惑。由于数独板有9*9=81 单元格,递归深度应受限于81;你试过使用调试器吗?
  • 我不知道如何调试我还没有学习调试,但我会检查一下。
  • 从表面上看,实现看起来还不错;我想知道问题是什么。
  • 似乎如果谜题无法解决,该方法返回 false。并成功终止。
  • 也许你的意思是终止成功。

标签: java recursion stack-overflow backtracking sudoku


【解决方案1】:

一旦控件第一次进入solve()方法,并且如果直到第122行所有if条件评估为true,您将再次调用solve()方法。

问题是,每次控件点击这个方法时,就好像它是第一次执行它一样。因为条件没有变化(for 循环总是从0 开始)。

这意味着,solve() 方法被重复调用,直到堆栈内存不足。

【讨论】:

  • 好的,谢谢,我尝试编辑求解方法,这样它就不会只是重复调用相同的循环。我仍然遇到同样的问题。我将更改后的代码添加到帖子中。
  • 您发布的代码不应编译。 rowcol 已被声明为方法参数,您正试图将它们重新声明为 for 循环迭代器。此外,每次调用 solve(..) 时,您的 for 循环仍然从索引 0 开始。
  • 对不起,我还在编辑代码,当我发布评论时,我的评论很糟糕,无论如何,嗯..它现在确实可以编译和工作,以一种奇怪的方式,花了大约一分钟来显示任何结果和它显示错误的结果。哈哈
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
  • 2015-12-25
  • 1970-01-01
  • 2016-08-16
  • 2012-05-09
  • 2020-01-11
相关资源
最近更新 更多