This commit is contained in:
@@ -65,6 +65,7 @@ public class Solver {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Compte le nombre de solutions possibles au MultiDoku passé en paramètres.
|
* Compte le nombre de solutions possibles au MultiDoku passé en paramètres.
|
||||||
|
*
|
||||||
* @param doku MultiDoku, MultiDoku dont on veut le nombre de solutions.
|
* @param doku MultiDoku, MultiDoku dont on veut le nombre de solutions.
|
||||||
* @return int, nombre de solutions possibles.
|
* @return int, nombre de solutions possibles.
|
||||||
*/
|
*/
|
||||||
@@ -95,6 +96,7 @@ public class Solver {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Résout le MultiDoku passé en paramètre, avec backtracking.
|
* Résout le MultiDoku passé en paramètre, avec backtracking.
|
||||||
|
*
|
||||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||||
*/
|
*/
|
||||||
@@ -131,6 +133,7 @@ public class Solver {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Résout le MultiDoku passé en paramètre, avec règles de déduction.
|
* Résout le MultiDoku passé en paramètre, avec règles de déduction.
|
||||||
|
*
|
||||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||||
*/
|
*/
|
||||||
@@ -138,33 +141,31 @@ public class Solver {
|
|||||||
if (Thread.interrupted())
|
if (Thread.interrupted())
|
||||||
throw new CancellationException("User wants to stop the solver");
|
throw new CancellationException("User wants to stop the solver");
|
||||||
|
|
||||||
|
Sudoku sudoku = doku.getSubGrid(0);
|
||||||
|
logger.log(Level.FINE,
|
||||||
|
'\n' + SudokuPrinter.toStringRectangleSudoku(sudoku,
|
||||||
|
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
||||||
|
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth()));
|
||||||
|
|
||||||
|
if (doku.isSolved()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
List<Cell> cellsToFill = doku.getEmptyCells();
|
List<Cell> cellsToFill = doku.getEmptyCells();
|
||||||
|
if (cellsToFill.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
while (!cellsToFill.isEmpty()) {
|
for (Cell cellToFill : cellsToFill) {
|
||||||
|
|
||||||
Sudoku sudoku = doku.getSubGrid(0);
|
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||||
logger.log(Level.FINE,
|
if (possibleSymbols.size() != 1) {
|
||||||
'\n' + SudokuPrinter.toStringRectangleSudoku(sudoku,
|
continue;
|
||||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
|
||||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth()));
|
|
||||||
|
|
||||||
boolean blocked = true;
|
|
||||||
for (Cell cellToFill : cellsToFill) {
|
|
||||||
|
|
||||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
|
||||||
if (possibleSymbols.size() != 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
|
|
||||||
cellsToFill.remove(cellToFill);
|
|
||||||
blocked = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blocked) {
|
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
|
||||||
break;
|
|
||||||
}
|
return Solver.humanSolve(doku);
|
||||||
}
|
}
|
||||||
|
|
||||||
return doku.isSolved();
|
return doku.isSolved();
|
||||||
@@ -172,42 +173,64 @@ public class Solver {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Résout le MultiDoku passé en paramètre, avec règles de déduction et backtracking.
|
* Résout le MultiDoku passé en paramètre, avec règles de déduction et backtracking.
|
||||||
|
*
|
||||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||||
|
* @param rand Random, pour tester aléatoirement les symboles, lors du backtracking.
|
||||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||||
*/
|
*/
|
||||||
public static boolean mixedSolve(MultiDoku doku) {
|
public static boolean mixedSolve(MultiDoku doku, Random rand) {
|
||||||
if (Thread.interrupted())
|
if (Thread.interrupted()) {
|
||||||
throw new CancellationException("User wants to stop the solver");
|
throw new CancellationException("User wants to stop the solver");
|
||||||
|
|
||||||
List<Cell> cellsToFill = doku.getEmptyCells();
|
|
||||||
|
|
||||||
while (!cellsToFill.isEmpty()) {
|
|
||||||
|
|
||||||
Sudoku sudoku = doku.getSubGrid(0);
|
|
||||||
logger.log(Level.FINE,
|
|
||||||
'\n' + SudokuPrinter.toStringRectangleSudoku(sudoku,
|
|
||||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
|
||||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth()));
|
|
||||||
|
|
||||||
boolean blocked = true;
|
|
||||||
for (Cell cellToFill : cellsToFill) {
|
|
||||||
|
|
||||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
|
||||||
if (possibleSymbols.size() != 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
|
|
||||||
cellsToFill.remove(cellToFill);
|
|
||||||
blocked = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blocked) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return doku.isSolved();
|
Sudoku sudoku = doku.getSubGrid(0);
|
||||||
|
logger.log(Level.FINE,
|
||||||
|
'\n' + SudokuPrinter.toStringRectangleSudoku(
|
||||||
|
sudoku,
|
||||||
|
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
||||||
|
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (doku.isSolved()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Cell> cellsToFill = doku.getEmptyCells();
|
||||||
|
if (cellsToFill.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Règles de déduction
|
||||||
|
for (Cell cellToFill : cellsToFill) {
|
||||||
|
|
||||||
|
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||||
|
if (possibleSymbols.size() != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
|
||||||
|
|
||||||
|
return Solver.mixedSolve(doku, rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Si ça ne marche pas
|
||||||
|
//On fait du backtracking
|
||||||
|
Cell cellToFill = doku.getRandomEmptyCell(rand);
|
||||||
|
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||||
|
|
||||||
|
while (!possibleSymbols.isEmpty()) {
|
||||||
|
int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size());
|
||||||
|
int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex);
|
||||||
|
|
||||||
|
cellToFill.setSymbolIndex(nextSymbol);
|
||||||
|
if (Solver.mixedSolve(doku, rand)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||||
|
possibleSymbols.remove(nextPossibleSymbolIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package sudoku.structure;
|
package sudoku.structure;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import sudoku.io.SudokuSerializer;
|
import sudoku.io.SudokuSerializer;
|
||||||
|
|
||||||
@@ -170,4 +167,15 @@ public class MultiDoku {
|
|||||||
return stateManager;
|
return stateManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renvoie une Cell vide choisie aléatoirement.
|
||||||
|
*
|
||||||
|
* @param rand Random, pour le choix aléatoire.
|
||||||
|
* @return Cell, une Cell vide.
|
||||||
|
*/
|
||||||
|
public Cell getRandomEmptyCell(Random rand) {
|
||||||
|
List<Cell> emptyCells = getEmptyCells();
|
||||||
|
int randomIndex = rand.nextInt(emptyCells.size());
|
||||||
|
return emptyCells.get(randomIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user