refactor : SudokuFactory
All checks were successful
Linux arm64 / Build (push) Successful in 43s

This commit is contained in:
Melvyn
2025-02-02 16:38:04 +01:00
parent 1419898955
commit b4157167b5

View File

@@ -27,8 +27,11 @@ public class SudokuFactory {
* Comprend les contraintes de blocs, de lignes, et de colonnes. * Comprend les contraintes de blocs, de lignes, et de colonnes.
*/ */
public static List<IConstraint> DEFAULT_CONSTRAINTS = SudokuFactory public static List<IConstraint> DEFAULT_CONSTRAINTS = SudokuFactory
.fromConstraints(Arrays.asList(Constraint.Block, Constraint.Column, .fromConstraints(Arrays.asList(
Constraint.Line)); Constraint.Block,
Constraint.Column,
Constraint.Line)
);
/** /**
* Créée des Cells et les met dans une liste de taille size. * Créée des Cells et les met dans une liste de taille size.
@@ -65,9 +68,6 @@ public class SudokuFactory {
int index = ((y + blockY * height) * size + (x + blockX * width)); int index = ((y + blockY * height) * size + (x + blockX * width));
Cell blockCell = cells.get(index); Cell blockCell = cells.get(index);
blockCell.setBlock(newBlock); blockCell.setBlock(newBlock);
// List<Block> blockContainers = new ArrayList<>();
// blockContainers.add(newBlock);
// blockCell.setBlockContainers(blockContainers);
newBlock.addCell(blockCell); newBlock.addCell(blockCell);
} }
} }
@@ -99,62 +99,6 @@ public class SudokuFactory {
return new MultiDoku(List.of(createSquareSudoku(size, constraints))); return new MultiDoku(List.of(createSquareSudoku(size, constraints)));
} }
/**
* Place des Cells immutables de valeurs fournies, aux Coordinate fournies dans
* le MultiDoku doku fourni.
*
* @param doku MultiDoku, MultiDoku à remplir.
* @param immutableCells Map<Coordinate, Integer>, association de Coordinate
* coordonnées et Integer valeurs, correspondant aux cases
* à remplir.
*/
public static void setImmutableCells(MultiDoku doku, Map<Coordinate, Integer> immutableCells) {
immutableCells.forEach((coordinate, symbol) -> {
for (Sudoku sudoku : doku.getSubGrids()) {
Cell cell = sudoku.getCell(coordinate.getX(), coordinate.getY());
if (cell != null) {
cell.setSymbolIndex(symbol);
cell.setImmutable();
}
}
});
}
/**
* Créée un MultiDoku de difficulté difficulty à partir d'un MultiDoku fourni.
*
* @param doku MultiDoku, MultiDoku dont on doit vider des Cells.
* @param nbCellsToEmpty int, nombre de cases à retirer.
* @return boolean, valant true si un MultiDoku de difficulté donnée peut être
* créée, false sinon.
* @throws Exception si la difficulté n'est pas compatible avec la taille du
* MultiDoku.
*/
public static boolean newDokuFromFilledOne(MultiDoku doku, int nbCellsToEmpty, Solver solver) throws Exception {
if (nbCellsToEmpty >= doku.getCells().size()) {
throw new Exception();
}
if (nbCellsToEmpty == 0) {
return true;
}
List<Cell> cellsThatCanBeEmptied = doku.getFilledCells();
int index = random.nextInt(cellsThatCanBeEmptied.size());
Cell cellToEmpty = cellsThatCanBeEmptied.get(index);
cellToEmpty.empty();
int nbDokuSultions = solver.countSolution(doku);
if (nbDokuSultions == 1) {
return newDokuFromFilledOne(doku, --nbCellsToEmpty, solver);
}
return false;
}
/** /**
* Créée un Sudoku vide dont les Blocks sont de taille widthBlock par * Créée un Sudoku vide dont les Blocks sont de taille widthBlock par
* heightBlock. * heightBlock.
@@ -227,6 +171,9 @@ public class SudokuFactory {
* Créée un MultiDoku de Blocks carrés de taille size composé de cinq Sudokus, * Créée un MultiDoku de Blocks carrés de taille size composé de cinq Sudokus,
* dont un central qui partage chacun de ses Blockss d'angle avec un autre * dont un central qui partage chacun de ses Blockss d'angle avec un autre
* Sudoku. * Sudoku.
* 2 3
* 1
* 4 5
* *
* @param size int, largeur des Blocks unitraires des Sudokus à crééer. * @param size int, largeur des Blocks unitraires des Sudokus à crééer.
* @return MultiDoku, MultiDoku de forme X. * @return MultiDoku, MultiDoku de forme X.
@@ -238,24 +185,21 @@ public class SudokuFactory {
} }
/** /**
* Créée un MultiDoku de Blocks rectangulaires de forme width par height composé * Créée un MultiDoku de Blocks rectangulaires de forme X, de taille width par height composé
* de cinq Sudokus, * de cinq Sudokus,
* dont un central qui partage chacun de ses Blocks d'angle avec un autre * dont un central qui partage chacun de ses Blocks d'angle avec un autre
* Sudoku. * Sudoku.
* 2 3
* 1
* 4 5
* *
* @param width int, largeur des Blocks unitraires des Sudokus à crééer. * @param width int, largeur des Blocks unitaires des Sudokus à crééer.
* @param height int, hauteur des Blocks unitraires des Sudokus à crééer. * @param height int, hauteur des Blocks unitaires des Sudokus à crééer.
* @return MultiDoku, MultiDoku de forme X. * @return MultiDoku, MultiDoku de forme X.
*/ */
public static MultiDoku createBasicXShapedMultidoku(int width, int height, List<IConstraint> constraints) { public static MultiDoku createBasicXShapedMultidoku(int width, int height, List<IConstraint> constraints) {
assert (width > 1 && height > 1); assert (width > 1 && height > 1);
/*
* 2 3
* 1
* 4 5
*/
Sudoku sudoku1 = createRectangleSudoku(width, height, constraints); Sudoku sudoku1 = createRectangleSudoku(width, height, constraints);
Sudoku sudoku2 = createRectangleSudoku(width, height, constraints); Sudoku sudoku2 = createRectangleSudoku(width, height, constraints);
Sudoku sudoku3 = createRectangleSudoku(width, height, constraints); Sudoku sudoku3 = createRectangleSudoku(width, height, constraints);
@@ -271,13 +215,16 @@ public class SudokuFactory {
} }
/** /**
* TODO * Créée un MultiDoku de Blocks carrés de forme +, de taille size composé
* Créée un MultiDoku de Blocks carrés de taille size composé de cinq Sudokus, * de cinq Sudokus,
* dont un central qui partage chacun de ses Blockss d'angle avec un autre * dont un central qui partage chacun de ses Blocks de bord avec un autre
* Sudoku. * Sudoku.
* 3
* 2 1 4
* 5
* *
* @param size int, largeur des Blocks unitraires des Sudokus à crééer. * @param size int, largeur des Blocks unitaires des Sudokus à crééer.
* @return MultiDoku, MultiDoku de forme X. * @return MultiDoku, MultiDoku de forme +.
*/ */
public static MultiDoku createBasicPlusShapedMultidoku(int size, List<IConstraint> constraints) { public static MultiDoku createBasicPlusShapedMultidoku(int size, List<IConstraint> constraints) {
assert (size > 1); assert (size > 1);
@@ -286,24 +233,20 @@ public class SudokuFactory {
} }
/** /**
* TODO * Créée un MultiDoku de Blocks rectangulaires de forme +, de taille width par height composé
* Créée un MultiDoku de Blocks rectangulaires de forme width par height composé
* de cinq Sudokus, * de cinq Sudokus,
* dont un central qui partage chacun de ses Blocks d'angle avec un autre * dont un central qui partage chacun de ses Blocks de bord avec un autre
* Sudoku. * Sudoku.
*
* @param width int, largeur des Blocks unitraires des Sudokus à crééer.
* @param height int, hauteur des Blocks unitraires des Sudokus à crééer.
* @return MultiDoku, MultiDoku de forme X.
*/
public static MultiDoku createBasicPlusShapedMultidoku(int width, int height, List<IConstraint> constraints) {
assert (width > 1 && height > 1);
/*
* 3 * 3
* 2 1 4 * 2 1 4
* 5 * 5
*
* @param width int, largeur des Blocks unitaires des Sudokus à crééer.
* @param height int, hauteur des Blocks unitaires des Sudokus à crééer.
* @return MultiDoku, MultiDoku de forme +.
*/ */
public static MultiDoku createBasicPlusShapedMultidoku(int width, int height, List<IConstraint> constraints) {
assert (width > 1 && height > 1);
Sudoku sudoku1 = createRectangleSudoku(width, height, constraints); Sudoku sudoku1 = createRectangleSudoku(width, height, constraints);
Sudoku sudoku2 = createRectangleSudoku(width, height, constraints); Sudoku sudoku2 = createRectangleSudoku(width, height, constraints);
@@ -319,25 +262,13 @@ public class SudokuFactory {
return new MultiDoku(Arrays.asList(sudoku1, sudoku2, sudoku3, sudoku4, sudoku5)); return new MultiDoku(Arrays.asList(sudoku1, sudoku2, sudoku3, sudoku4, sudoku5));
} }
public static void fillDoku(MultiDoku doku, Difficulty difficulty) throws Exception { /**
Solver solver = new RandomSolver(); * Crée un Sudoku vide avec les Blocks aléatoires.
solver.solve(doku); *
int nbCellsToEmpty = (int) (difficulty.getFactor() * doku.getNbCells()); * @param blockSize int, la taille des Block.
boolean successfull = newDokuFromFilledOne(doku, nbCellsToEmpty, solver); * @param constraints List<IConstraint>, la liste des contraintes.
doku.setFilledCellsImmutable(); * @return MultiDoku, avec un seul Sudoku.
} */
public static MultiDoku fromfile(String filePath) {
try {
String content = Files.readString(Paths.get(filePath));
MultiDoku doku = SudokuSerializer.deserializeSudoku(content);
return doku;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static MultiDoku createBasicEmptyRandomBlockDoku(int blockSize, List<IConstraint> constraints) { public static MultiDoku createBasicEmptyRandomBlockDoku(int blockSize, List<IConstraint> constraints) {
int blockCellCount = blockSize * blockSize; int blockCellCount = blockSize * blockSize;
List<Cell> cells = initCells(blockCellCount); List<Cell> cells = initCells(blockCellCount);
@@ -361,6 +292,76 @@ public class SudokuFactory {
return new MultiDoku(List.of(sudoku)); return new MultiDoku(List.of(sudoku));
} }
/**
* Créée un MultiDoku de difficulté difficulty à partir d'un MultiDoku fourni.
*
* @param doku MultiDoku, MultiDoku dont on doit vider des Cells.
* @param nbCellsToEmpty int, nombre de cases à retirer.
* @return boolean, valant true si un MultiDoku de difficulté donnée peut être
* créée, false sinon.
* @throws Exception si la difficulté n'est pas compatible avec la taille du
* MultiDoku.
*/
public static boolean newDokuFromFilledOne(MultiDoku doku, int nbCellsToEmpty, Solver solver) throws Exception {
if (nbCellsToEmpty >= doku.getCells().size()) {
throw new Exception();
}
if (nbCellsToEmpty == 0) {
return true;
}
List<Cell> cellsThatCanBeEmptied = doku.getFilledCells();
int index = random.nextInt(cellsThatCanBeEmptied.size());
Cell cellToEmpty = cellsThatCanBeEmptied.get(index);
cellToEmpty.empty();
int nbDokuSultions = solver.countSolution(doku);
if (nbDokuSultions == 1) {
return newDokuFromFilledOne(doku, --nbCellsToEmpty, solver);
}
return false;
}
/**
* Rempli un MultiDoku donné par rapport à un difficulté.
*
* @param doku MultiDoku, vide.
* @param difficulty Difficulty, qui correspond au pourcentage de cases à enlever.
*/
public static void fillDoku(MultiDoku doku, Difficulty difficulty) throws Exception {
Solver solver = new RandomSolver();
solver.solve(doku);
int nbCellsToEmpty = (int) (difficulty.getFactor() * doku.getNbCells());
newDokuFromFilledOne(doku, nbCellsToEmpty, solver);
doku.setFilledCellsImmutable();
}
/**
* Génère un MultiDoku à partir d'un fichier de sauvegarde.
*
* @param filePath String, chemin du fichier.
* @return MultiDoku.
*/
public static MultiDoku fromfile(String filePath) {
try {
String content = Files.readString(Paths.get(filePath));
return SudokuSerializer.deserializeSudoku(content);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* Transforme des Constraint en IConstraint correspondants
* @param constraints List<Constraints>
* @return List<IConstraints>
*/
public static List<IConstraint> fromConstraints(List<Constraint> constraints) { public static List<IConstraint> fromConstraints(List<Constraint> constraints) {
List<IConstraint> iconstraints = new ArrayList<>(); List<IConstraint> iconstraints = new ArrayList<>();
for (Constraint cons : constraints) { for (Constraint cons : constraints) {