feat: dynamic constraints (Fixes #8)
All checks were successful
Linux arm64 / Build (push) Successful in 37s
All checks were successful
Linux arm64 / Build (push) Successful in 37s
This commit is contained in:
@@ -11,6 +11,8 @@ import java.util.Random;
|
||||
|
||||
import sudoku.constraint.BlockConstraint;
|
||||
import sudoku.constraint.ColumnConstraint;
|
||||
import sudoku.constraint.Constraint;
|
||||
import sudoku.constraint.DiagonalConstraint;
|
||||
import sudoku.constraint.IConstraint;
|
||||
import sudoku.constraint.LineConstraint;
|
||||
import sudoku.io.SudokuSerializer;
|
||||
@@ -27,10 +29,12 @@ public class SudokuFactory {
|
||||
* Liste des contraintes par défaut d'un Multi- ou Sudoku.
|
||||
* Comprend les contraintes de blocs, de lignes, et de colonnes.
|
||||
*/
|
||||
public static List<IConstraint> DEFAULT_CONSTRAINTS = Arrays.asList(new BlockConstraint(), new LineConstraint(), new ColumnConstraint());
|
||||
public static List<Constraint> DEFAULT_CONSTRAINTS = Arrays.asList(Constraint.Block, Constraint.Column,
|
||||
Constraint.Line);
|
||||
|
||||
/**
|
||||
* Créée des Cells et les met dans une liste de taille size.
|
||||
*
|
||||
* @param size int, nombre de Cells à initialiser.
|
||||
* @return List<Cell>, liste des Cells initialisées.
|
||||
*/
|
||||
@@ -43,9 +47,11 @@ public class SudokuFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Créée des Blocks de taille width par height à partir des cellules données, et les met dans une liste.
|
||||
* @param cells List<Cell>, liste des Cells à découper en Blocks.
|
||||
* @param width int, largeur des Blocks à créer.
|
||||
* Créée des Blocks de taille width par height à partir des cellules données, et
|
||||
* les met dans une liste.
|
||||
*
|
||||
* @param cells List<Cell>, liste des Cells à découper en Blocks.
|
||||
* @param width int, largeur des Blocks à créer.
|
||||
* @param height int, hauteur des Blocks à créer.
|
||||
* @return List<Block>, liste des Blocks créés.
|
||||
*/
|
||||
@@ -73,29 +79,36 @@ public class SudokuFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Créée un MultiDoku vide dont les Blocks sont de taille widthBlock par heightBlock.
|
||||
* @param widthBlock int, largeur des Blocks.
|
||||
* Créée un MultiDoku vide dont les Blocks sont de taille widthBlock par
|
||||
* heightBlock.
|
||||
*
|
||||
* @param widthBlock int, largeur des Blocks.
|
||||
* @param heightBlock int, hauteur des Blocks.
|
||||
* @return MultiDoku, MultiDoku vide.
|
||||
*/
|
||||
public static MultiDoku createBasicEmptyRectangleSudoku(int widthBlock, int heightBlock) {
|
||||
Sudoku s = createRectangleSudoku(widthBlock, heightBlock);
|
||||
return new MultiDoku(Arrays.asList(s));
|
||||
public static MultiDoku createBasicEmptyRectangleDoku(int widthBlock, int heightBlock,
|
||||
List<Constraint> constraints) {
|
||||
return new MultiDoku(Arrays.asList(createRectangleSudoku(widthBlock, heightBlock, constraints)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Créée un MultiDoku vide dont les Blocks sont carrés de longueur size.
|
||||
*
|
||||
* @param size int, taille des Blocks.
|
||||
* @return MultiDoku, MultiDoku vide.
|
||||
*/
|
||||
public static MultiDoku createBasicEmptySquareSudoku(int size) {
|
||||
return createBasicEmptyRectangleSudoku(size, size);
|
||||
public static MultiDoku createBasicEmptySquareDoku(int size, List<Constraint> constraints) {
|
||||
return new MultiDoku(Arrays.asList(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.
|
||||
* 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) -> {
|
||||
@@ -114,10 +127,12 @@ public class SudokuFactory {
|
||||
*
|
||||
* @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.
|
||||
* @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) throws Exception {
|
||||
public static boolean newDokuFromFilledOne(MultiDoku doku, int nbCellsToEmpty) throws Exception {
|
||||
|
||||
if (nbCellsToEmpty > doku.getCells().size()) {
|
||||
throw new Exception();
|
||||
@@ -149,34 +164,41 @@ public class SudokuFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Créée un Sudoku vide dont les Blocks sont de taille widthBlock par heightBlock.
|
||||
* @param widthBlock int, largeur des Blocks.
|
||||
* Créée un Sudoku vide dont les Blocks sont de taille widthBlock par
|
||||
* heightBlock.
|
||||
*
|
||||
* @param widthBlock int, largeur des Blocks.
|
||||
* @param heightBlock int, hauteur des Blocks.
|
||||
* @return Sudoku, Sudoku vide.
|
||||
*/
|
||||
private static Sudoku createRectangleSudoku(int widthBlock, int heightBlock) {
|
||||
private static Sudoku createRectangleSudoku(int widthBlock, int heightBlock, List<Constraint> constraints) {
|
||||
int symbolCount = widthBlock * heightBlock;
|
||||
List<Cell> cases = initCells(symbolCount);
|
||||
List<Block> blocs = initRectangleBlocs(cases, widthBlock, heightBlock);
|
||||
Sudoku s = new Sudoku(cases, blocs, DEFAULT_CONSTRAINTS);
|
||||
Sudoku s = new Sudoku(cases, blocs, constraints);
|
||||
for (Block block : s.getBlocks()) {
|
||||
block.getSudokus().add(s);
|
||||
}
|
||||
s.setBlockWidth(widthBlock);
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Créée un Sudoku vide dont les Blocks sont carrés de longueur size.
|
||||
*
|
||||
* @param size int, taille des Blocks.
|
||||
* @return Sudoku, Sudoku vide.
|
||||
*/
|
||||
private static Sudoku createSquareSudoku(int size) {
|
||||
return createRectangleSudoku(size, size);
|
||||
private static Sudoku createSquareSudoku(int size, List<Constraint> constraints) {
|
||||
return createRectangleSudoku(size, size, constraints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connecte deux Sudokus selon la décalage offset fourni.
|
||||
*
|
||||
* @param sudoku1 Sudoku, premier sudoku à connecter.
|
||||
* @param sudoku2 Sudoku, second sudoku à connecter.
|
||||
* @param offset Coordinate, décalage entre les deux Sudokus.
|
||||
* @param offset Coordinate, décalage entre les deux Sudokus.
|
||||
*/
|
||||
private static void linkSquareSudokus(Sudoku sudoku1, Sudoku sudoku2, Coordinate offset) {
|
||||
int blockWidth = sudoku1.getBlockWidth();
|
||||
@@ -193,6 +215,7 @@ public class SudokuFactory {
|
||||
|
||||
// on remplace le bloc
|
||||
sudoku2.getBlocks().set(block2Y * blockWidth + block2X, block1);
|
||||
block1.getSudokus().add(sudoku2);
|
||||
|
||||
// on remplace les cellules
|
||||
for (int i = 0; i < block1.getCells().size(); i++) {
|
||||
@@ -208,24 +231,27 @@ public class SudokuFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Sudoku.
|
||||
* 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
|
||||
* Sudoku.
|
||||
*
|
||||
* @param size int, largeur des Blocks unitraires des Sudokus à crééer.
|
||||
* @return MultiDoku, MultiDoku de forme X.
|
||||
*/
|
||||
public static MultiDoku createBasicXShapedMultidoku(int size) {
|
||||
public static MultiDoku createBasicXShapedMultidoku(int size, List<Constraint> constraints) {
|
||||
assert (size > 1);
|
||||
|
||||
/*
|
||||
* 2 3
|
||||
* 1
|
||||
* 1
|
||||
* 4 5
|
||||
*/
|
||||
|
||||
Sudoku sudoku1 = createSquareSudoku(size);
|
||||
Sudoku sudoku2 = createSquareSudoku(size);
|
||||
Sudoku sudoku3 = createSquareSudoku(size);
|
||||
Sudoku sudoku4 = createSquareSudoku(size);
|
||||
Sudoku sudoku5 = createSquareSudoku(size);
|
||||
Sudoku sudoku1 = createSquareSudoku(size, constraints);
|
||||
Sudoku sudoku2 = createSquareSudoku(size, constraints);
|
||||
Sudoku sudoku3 = createSquareSudoku(size, constraints);
|
||||
Sudoku sudoku4 = createSquareSudoku(size, constraints);
|
||||
Sudoku sudoku5 = createSquareSudoku(size, constraints);
|
||||
|
||||
linkSquareSudokus(sudoku1, sudoku2, new Coordinate(1 - size, 1 - size));
|
||||
linkSquareSudokus(sudoku1, sudoku3, new Coordinate(size - 1, 1 - size));
|
||||
@@ -237,7 +263,7 @@ public class SudokuFactory {
|
||||
|
||||
public static void fillDoku(MultiDoku doku, Difficulty difficulty) throws Exception {
|
||||
Solver.solveRandom(doku, random);
|
||||
int nbCellsToEmpty = (int)(difficulty.getFactor()*doku.getNbCells());
|
||||
int nbCellsToEmpty = (int) (difficulty.getFactor() * doku.getNbCells());
|
||||
boolean successfull = newDokuFromFilledOne(doku, nbCellsToEmpty);
|
||||
if (!successfull) {
|
||||
throw new Exception("Canno't create this doku with this difficulty");
|
||||
|
||||
Reference in New Issue
Block a user