Алгоритм логического решения (для судоку в Java)

У меня проблемы с алгоритмом решения логики. Он очень хорошо решает головоломки с большим количеством подсказок, у него есть проблемы только с головоломками, в которых меньше 45 подсказок.

Это алгоритм решения. Неизменяемый - это логическое значение, которое определяет, можно ли изменить это значение. cell [row] [col] .possibleValues ​​- это LinkedList в классе SudokuCell, в котором хранятся значения, возможные для этого элемента сетки. grid.sGrid - это главный массив головоломки int [] []. removeFromCells () - это метод, который удаляет значения из строки, столбца и квадранта сетки. Этот код приведен ниже.

Второй цикл for предназначен только для проверки единственного решения. Я решил избежать рекурсии, потому что я действительно не могу понять это. Кажется, что этот метод пока работает достаточно хорошо.

public boolean solve(){

    for(int i = 0; i < 81; i++){
        for(int row = 0; row < 9; row++){
            for(int col = 0; col < 9; col++){
                if(!immutable[row][col]){
                    if(cell[row][col].getSize() == 1){
                        int value = cell[row][col].possibleValues.get(0);
                        grid.sGrid[row][col] = value;
                        immutable[row][col] = true;
                        removeFromCells(row, col, value);
                    }
                }
            }
        }
    }


    int i = 0;
    for(int row = 0; row < 9; row++){
        for(int col = 0; col < 9; col++){
            if(grid.sGrid[row][col] == 0){
                i++;
            }
        }
    }

    if(i != 0){
        return false;
    } else{
        return true;
    }
}

Это код для removeFromCells ()

Я думаю, что большая часть кода не требует пояснений. Первый цикл for удаляет значение из строки и столбца (x, y), а второй цикл удаляет значение из квадранта.

public void removeFromCells(int x, int y, int value){

    /*
     * First thing to do, find the quadrant where cell[x][y] belong.
     */

    int topLeftCornerRow = 3 * (x / 3) ;
    int topLeftCornerCol = 3 * (y / 3) ;

    /*
     * Remove the values from each row and column including the one
     * where the original value to be removed is.
     */
    for(int i = 0; i < 9; i++){
        cell[i][y].removeValue(value);
        cell[x][i].removeValue(value);
    }


    for(int row = 0; row < 3; row++){
        for(int col = 0; col < 3; col++){
            cell[topLeftCornerRow + row][topLeftCornerCol + col].removeValue(value);
        }
    }
}

Еще одна проблема может заключаться в том, где создаются возможные значения. Вот метод, который у меня есть для этого:

Первый цикл for создает новые SudokuCells, чтобы избежать ужасного исключения нулевого указателя.

Любые нулевые значения в sGrid представлены как 0, поэтому цикл for их пропускает.

Конструктор SudokuBoard вызывает этот метод, поэтому я знаю, что он вызывается.

public void constructBoard(){

    for(int row = 0; row < 9; row++){
        for(int col = 0; col < 9; col++){
            cell[row][col] = new SudokuCell();
        }
    }

    immutable = new boolean[9][9];

    for(int row = 0; row < 9; row++){
        for(int col = 0; col < 9; col++){
            immutable[row][col] = false;
            if(grid.sGrid[row][col] != 0){
                removeFromCells(row, col, grid.sGrid[row][col]);
                immutable[row][col] = true;
            }
        }
    }
}

Я бы опубликовал весь файл, но там много ненужных методов. Я опубликовал то, что, как мне кажется, вызывает мои проблемы.

11
задан SkylineAddict 8 March 2011 в 18:53
поделиться