Merge branch 'master' of git.ale-pri.com:Ryuk/Sudoku
All checks were successful
Linux arm64 / Build (push) Successful in 37s

This commit is contained in:
2025-01-30 13:21:05 +01:00
6 changed files with 54 additions and 18 deletions

View File

@@ -82,7 +82,7 @@ public class SudokuView extends BaseView {
resolveThread = new Thread(() -> { resolveThread = new Thread(() -> {
try { try {
Random rand = new Random(); Random rand = new Random();
Solver.solveRandom(doku, rand); Solver.randomSolve(doku, rand);
Thread.sleep(200); Thread.sleep(200);
} catch (CancellationException | InterruptedException e) { } catch (CancellationException | InterruptedException e) {
System.out.println("The user is bored !"); System.out.println("The user is bored !");

View File

@@ -133,7 +133,7 @@ public class ConsoleInterface {
} }
private void generateFullDoku(MultiDoku doku) { private void generateFullDoku(MultiDoku doku) {
Solver.solveRandom(doku, new Random()); Solver.randomSolve(doku, new Random());
} }
} }

View File

@@ -27,7 +27,7 @@ public class Solver {
* @param rand Random, pour tester aléatoirement les symboles * @param rand Random, pour tester aléatoirement les symboles
* @return boolean, true s'il est résolu ou false s'il ne l'est pas. * @return boolean, true s'il est résolu ou false s'il ne l'est pas.
*/ */
public static boolean solveRandom(MultiDoku doku, Random rand) { public static boolean randomSolve(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");
@@ -53,7 +53,7 @@ public class Solver {
int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex); int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex);
cellToFill.setSymbolIndex(nextSymbol); cellToFill.setSymbolIndex(nextSymbol);
if (Solver.solveRandom(doku, rand)) { if (Solver.randomSolve(doku, rand)) {
return true; return true;
} }
cellToFill.setSymbolIndex(Cell.NOSYMBOL); cellToFill.setSymbolIndex(Cell.NOSYMBOL);
@@ -65,7 +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 oldDoku 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.
*/ */
public static int countSolution(MultiDoku doku) { public static int countSolution(MultiDoku doku) {
@@ -130,7 +130,7 @@ public class Solver {
} }
/** /**
* Résout le MultiDoku passé en paramètre, sans backtracking. * 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.
*/ */
@@ -169,4 +169,45 @@ public class Solver {
return doku.isSolved(); return doku.isSolved();
} }
/**
* 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.
*/
public static boolean mixedSolve(MultiDoku doku) {
if (Thread.interrupted())
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();
}
} }

View File

@@ -11,12 +11,7 @@ import java.util.Random;
import sudoku.io.SudokuSerializer; import sudoku.io.SudokuSerializer;
import sudoku.constraint.BlockConstraint;
import sudoku.constraint.ColumnConstraint;
import sudoku.constraint.Constraint; import sudoku.constraint.Constraint;
import sudoku.constraint.DiagonalConstraint;
import sudoku.constraint.IConstraint;
import sudoku.constraint.LineConstraint;
import sudoku.solver.Solver; import sudoku.solver.Solver;
public class SudokuFactory { public class SudokuFactory {
@@ -277,7 +272,7 @@ public class SudokuFactory {
} }
public static void fillDoku(MultiDoku doku, Difficulty difficulty) throws Exception { public static void fillDoku(MultiDoku doku, Difficulty difficulty) throws Exception {
Solver.solveRandom(doku, random); Solver.randomSolve(doku, random);
int nbCellsToEmpty = (int) (difficulty.getFactor() * doku.getNbCells()); int nbCellsToEmpty = (int) (difficulty.getFactor() * doku.getNbCells());
boolean successfull = newDokuFromFilledOne(doku, nbCellsToEmpty); boolean successfull = newDokuFromFilledOne(doku, nbCellsToEmpty);
if (!successfull) { if (!successfull) {

View File

@@ -19,7 +19,7 @@ public class SudokuSerializerTest {
void testSerializeWithSize(int blockWidth, int blockHeight) { void testSerializeWithSize(int blockWidth, int blockHeight) {
var sudoku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight, var sudoku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight,
SudokuFactory.DEFAULT_CONSTRAINTS); SudokuFactory.DEFAULT_CONSTRAINTS);
Solver.solveRandom(sudoku, new Random()); Solver.randomSolve(sudoku, new Random());
JSONObject data = SudokuSerializer.serializeSudoku(sudoku); JSONObject data = SudokuSerializer.serializeSudoku(sudoku);
MultiDoku multiDoku = SudokuSerializer.deserializeSudoku(data); MultiDoku multiDoku = SudokuSerializer.deserializeSudoku(data);
assertTrue(data.toString().equals(SudokuSerializer.serializeSudoku(multiDoku).toString())); assertTrue(data.toString().equals(SudokuSerializer.serializeSudoku(multiDoku).toString()));
@@ -28,7 +28,7 @@ public class SudokuSerializerTest {
void testSaveWithSize(int blockWidth, int blockHeight) { void testSaveWithSize(int blockWidth, int blockHeight) {
MultiDoku doku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight, MultiDoku doku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight,
SudokuFactory.DEFAULT_CONSTRAINTS); SudokuFactory.DEFAULT_CONSTRAINTS);
Solver.solveRandom(doku, new Random()); Solver.randomSolve(doku, new Random());
String savePath = SudokuSerializer.saveMultiDoku(doku); String savePath = SudokuSerializer.saveMultiDoku(doku);
MultiDoku otherDoku = null; MultiDoku otherDoku = null;
try { try {
@@ -47,7 +47,7 @@ public class SudokuSerializerTest {
void testSerializeX(int size) { void testSerializeX(int size) {
var sudoku = SudokuFactory.createBasicXShapedMultidoku(size, SudokuFactory.DEFAULT_CONSTRAINTS); var sudoku = SudokuFactory.createBasicXShapedMultidoku(size, SudokuFactory.DEFAULT_CONSTRAINTS);
Solver.solveRandom(sudoku, new Random()); Solver.randomSolve(sudoku, new Random());
JSONObject data = SudokuSerializer.serializeSudoku(sudoku); JSONObject data = SudokuSerializer.serializeSudoku(sudoku);
MultiDoku multiDoku = SudokuSerializer.deserializeSudoku(data); MultiDoku multiDoku = SudokuSerializer.deserializeSudoku(data);

View File

@@ -57,7 +57,7 @@ class SolverTest {
assert (dokuResult.isSolved()); assert (dokuResult.isSolved());
Solver.solveRandom(dokuToTest, rand); Solver.randomSolve(dokuToTest, rand);
System.out.println("\n****************************\nDoku solved"); System.out.println("\n****************************\nDoku solved");
SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3); SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
@@ -89,13 +89,13 @@ class SolverTest {
5, ns, ns, ns, 3, 1, 0, ns, ns); 5, ns, ns, ns, 3, 1, 0, ns, ns);
sudokuToTest2.setImmutableCellsSymbol(immutableCells2); sudokuToTest2.setImmutableCellsSymbol(immutableCells2);
boolean isSolved = Solver.solveRandom(dokuToTest2, rand); boolean isSolved = Solver.randomSolve(dokuToTest2, rand);
assert (!isSolved); assert (!isSolved);
MultiDoku dokuToTest3 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS); MultiDoku dokuToTest3 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
Solver.solveRandom(dokuToTest3, rand); Solver.randomSolve(dokuToTest3, rand);
SudokuPrinter.printRectangleSudoku(dokuToTest3.getSubGrid(0), 3, 3); SudokuPrinter.printRectangleSudoku(dokuToTest3.getSubGrid(0), 3, 3);
} }