From 80239274d76bfc8bd55dd13bfb80f15198d32111 Mon Sep 17 00:00:00 2001 From: Melvyn Date: Mon, 27 Jan 2025 14:48:28 +0100 Subject: [PATCH] feat : solver random --- app/gradle/wrapper/gradle-wrapper.properties | 5 ++ app/src/main/java/gui/menu/SudokuView.java | 28 +++---- app/src/main/java/sudoku/solver/Solver.java | 74 ++++++++++--------- .../main/java/sudoku/solver/StupidSolver.java | 3 + .../main/java/sudoku/structure/Sudoku.java | 5 +- .../test/java/sudoku/solver/SolverTest.java | 10 ++- 6 files changed, 74 insertions(+), 51 deletions(-) create mode 100644 app/gradle/wrapper/gradle-wrapper.properties diff --git a/app/gradle/wrapper/gradle-wrapper.properties b/app/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..1e2fbf0 --- /dev/null +++ b/app/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/app/src/main/java/gui/menu/SudokuView.java b/app/src/main/java/gui/menu/SudokuView.java index e91f46f..bb02cf9 100644 --- a/app/src/main/java/gui/menu/SudokuView.java +++ b/app/src/main/java/gui/menu/SudokuView.java @@ -3,6 +3,7 @@ package gui.menu; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.concurrent.CancellationException; import gui.ColorGenerator; @@ -12,7 +13,7 @@ import imgui.ImVec2; import imgui.ImVec4; import imgui.flag.ImGuiCol; import imgui.flag.ImGuiStyleVar; -import sudoku.solver.StupidSolver; +import sudoku.solver.Solver; import sudoku.structure.Block; import sudoku.structure.Cell; import sudoku.structure.MultiDoku; @@ -98,19 +99,18 @@ public class SudokuView extends BaseView { ImGui.beginDisabled(); if (ImGui.button("Résoudre")) { - resolveThread = new Thread(new Runnable() { - @Override - public void run() { - try { - doku.getSubGrid(0).clear(); - StupidSolver.solve(doku); - Thread.sleep(200); - } catch (CancellationException | InterruptedException e) { - System.out.println("The user is bored !"); - } - stopResolve(); - } - }); + + resolveThread = new Thread(() -> { + try { + Random rand = new Random(); + doku.getSubGrid(0).clear(); + Solver.solveRandom(doku, rand); + Thread.sleep(200); + } catch (CancellationException | InterruptedException e) { + System.out.println("The user is bored !"); + } + stopResolve(); + }); } boolean wantsToStop = false; if (resolveThread != null && resolveThread.isAlive()){ diff --git a/app/src/main/java/sudoku/solver/Solver.java b/app/src/main/java/sudoku/solver/Solver.java index 74c5f29..e1eb4b5 100644 --- a/app/src/main/java/sudoku/solver/Solver.java +++ b/app/src/main/java/sudoku/solver/Solver.java @@ -4,16 +4,54 @@ import sudoku.structure.MultiDoku; import sudoku.structure.Cell; import java.util.List; +import java.util.Random; +import java.util.concurrent.CancellationException; public class Solver { /** * Résout le multidoku passé en paramètre si c'est possible. * En testant toutes les possibilités avec un algorithme de backtracking. + * * @param doku Multidoku, à résoudre + * @param rand random pour tester aléatoirement les symboles * @return boolean, true s'il est résolut ou false s'il ne l'est pas. */ + public static boolean solveRandom(MultiDoku doku, Random rand) { + if (Thread.interrupted()) + throw new CancellationException("User wants to stop the solver"); + + if (doku.isValid()) { + return true; + } + + Cell cellToFill = doku.getFirstEmptyCell(); + if (cellToFill == null) { + return false; + } + + List possibleSymbols = doku.getPossibleSymbolsOfCell(cellToFill); + + while (!possibleSymbols.isEmpty()){ + int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size()); + int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex); + + cellToFill.setSymbolIndex(nextSymbol); + if (Solver.solveRandom(doku, rand)) { + return true; + } else { + cellToFill.setSymbolIndex(Cell.NOSYMBOL); + possibleSymbols.remove(nextPossibleSymbolIndex); + } + + } + return false; + } + public static boolean solve(MultiDoku doku) { + if (Thread.interrupted()) + throw new CancellationException("User wants to stop the solver"); + if (doku.isValid()) { return true; } @@ -28,46 +66,16 @@ public class Solver { return false; } - for (int symbol : possibleSymbols) { + for (int symbol : possibleSymbols){ + cellToFill.setSymbolIndex(symbol); if (Solver.solve(doku)) { return true; } else { cellToFill.setSymbolIndex(Cell.NOSYMBOL); } + } return false; } - - /* - Ancien algo abandonné pour le moment - - private void rollBack() { - stack.pop(); - } - - - public MultiDoku solve(MultiDoku doku, List constraints) throws Exception { - List allMutableCells = doku.getMutableCells(); - List remainingCellsToCheck = new ArrayList<>(allMutableCells); - Random rand = new Random(); - while (!remainingCellsToCheck.isEmpty()) { - int indexCurrentCell = rand.nextInt(remainingCellsToCheck.size()); - MutableCell currentCell = remainingCellsToCheck.get(indexCurrentCell); - - int symbol = currentCell.getPossibleSymbols().get(0); - currentCell.setSymbolIndex(symbol); - // stack.push(new MutableCell(currentCell)); - try { - doku.updateSymbolsPossibilities(); - } catch (Exception e) { - this.rollBack(); - System.out.println(this.stack); - } - remainingCellsToCheck.remove(indexCurrentCell); - } - return doku; - } - - */ } diff --git a/app/src/main/java/sudoku/solver/StupidSolver.java b/app/src/main/java/sudoku/solver/StupidSolver.java index 9ed1b8a..1528e27 100644 --- a/app/src/main/java/sudoku/solver/StupidSolver.java +++ b/app/src/main/java/sudoku/solver/StupidSolver.java @@ -5,6 +5,9 @@ import java.util.concurrent.CancellationException; import sudoku.structure.MultiDoku; import sudoku.structure.Sudoku; +/** + * Class de test non utilisé + */ public class StupidSolver { private static boolean solve(Sudoku sudoku, int index) { diff --git a/app/src/main/java/sudoku/structure/Sudoku.java b/app/src/main/java/sudoku/structure/Sudoku.java index 8d88bde..1d24441 100644 --- a/app/src/main/java/sudoku/structure/Sudoku.java +++ b/app/src/main/java/sudoku/structure/Sudoku.java @@ -229,8 +229,9 @@ public class Sudoku { } catch (Exception e) { return result; } - for (IConstraint constraint : this.constraints) { - if (result.isEmpty()) { + for (int i = 0; i < this.constraints.size(); i++) { + IConstraint constraint = this.constraints.get(i); + if (i == 0) { result.addAll(constraint.getPossibleSymbols(this, cellCoordinates.getX(), cellCoordinates.getY())); } else { result.retainAll(constraint.getPossibleSymbols(this, cellCoordinates.getX(), cellCoordinates.getY())); diff --git a/app/src/test/java/sudoku/solver/SolverTest.java b/app/src/test/java/sudoku/solver/SolverTest.java index deeabc9..4138326 100644 --- a/app/src/test/java/sudoku/solver/SolverTest.java +++ b/app/src/test/java/sudoku/solver/SolverTest.java @@ -56,7 +56,7 @@ class SolverTest { assert(dokuResult.isValid()); - Solver.solve(dokuToTest); + Solver.solveRandom(dokuToTest, ); System.out.println("\n****************************\nDoku solved"); @@ -81,8 +81,14 @@ class SolverTest { 5, ns, ns, ns, 3, 1, 0, ns, ns); sudokuToTest2.setImmutableCellsSymbol(immutableCells2); - boolean isSolved = Solver.solve(dokuToTest2); + boolean isSolved = Solver.solveRandom(dokuToTest2, ); assert(!isSolved); + + MultiDoku dokuToTest3 = SudokuFactory.createBasicEmptySquareSudoku(3); + + Solver.solveRandom(dokuToTest3, ); + + SudokuPrinter.printRectangleSudoku(dokuToTest3.getSubGrid(0), 3, 3); } } \ No newline at end of file