refactor MixedSolver

This commit is contained in:
2025-02-02 14:56:31 +01:00
parent 618e436270
commit efa357a1ab

View File

@@ -1,7 +1,6 @@
package sudoku.solver; package sudoku.solver;
import java.util.List; import java.util.List;
import java.util.Random;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import sudoku.structure.Cell; import sudoku.structure.Cell;
@@ -9,6 +8,19 @@ import sudoku.structure.MultiDoku;
public class MixedSolver implements Solver { public class MixedSolver implements Solver {
private Cell findCellToBacktrack(MultiDoku doku, int maxPossibilities) {
for (Cell cell : doku.getCells()) {
if (!cell.isMutable() || !cell.isEmpty())
continue;
List<Integer> possibleSymbols = cell.getPossibleSymbols();
if (possibleSymbols.size() == maxPossibilities) {
return cell;
}
}
return null;
}
/** /**
* Résout le MultiDoku passé en paramètre, avec règles de déduction et * Résout le MultiDoku passé en paramètre, avec règles de déduction et
* backtracking. * backtracking.
@@ -18,47 +30,45 @@ public class MixedSolver implements Solver {
*/ */
@Override @Override
public boolean solve(MultiDoku doku, List<SolverStep> steps) { public boolean solve(MultiDoku doku, List<SolverStep> steps) {
Random rand = new Random();
if (Thread.interrupted()) { if (Thread.interrupted()) {
throw new CancellationException("User wants to stop the solver"); throw new CancellationException("User wants to stop the solver");
} }
if (doku.isSolved()) { while (!doku.isSolved()) {
return true; boolean filledCell = false;
} for (Cell cell : doku.getCells()) {
if (!cell.isMutable() || !cell.isEmpty())
continue;
Cell cellToFill = doku.getFirstEmptyCell(); List<Integer> possibleSymbols = cell.getPossibleSymbols();
if (cellToFill == null) { if (possibleSymbols.size() == 1) {
return false; cell.setSymbolIndex(possibleSymbols.getFirst());
} addStep(cell, steps);
filledCell = true;
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols(); }
if (possibleSymbols.size() == 1) {
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
addStep(cellToFill, steps);
if (this.solve(doku, steps)) {
return true;
} }
} // on ne peut plus remplir de cases, on tente de backtrack
if (!filledCell) {
while (!possibleSymbols.isEmpty()) { int maxPossibilities = 2;
int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size()); Cell backtrackCell = null;
int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex); while (backtrackCell == null) {
backtrackCell = findCellToBacktrack(doku, maxPossibilities);
cellToFill.setSymbolIndex(nextSymbol); maxPossibilities++;
addStep(cellToFill, steps); }
if (this.solve(doku, steps)) { // on fait du backtracking
return true; List<Integer> possibilities = backtrackCell.getPossibleSymbols();
for (int symbol : possibilities) {
doku.getStateManager().pushState();
backtrackCell.setSymbolIndex(symbol);
if (solve(doku, steps))
return true;
doku.getStateManager().popState();
}
} }
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
addStep(cellToFill, steps);
possibleSymbols.remove(nextPossibleSymbolIndex);
} }
return false; return true;
} }
} }