package sudoku.solver; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CancellationException; import sudoku.structure.Cell; import sudoku.structure.MultiDoku; public class MixedSolver implements Solver { private List findCellsToBacktrack(MultiDoku doku, int maxPossibilities) { List cells = new ArrayList<>(); for (Cell cell : doku.getCells()) { if (!cell.isMutable() || !cell.isEmpty()) continue; List possibleSymbols = cell.getPossibleSymbols(); if (possibleSymbols.size() == maxPossibilities) { cells.add(cell); } // une cellule nous empêche de continuer if (possibleSymbols.size() == 0) return null; } return cells; } /** * Résout le MultiDoku passé en paramètre, avec règles de déduction et * backtracking. * * @param doku MultiDoku, MultiDoku à résoudre. * @return boolean, valant true si le MultiDoku est résolu, false sinon. */ @Override public boolean solve(MultiDoku doku, List steps) { if (Thread.interrupted()) { throw new CancellationException("User wants to stop the solver"); } if (doku.isSolved()) return true; if (findCellsToBacktrack(doku, 0) == null) return false; for (Cell cell : doku.getCells()) { if (!cell.isMutable() || !cell.isEmpty()) continue; List possibleSymbols = cell.getPossibleSymbols(); if (possibleSymbols.size() == 1) { cell.setSymbolIndex(possibleSymbols.getFirst()); addStep(cell, steps); if (solve(doku, steps)) return true; cell.setSymbolIndex(Cell.NOSYMBOL); addStep(cell, steps); return false; } } // on ne peut plus remplir de cases, on tente de backtrack int maxPossibilities = 2; List backtrackCells = new ArrayList<>(); while (backtrackCells.isEmpty()) { backtrackCells = findCellsToBacktrack(doku, maxPossibilities); if (backtrackCells == null || maxPossibilities > doku.getSubGrid(0).getSize()) return false; maxPossibilities++; } // on fait du backtracking for (Cell backtrackCell : backtrackCells) { List possibilities = backtrackCell.getPossibleSymbols(); for (int symbol : possibilities) { backtrackCell.setSymbolIndex(symbol); addStep(backtrackCell, steps); if (solve(doku, steps)) return true; } backtrackCell.setSymbolIndex(Cell.NOSYMBOL); addStep(backtrackCell, steps); } return false; } }