diff --git a/app/src/main/java/sudoku/solver/MixedSolver.java b/app/src/main/java/sudoku/solver/MixedSolver.java index f6d12f5..e2ad05a 100644 --- a/app/src/main/java/sudoku/solver/MixedSolver.java +++ b/app/src/main/java/sudoku/solver/MixedSolver.java @@ -1,7 +1,6 @@ package sudoku.solver; import java.util.List; -import java.util.Random; import java.util.concurrent.CancellationException; import sudoku.structure.Cell; @@ -9,6 +8,19 @@ import sudoku.structure.MultiDoku; public class MixedSolver implements Solver { + private Cell findCellToBacktrack(MultiDoku doku, int maxPossibilities) { + for (Cell cell : doku.getCells()) { + if (!cell.isMutable() || !cell.isEmpty()) + continue; + + List 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 * backtracking. @@ -18,47 +30,45 @@ public class MixedSolver implements Solver { */ @Override public boolean solve(MultiDoku doku, List steps) { - Random rand = new Random(); - if (Thread.interrupted()) { throw new CancellationException("User wants to stop the solver"); } - if (doku.isSolved()) { - return true; - } + while (!doku.isSolved()) { + boolean filledCell = false; + for (Cell cell : doku.getCells()) { + if (!cell.isMutable() || !cell.isEmpty()) + continue; - Cell cellToFill = doku.getFirstEmptyCell(); - if (cellToFill == null) { - return false; - } - - List possibleSymbols = cellToFill.getPossibleSymbols(); - - if (possibleSymbols.size() == 1) { - cellToFill.setSymbolIndex(possibleSymbols.getFirst()); - addStep(cellToFill, steps); - if (this.solve(doku, steps)) { - return true; + List possibleSymbols = cell.getPossibleSymbols(); + if (possibleSymbols.size() == 1) { + cell.setSymbolIndex(possibleSymbols.getFirst()); + addStep(cell, steps); + filledCell = true; + } } - } - - while (!possibleSymbols.isEmpty()) { - int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size()); - int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex); - - cellToFill.setSymbolIndex(nextSymbol); - addStep(cellToFill, steps); - if (this.solve(doku, steps)) { - return true; + // on ne peut plus remplir de cases, on tente de backtrack + if (!filledCell) { + int maxPossibilities = 2; + Cell backtrackCell = null; + while (backtrackCell == null) { + backtrackCell = findCellToBacktrack(doku, maxPossibilities); + maxPossibilities++; + } + // on fait du backtracking + List 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; } }