user3891918
user3891918

Reputation: 11

Sudoku Algorithm generates 0 values

So I have a sudoku algorithm for a generating a completed game board. The problem is that the algorithm in some instances runs out of possible values to place in the grid, so by default it places a 0.

Here's the code:

public void generateBoard() {
    // Determine values for board
    int r, d;

    // For every slot in grid
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {

            // Create HashSet with values 1-9
            for (int k = 1; k <= 9; k++) {
                set.add(k);
            }

            checkRow(i);
            checkCol(j);
            checkBox(i, j);

            // Create an iterator
            Iterator<Integer> iterator = set.iterator();

            // Add HashSet values to ArrayList via Iterator
            while (iterator.hasNext()) {
                d = iterator.next();
                values.add(d);
            }

            try {
                // Randomly choose from list of viable values to be put into slot
                r = new Random().nextInt(values.size());
                slots[i][j] = (Integer) values.get(r);
            } catch (Exception e) {
                e.printStackTrace();
                //resetBoard();
                //continue;

            }

            // Clear HashSet and ArrayList after slot is assigned value
            values.clear();
            set.clear();
        }
    }

}

public void checkRow(int i) {
    for (int c = 1; c <= 9; c++) {
        for (int a = 0; a < 9; a++) {
            // If c value is already in row remove from HashSet
            if (c == slots[i][a]) {
                set.remove(c);
            }
        }
    }
}

public void checkCol(int j) {
    for (int c = 1; c <= 9; c++) {
        for (int a = 0; a < 9; a++) {
            // If c value is already in column remove from HashSet
            if (c == slots[a][j]) {
                set.remove(c);
            }
        }
    }
}

public void checkBox(int i, int j) {
    int xSet = (i - (i % 3));
    int ySet = (j - (j % 3));

    for (int c = 1; c <= 9; c++) {
        for (int x = xSet; x < xSet + 3; x++) {
            for (int y = ySet; y < ySet + 3; y++) {
                // If c value is already in box remove from HashSet
                if (c == slots[x][y]) {
                    set.remove(c);
                }
            }
        }
    }
}

And this is what the generated board looks like: http://imgur.com/2cWh61j

Upvotes: 1

Views: 116

Answers (1)

BambooleanLogic
BambooleanLogic

Reputation: 8161

The reason why your algorithm fails is because it's inherently wrong. Generating a Sudoku puzzle is more complicated than that.

A shortcut sometimes used to create a puzzle is to hardcode a few correct puzzles, picking one at random, shuffling the digits (swap all Xs with Ys and vice versa, and so on) shuffling the rows/columns (without moving any number outside its old box) and shuffling the 3x9 and 9x3 areas along the box borders. Doing so will create a puzzle that's TECHNICALLY the same as the original from a mathematical standpoint but should "feel" unique enough to a human.

Also keep in mind that even when you have a complete board, figuring out which tiles you can safely remove without creating an ambiguous puzzle is a bit tricky as well. The naive "remove x tiles at random" solution often fails.

Another question (with some useful answers) about how to create Sudokus can be found here: How to generate Sudoku boards with unique solutions

Upvotes: 2

Related Questions