mardi 28 juin 2016

Backtracking algorithm to solve Sudoku

I've been trying to implement a backtracking algorithm to solve Sudoku in java console application. I've never implemented the algorithm before, and probably looking at few youtube videos was not enough, because it does not seem to work as I think it should.

I've filled manually the board with an actual sudoku I found online. However, it does not go past the first square. Initially I've tried to nest the whole thing in a double for-loop, but that does not seem to work either.

I've tested properly the valid-move methods so the problem is clearly not there. Appreciate any help.

public class Sudoku {

    public static int[][] createBoard(int n)
    {
        int[][] board = new int[n][n];
        for (int i=0; i<board.length; i++)
            for (int j=0; j<board[i].length; j++)
                board[i][j]=0;
        return board;
    }

    public static void printBoard(int[][] b)
    {
        int buffer=(int)Math.sqrt(b.length);
        String btm=new String(new char[buffer*buffer*3+buffer+1]).replace("�", "_"); // fitting for all board size
        for (int i=0; i<b.length; i++)
        {
            if (i%buffer==0)
                System.out.println(btm);
            for (int j=0; j<b[i].length; j++)
            {
                if (j%buffer==0)
                    System.out.print("|");
                if (b[i][j]==0)
                    System.out.print(" _ ");
                else
                    System.out.print(" " + b[i][j] + " ");
            }
                System.out.println("|");
        }
        System.out.println(btm);
    }

    // returns true if a number can be inserted in a row. 
    public static boolean checkLegalRow(int[][] b, int row, int num)
    {
        for (int i=0; i<b.length; i++)
        {
            if (b[row][i]==num)
                return false;
        }
        return true;
    }
    // returns true if a number can be inserted in a column.
    public static boolean checkLegalCol(int[][] b, int col, int num)
    {
        for (int i=0; i<b.length; i++)
        {
            if (b[i][col]==num)
                return false;
        }
        return true;
    }

    //returns true if number can be inserted in its NxN box
    public static boolean checkLegalBox(int[][] b, int row, int col, int num)
    {
        int buffer=(int)Math.sqrt(b.length);
        for (int i=0, adjRow=row-(row%buffer); i<buffer; i++, adjRow++)
        {
            for (int j=0, adjCol=col-(col%buffer); j<buffer; j++, adjCol++)
            {
                if (b[adjRow][adjCol]==num)
                    return false;
            }
        }
        return true;
    }

    public static boolean legalMove(int[][] b, int row, int col, int num)
    {
        return checkLegalRow(b,row,num) && checkLegalCol(b,col,num) && checkLegalBox(b,row,col,num) && b[row][col]==0;
    }

    public static void solveBacktrack(int[][] b, int row, int col)
    {
        for (int k=1; k<=b.length; k++)
            {
                if (legalMove(b,row,col,k))
                {
                    b[row][col]=k;
                    if (row==b.length-1 && col==b.length-1)
                        printBoard(b);
                    else
                    {
                        //printBoard(b);
                        if (col==b.length-1)
                            solveBacktrack(b,row+1,0);
                        else
                            solveBacktrack(b,row,col+1);
                    }
                }
            }
    }

    public static void main(String[] args)
    {
        int[][] board=createBoard(9);
        board[0][1]=4; board[1][0]=6; board[2][1]=8; board[2][2]=9; board[0][3]=6; board[2][5]=3; board[1][7]=3;
        board[1][8]=1; board[3][3]=4;
        board[3][0]=2;  board[3][2]=1; board[3][4]=5; board[3][7]=7; board[3][8]=8; board[4][1]=5;
        board[4][3]=3; board[4][5]=7; board[5][0]=3; board[5][1]=6; board[5][4]=2; board[5][5]=8; board[5][8]=5;
        board[6][3]=1; board[6][6]=6; board[6][7]=4; board[7][0]=4; board[7][1]=3; board[7][8]=9; board[8][2]=6; 
        board[8][5]=9;
        printBoard(board);
        solveBacktrack(board,0,0);
    }
}

Aucun commentaire:

Enregistrer un commentaire