feat : generation de doku par rapport à une difficulté
Some checks are pending
Linux arm64 / Build (push) Waiting to run
Some checks are pending
Linux arm64 / Build (push) Waiting to run
This commit is contained in:
@@ -11,11 +11,11 @@ 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.
|
||||
* En testant toutes les possibilités, de manière aléatoire, 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.
|
||||
* @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.
|
||||
*/
|
||||
public static boolean solveRandom(MultiDoku doku, Random rand) {
|
||||
if (Thread.interrupted())
|
||||
@@ -39,15 +39,40 @@ public class Solver {
|
||||
cellToFill.setSymbolIndex(nextSymbol);
|
||||
if (Solver.solveRandom(doku, rand)) {
|
||||
return true;
|
||||
} else {
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
possibleSymbols.remove(nextPossibleSymbolIndex);
|
||||
}
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
possibleSymbols.remove(nextPossibleSymbolIndex);
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int countSolution(MultiDoku doku) {
|
||||
int result = 0;
|
||||
|
||||
if (doku.isValid()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Cell cellToFill = doku.getFirstEmptyCell();
|
||||
if (cellToFill == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<Integer> possibleSymbols = doku.getPossibleSymbolsOfCell(cellToFill);
|
||||
|
||||
for (int symbol : possibleSymbols) {
|
||||
|
||||
cellToFill.setSymbolIndex(symbol);
|
||||
if (Solver.solve(doku)) {
|
||||
result++;
|
||||
}
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean solve(MultiDoku doku) {
|
||||
if (Thread.interrupted())
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
|
||||
@@ -77,4 +77,10 @@ public class Cell {
|
||||
public boolean isMutable() {
|
||||
return this.isMutable;
|
||||
}
|
||||
|
||||
public int empty() {
|
||||
int oldSymbol = this.symbolIndex;
|
||||
this.symbolIndex = Cell.NOSYMBOL;
|
||||
return oldSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,5 +98,21 @@ public class MultiDoku {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Cell> getFilledCells() {
|
||||
List<Cell> result = new ArrayList<>();
|
||||
for (Cell c : this.getCells()){
|
||||
if (!c.isEmpty()) {
|
||||
result.add(c);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void empty(Cell cell) {
|
||||
List<Cell> cells = getCells();
|
||||
Cell cellToEmpty = cells.get(cells.indexOf(cell));
|
||||
cellToEmpty.setSymbolIndex(Cell.NOSYMBOL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -287,4 +287,8 @@ public class Sudoku {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void empty(Cell cell) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,17 @@ import sudoku.constraint.BlockConstraint;
|
||||
import sudoku.constraint.ColumnConstraint;
|
||||
import sudoku.constraint.IConstraint;
|
||||
import sudoku.constraint.LineConstraint;
|
||||
import sudoku.structure.*;
|
||||
import sudoku.solver.Solver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class SudokuFactory {
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
private static List<Cell> initCells(int size) {
|
||||
List<Cell> cells = new ArrayList<>(size * size);
|
||||
for (int i = 0; i < size * size; i++) {
|
||||
@@ -72,4 +75,35 @@ public class SudokuFactory {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean newDokuFromFilledOne (MultiDoku doku, int difficulty) throws Exception {
|
||||
|
||||
if (difficulty > doku.getCells().size()) {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
if (difficulty == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Cell> cellsThatCanBeEmptied = doku.getFilledCells();
|
||||
|
||||
while (!cellsThatCanBeEmptied.isEmpty()) {
|
||||
int index = random.nextInt(cellsThatCanBeEmptied.size());
|
||||
Cell cellToEmpty = cellsThatCanBeEmptied.get(index);
|
||||
|
||||
int oldSymbol = cellToEmpty.empty();
|
||||
|
||||
if (Solver.countSolution(doku) == 1) {
|
||||
if (newDokuFromFilledOne(doku, --difficulty)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
cellToEmpty.setSymbolIndex(oldSymbol);
|
||||
cellsThatCanBeEmptied.remove(cellToEmpty);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user