For循环冻结了我的程序

时间:2014-03-28 08:53:01

标签: java for-loop freeze sudoku

我正在尝试制作一个9 X 9 Sudoku随机生成的网格,但我遇到了问题。每次我运行程序时,它总是冻结,只显示或多或少5行随机生成的数字。我不会遇到4 X 4和6 X 6网格的问题,只有9 X 9.我不知道它为什么会一直冻结。我希望有一个人可以帮助我。这是我的代码。

public class Sudoku9x9
{
    public static void main(String[] args)
    {
        Random rand = new Random();
        int[][] sudoku = new int[9][9];
        int rnum = 0;

        for(int a = 0; a < 9; a++)
        {
            for(int b = 0; b < 9; b++)
            {
                boolean checkWhile = false;
                while(checkWhile == false)
                {
                    rnum = rand.nextInt(9) + 1;
                    if(CheckRow(a, b, sudoku, rnum) && CheckCol(a, b, sudoku, rnum)))
                    {
                        sudoku[a][b] = rnum;
                        checkWhile = true;
                    }
                }

                System.out.print(rnum + " ");
            }

            System.out.println("");
        }

        for(int a = 0; a < 9; a++)
        {
            for(int b = 0; b < 9; b++)
            {
                System.out.print(sudoku[a][b] + " ");
            }

            System.out.println("");
        }
    }

    public static boolean CheckRow(int a, int b, int[][] sudoku, int rnum)
    {
        boolean check = true;
        for(int c = b; c > 0; c--)
        {
            if(sudoku[a][c - 1] == rnum)
            {
                check = false;
            }
        }

        return check;
    }

    public static boolean CheckCol(int a, int b, int[][] sudoku, int rnum)
    {
        boolean check1 = true;
        for(int c = a; c > 0; c--)
        {
            if(sudoku[c - 1][b] == rnum)
            {
                check1 = false;
            }
        }

        return check1;
    }
}

2 个答案:

答案 0 :(得分:1)

你的循环很慢,因为当你的程序填满大部分Sudoku时,很难生成一个适当的随机int来填充下一个槽,所以rnum将被生成一次又一次并且许多重复的整数是产生。例如,如果只有一个数字可以使checkRow和checkCol为true,则生成它的概率为1/9!更糟糕的是,你的计划将陷入无法解决的境地!!!

所以你需要一个回溯计划,类似于八皇后问题。这是我的代码:

static int[][] sudoku = new int[9][9];

public static boolean CheckRow(int a, int b, int[][] sudoku, int rnum)
{
    boolean check = true;
    for(int c = b; c > 0; c--)
    {
        if(sudoku[a][c - 1] == rnum)
        {
            return false;
        }
    }

    return check;
}

public static boolean CheckCol(int a, int b, int[][] sudoku, int rnum)
{
    boolean check1 = true;
    for(int c = a; c > 0; c--)
    {
        if(sudoku[c - 1][b] == rnum)
        {
            return false;
        }
    }

    return check1;
}

public static boolean fill(int a, int b) {
    Random rand = new Random();
    int rnum = rand.nextInt(9) + 1;
    boolean checkWhile = false;
    for(int i = 0; i < 9 && !checkWhile; i++) {
        if(CheckRow(a, b, sudoku, rnum) && CheckCol(a, b, sudoku, rnum))
        {
            sudoku[a][b] = rnum;
            if(a == 8 && b == 8) return true;
            if(b == 8) checkWhile = fill(a+1,0);
            else checkWhile = fill(a,b+1);
        }
        if(rnum == 9) rnum = 1;
        else rnum += 1;

    }
    return checkWhile;
}

public static void main(String[] args) {    
    fill(0,0);
    for(int i = 0; i < 9; i++) {
        for(int j = 0; j < 9; j++) {
            System.out.print(sudoku[i][j]+" ");
        }
        System.out.println("");
    }

}

答案 1 :(得分:0)

我可以发现一种避免不必要的检查的方法是更改​​你的检查方法,一旦发现错误就返回;

public static boolean CheckCol(int a, int b, int[][] sudoku, int rnum)
    {
        boolean check1 = true;
        for(int c = a; c > 0; c--)
        {
            if(sudoku[c - 1][b] == rnum)
            {
                return false;
            }
        }

        return check1;
    }

也适用于行。

阅读locoyou的回答。此外,您的程序没有回溯功能,它可能会来到您的sodoku无法解决的地方,然后您需要回溯。您可能想要检查的数据的另一个重要元素是检查该号码所在的3x3框。