У меня проблемы с моим алгоритмом решения логики. Он решает головоломки с большим количеством подсказок очень хорошо, у него просто проблемы с головоломками, которые имеют менее 45 подсказок.
Это алгоритм для решения. Immutable - это логическое значение, которое определяет, можно ли изменить это значение. 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;
}
}
Это код для удаленияFromCells()
Я думаю, что большая часть кода довольно понятна. Первый цикл 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;
}
}
}
}
Я бы опубликовал весь файл, но там много ненужных методов. Я опубликовал то, что, по моему мнению, вызывает проблемы.