Генератор судоку Java работает неправильно

Я работаю над генератором головоломок судоку в java, я написал этот класс для создания головоломки, но он неправильно генерирует головоломку. Вот пример того, что я получаю:

головоломка

Как видите, это недопустимое решение судоку. Но, глядя на мой код, я не понимаю, почему он не генерирует правильную головоломку. Может кто-нибудь объяснить, почему это работает неправильно?

package sudoku;

import java.util.Random;

public class Puzzle {

    // number generator
    Random gen = new Random();

    // 9x9 puzzle
    int puzzle[][] = new int[9][9];

    public int[][] generate() {

        // add each number to the board
        for (int x = 0; x < 9; x++) {
            for (int y = 0; y < 9; y++) {

                boolean isValid = false;

                // keep generating new numbers until a valid number is found
                while (isValid == false) {

                    // generate random number 1-9
                    int num = gen.nextInt(9) + 1;

                    // check if number is valid
                    if (checkRow(num, x) == true || checkCol(num, y) == true
                            || checkSection(num, x, y) == true) {

                        // add number to the board
                        puzzle[x][y] = num;

                        // exit loop
                        isValid = true;
                    }
                }
            }
        }

        return puzzle;
    }

    // check each element of the row for num, if num is found return false
    private boolean checkRow(int num, int row) {

        boolean valid = true;
        for (int i = 0; i < 9; i++) {
            if (puzzle[row][i] == num) {
                valid = false;
                break;
            }
        }

        return valid;
    }

    // check each element of the column for num, if num is found return false
    private boolean checkCol(int num, int col) {

        boolean valid = true;
        for (int i = 0; i < 9; i++) {
            if (puzzle[i][col] == num) {
                valid = false;
                break;
            }
        }

        return valid;
    }

    // check each element of the section for num, if num is found return false
    private boolean checkSection(int num, int xPos, int yPos) {

        int[][] section = new int[3][3];
        section = getSection(xPos, yPos);

        boolean valid = true;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (section[i][j] == num) {
                    valid = false;
                    break;
                }
            }
        }

        return valid;
    }

    // return the 3x3 section the given coordinates are in
    private int[][] getSection(int xPos, int yPos) {

        int xIndex = 0;
        int yIndex = 0;
        int[][] section = new int[3][3];

        // get x index
        if (xPos == 0 || xPos == 3 || xPos == 6) {
            xIndex = xPos;
        } else if (xPos == 1 || xPos == 4 || xPos == 7) {
            xIndex = xPos - 1;
        } else if (xPos == 2 || xPos == 5 || xPos == 8) {
            xIndex = xPos - 2;
        }

        // get y index
        if (yPos == 0 || yPos == 3 || yPos == 6) {
            yIndex = yPos;
        } else if (yPos == 1 || yPos == 4 || yPos == 7) {
            yIndex = yPos - 1;
        } else if (yPos == 2 || yPos == 5 || yPos == 8) {
            yIndex = yPos - 2;
        }

        int i = 0;
        int j = 0;
        // extract section from puzzle
        for (int x = xIndex; x < 3; x++) {
            for (int y = yIndex; y < 3; y++) {
                section[x][y] = puzzle[i][j];
                i++;
            }
            j++;
        }

        return section;

    }
}

person Petefic    schedule 15.06.2013    source источник
comment
Ваш класс полностью процедурно написан, без каких-либо следов объектной ориентации. Вы можете обнаружить, что ваш алгоритм легче устранить, если вы разделите его на объекты, каждый из которых имеет свои собственные методы для тестирования и построения. Существительные в вашем проекте: Головоломка, Секции, Квадраты; возможно, столбец, ряд и цифра. Это звучит как классы. Вместо отладки огромной монолитной процедуры было бы проще отлаживать поведение отдельных модулей.   -  person scottb    schedule 15.06.2013
comment
Это не ошибка, но в if (someCondition == true) часть ==true избыточна, достаточно простой if (someCondition).   -  person Pshemo    schedule 15.06.2013


Ответы (2)


Недостаточно, чтобы строка, столбец или раздел были действительными. Они ВСЕ ДОЛЖНЫ быть действительными. Итак, измените эту строку:

if (checkRow(num, x) == true || checkCol(num, y) == true || checkSection(num, x, y) == true) 

с

if (checkRow(num, x) == true && checkCol(num, y) == true && checkSection(num, x, y) == true) 

или просто

if (checkRow(num, x) && checkCol(num, y) && checkSection(num, x, y)) {
person darijan    schedule 15.06.2013

Могут быть дополнительные ошибки, но эта строка явно неверна:

if (checkRow(num, x) == true || checkCol(num, y) == true
                        || checkSection(num, x, y) == true) {

Вы должны использовать здесь && (логическое И) вместо || (логическое ИЛИ).

person schnaader    schedule 15.06.2013