利用程序随机构造N个已解答的数独棋盘

时间:2021-10-03 19:31:33
package cn.suduku.demo;

public class sudoku2 {

    public static void main(String[] args) {
        
        Sudoku s = new Sudoku(); 
        s.displaySudoku();
        
        if(s.solveSudoku())
        {
            s.displaySudoku();
        }
        else
        {
            System.out.println("Unsuccessful");
        }

    }

}


class Sudoku
{
    private int[][] sudoku;
    private static final int UNASSIGNED = 0;
    
    public Sudoku()
    {
        sudoku = new int[9][9];
    }
    
    public Sudoku(int sudoku[][])
    {
        this.sudoku= sudoku;
    }
    
    public boolean solveSudoku() ////方法从左上角单元格开始遍历到右侧。它逐个检查每行中的单元格,并获取具有UNASSIGNED值的第一个单元格。
    {
        for(int row=0;row<9;row++)
        {
            for(int col=0;col<9;col++)
            {
                if(sudoku[row][col]==UNASSIGNED)
                {
                    for(int number=1;number<=9;number++)
                    {
                        if(isAllowed(row, col, number))
                        {
                            sudoku[row][col] = number;
                            if(solveSudoku())
                            {
                                return true;
                            }
                            else
                            {
                                sudoku[row][col] = UNASSIGNED;
                            }
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
    //如果当前行,当前列,当前3x3格子存在数字,用以下三个方法检查
    private boolean containsInRow(int row,int number)
    {
        for(int i=0;i<9;i++)
        {
            if(sudoku[row][i]==number)
            {
                return true;
            }
        }
        return false;
    }
    
    private boolean containsInCol(int col,int number)
    {
        for(int i=0;i<9;i++)
        {
            if(sudoku[i][col]==number)
            {
                return true;
            }
        }
        return false;
    }
    
    private boolean containsInBox(int row, int col,int number)
    {
        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(sudoku[i][j]==number)
                {
                    return true;
                }
            }
            
        }
        return false;
    }
    
    private boolean isAllowed(int row, int col,int number) //检查分配的数字是否安全,如果返回为true则不允许使用该数字
    {
        return !(containsInRow(row, number) || containsInCol(col, number) || containsInBox(row, col, number));
    }
    
    public void displaySudoku()
    {
        for(int i=0;i<9;i++)
        {
            if(i%3==0 && i!=0)
            {
                System.out.println("----------------------------------\n");
            }
            for(int j=0;j<9;j++)
            {
                if(j%3==0 && j!=0)
                {
                    System.out.print(" | ");
                }
                System.out.print(" " + sudoku[i][j] + " ");
                
            }
            
            System.out.println();
        }
        System.out.println("\n\n__________________________________________\n\n");
    }
    
}

以上则是程序的运行代码,输出结果如下:

 1  2  3  |  4  5  6  |  7  8  9 

 4  5  6  |  7  8  9  |  1  2  3 

 7  8  9  |  1  2  3  |  4  5  6 

----------------------------------

 

 2  1  4  |  3  6  5  |  8  9  7 

 3  6  5  |  8  9  7  |  2  1  4 

 8  9  7  |  2  1  4  |  3  6  5 

----------------------------------

 

 5  3  1  |  6  4  2  |  9  7  8 

 6  4  2  |  9  7  8  |  5  3  1 

 

 9  7  8  |  5  3  1  |  6  4  2 

 

分析:该程序运行正确,运行速度很快,程序代码量少。

心得:本次项目花了三天的时间来完成,万事开头难,在写程序前一直在想该程序如何去实现,同时跟朋友讨论了下,最后决定使用回溯法去实现该程序。递归回溯法,一步一步构建解决方案,如果在某个步骤显示当前路径无法解决方案,则返回上一步并选择其他的路径。因此该程序可以逐个解决数据为单元格分配数字,在分配号码之前我们需要确认当前行,当前列,当前3x3网格中是不存在相同的号码。如果相应的行,列,子格中不存在数字,我们可以分配数字,并递归检查此分配是否符合方案,如果分配没有解决方案,那么我们尝试当前单元格的下一个数字。如果没有数字(1到9)解决方案,我们返回false。但是开始漏了3x3小格子里面也要进行数据判断,总是不成功,最后整体看了下才发现是自己漏了这一重要点。总体来说本次项目收获蛮大的,在设计一个程序时,最重要的就是开始的需求分析,如果错了那就是一个失败的程序。

 

课外任务:

目前来说,对于编程方便,自己需要更多的去提升,提高整体的代码量,而且要继续对java的学习,而且需要学习js和h5方面的知识。

我认为对我特别重要的技能有:

1.Proggramming  Overall    当前 3分  课后 8分

2.Programma:performance    当前 2分  课后 8分

3.Programming:cutting edge technology    当前 4分  课后 8分

4.Personal Software Process    当前 1分  课后 8分

5.Programming:BigDate     当前 0分  课后 5分.

6.Programming:Design    当前 3分  课后 7分