import java.util.Random;

public class SudokuGenerator {
    private int[][] board;
    private static final int SIZE = 9;
    private static final int EMPTY = 0;

    public SudokuGenerator() {
        board = new int[SIZE][SIZE];
    }

    public void generateBoard() {
        fillDiagonalSections();
        fillRemaining(0, 3);
        removeDigits(20);
    }

    void fillDiagonalSections() {
        for (int i = 0; i < SIZE; i = i + 3) {
            fillBox(i, i);
        }
    }

    boolean unUsedInBox(int rowStart, int colStart, int num) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[rowStart + i][colStart + j] == num) {
                    return false;
                }
            }
        }
        return true;
    }

    void fillBox(int row, int col) {
        int num;
        Random rand = new Random();
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                do {
                    num = rand.nextInt(SIZE) + 1;
                } while (!unUsedInBox(row, col, num));
                board[row + i][col + j] = num;
            }
        }
    }

    boolean fillRemaining(int i, int j) {
        if (j >= SIZE && i < SIZE - 1) {
            i = i + 1;
            j = 0;
        }
        if (i >= SIZE && j >= SIZE)
            return true;

        if (i < 3) {
            if (j < 3)
                j = 3;
        } else if (i < SIZE - 3) {
            if (j == (i / 3) * 3)
                j = j + 3;
        } else {
            if (j == SIZE - 3) {
                i = i + 1;
                j = 0;
                if (i >= SIZE)
                    return true;
            }
        }

        for (int num = 1; num <= SIZE; num++) {
            if (isSafe(i, j, num)) {
                board[i][j] = num;
                if (fillRemaining(i, j + 1))
                    return true;

                board[i][j] = EMPTY;
            }
        }
        return false;
    }

    boolean isSafe(int i, int j, int num) {
        return (unUsedInRow(i, num) && unUsedInCol(j, num) && unUsedInBox(i - i % 3, j - j % 3, num));
    }

    boolean unUsedInRow(int i, int num) {
        for (int j = 0; j < SIZE; j++) {
            if (board[i][j] == num)
                return false;
        }
        return true;
    }

    boolean unUsedInCol(int j, int num) {
        for (int i = 0; i < SIZE; i++) {
            if (board[i][j] == num)
                return false;
        }
        return true;
    }

    void removeDigits(int K) {
        Random rand = new Random();
        while (K > 0) {
            int cellId = rand.nextInt(SIZE * SIZE);

            // extract coordinates i and j
            int i = cellId / SIZE;
            int j = cellId % SIZE;

            if (board[i][j] != EMPTY) {
                K--;
                board[i][j] = EMPTY;
            }
        }
    }

    public void printSudoku() {
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++)
                System.out.print(board[i][j] + " ");
            System.out.println();
        }
    }

    public static void main(String[] args) {
        SudokuGenerator sudokuGenerator = new SudokuGenerator();
        sudokuGenerator.generateBoard();
        sudokuGenerator.printSudoku();
    }
}

SudokuGenerator.main(null);
6 7 5 2 1 4 0 8 9 
0 3 0 5 8 0 4 2 7 
4 0 8 3 7 9 1 6 5 
2 5 0 1 0 8 6 4 0 
0 4 1 6 5 3 7 9 2 
0 9 0 7 4 0 0 1 8 
0 8 0 9 6 0 2 3 1 
0 1 2 4 3 7 8 5 0 
5 6 3 8 2 0 9 0 4