diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..efd7cbf --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..03872dd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..1fee3bf --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1737463425999 + + + 1737463425999 + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/sudoku/ContrainteBloc.java b/app/src/main/java/sudoku/ContrainteBloc.java index a0c27f9..5a1e3f3 100644 --- a/app/src/main/java/sudoku/ContrainteBloc.java +++ b/app/src/main/java/sudoku/ContrainteBloc.java @@ -1,7 +1,5 @@ package sudoku; -import sudoku.core.Console; - public class ContrainteBloc implements Contrainte { @Override public boolean estRespectee(Grille grille, Case c) { @@ -14,7 +12,6 @@ public class ContrainteBloc implements Contrainte { for (int j = 0; j < blocSize; j++) { Case currentCase = grille.getCase(startRow + i, startCol + j); if (currentCase != c && currentCase.getSymbole() != null && currentCase.getSymbole().equals(symbole)) { - Console.errorln("La contrainte de bloc n'est pas respectee: ligne=" + (startRow + i) + ", col=" + (startCol + j) + ", symbole=" + symbole); return false; } } diff --git a/app/src/main/java/sudoku/ContrainteColonne.java b/app/src/main/java/sudoku/ContrainteColonne.java index c0744cd..d7e1464 100644 --- a/app/src/main/java/sudoku/ContrainteColonne.java +++ b/app/src/main/java/sudoku/ContrainteColonne.java @@ -1,7 +1,5 @@ package sudoku; -import sudoku.core.Console; - public class ContrainteColonne implements Contrainte { @Override public boolean estRespectee(Grille grille, Case c) { @@ -10,7 +8,6 @@ public class ContrainteColonne implements Contrainte { for (int ligne = 0; ligne < grille.getTaille(); ligne++) { Case currentCase = grille.getCase(ligne, colonne); if (currentCase != c && currentCase.getSymbole() != null && currentCase.getSymbole().equals(symbole)) { - Console.errorln("La contrainte de colonne n'est pas respectee: ligne=" + ligne + ", col=" + colonne + ", symbole=" + symbole); return false; } } diff --git a/app/src/main/java/sudoku/ContrainteLigne.java b/app/src/main/java/sudoku/ContrainteLigne.java index 4a3ca55..464da89 100644 --- a/app/src/main/java/sudoku/ContrainteLigne.java +++ b/app/src/main/java/sudoku/ContrainteLigne.java @@ -1,7 +1,5 @@ package sudoku; -import sudoku.core.Console; - public class ContrainteLigne implements Contrainte { @Override public boolean estRespectee(Grille grille, Case c) { @@ -10,7 +8,6 @@ public class ContrainteLigne implements Contrainte { for (int col = 0; col < grille.getTaille(); col++) { Case currentCase = grille.getCase(ligne, col); if (currentCase != c && currentCase.getSymbole() != null && currentCase.getSymbole().equals(symbole)) { - Console.errorln("La contrainte de ligne n'est pas respectee: ligne=" + ligne + ", col=" + col + ", symbole=" + symbole); return false; } } diff --git a/app/src/main/java/sudoku/Grille.java b/app/src/main/java/sudoku/Grille.java index 288c679..ff6021f 100644 --- a/app/src/main/java/sudoku/Grille.java +++ b/app/src/main/java/sudoku/Grille.java @@ -11,12 +11,14 @@ public class Grille { private final Case[][] cases; private final ArrayList blocs; private ArrayList symbolesPossibles; + private final Sudoku sudoku; - public Grille(int taille) { + public Grille(int taille, Sudoku sudoku) { this.taille = taille; this.cases = new Case[taille][taille]; this.blocs = new ArrayList<>(); this.symbolesPossibles = new ArrayList<>(); + this.sudoku = sudoku; // Initialiser les cases for (int i = 0; i < taille; i++) { @@ -31,11 +33,22 @@ public class Grille { if (symbole != null && !symbolesPossibles.contains(symbole)) { throw new IllegalArgumentException("Symbole non autorisé : " + symbole); } + // Save ancien symbole + Symbole ancienSymbole = cases[ligne][colonne].getSymbole(); + + // Set nouveau symbole cases[ligne][colonne].setSymbole(symbole); + + // Vérifier les contraintes + if (!sudoku.verifierToutesContraintes()) { + // Revert to ancien symbole + cases[ligne][colonne].setSymbole(ancienSymbole); + throw new IllegalArgumentException("SET CASE: Les contraintes ne sont pas respectées pour la case (" + + ligne + ", " + colonne + ")"); + } } catch (Exception e) { Console.errorln(e.getMessage()); } - } public Case getCase(int ligne, int colonne) { @@ -49,9 +62,10 @@ public class Grille { "\u001B[33m" // Jaune }; - private int getCouleurDisponible(int blocRow, int blocCol) { + private int getCouleurDisponible(int blocRow, int blocCol, int blocHeight, int blocWidth) { List couleursUtilisees = new ArrayList<>(); - int blocSize = (int) Math.sqrt(taille); + int blocsParLigne = taille / blocWidth; + int blocsParColonne = taille / blocHeight; // Parcourir les voisins (haut, bas, gauche, droite, et diagonaux) for (int dRow = -1; dRow <= 1; dRow++) { @@ -63,9 +77,9 @@ public class Grille { int voisinCol = blocCol + dCol; // Vérifier si le voisin est dans les limites - if (voisinRow >= 0 && voisinRow < taille / blocSize && - voisinCol >= 0 && voisinCol < taille / blocSize) { - int blockIndex = voisinRow * (taille / blocSize) + voisinCol; + if (voisinRow >= 0 && voisinRow < blocsParColonne && + voisinCol >= 0 && voisinCol < blocsParLigne) { + int blockIndex = voisinRow * blocsParLigne + voisinCol; if (blockIndex < blocs.size()) { couleursUtilisees.add(blocs.get(blockIndex).getCouleurIndex()); } @@ -102,19 +116,7 @@ public class Grille { * @param positions * @return */ - public Bloc creerBloc(List positions) { - int i = positions.get(0)[0]; - int j = positions.get(0)[1]; - int blocSize = (int) Math.sqrt(taille); - int couleurIndex = getCouleurDisponible(i / blocSize, j / blocSize); - - Bloc bloc = new Bloc(QUATRE_COULEURS[couleurIndex], couleurIndex); - for (int[] pos : positions) { - bloc.ajouterCase(cases[pos[0]][pos[1]]); - } - blocs.add(bloc); - return bloc; - } + // TODO : Refactor to use BlocBuilder public void creerBlocCarre() { try { @@ -138,7 +140,55 @@ public class Grille { } } - int couleurIndex = getCouleurDisponible(blocRow, blocCol); + int couleurIndex = getCouleurDisponible(blocRow, blocCol, blocSize, blocSize); + Bloc bloc = new Bloc(QUATRE_COULEURS[couleurIndex], couleurIndex); + + for (int[] pos : positions) { + bloc.ajouterCase(cases[pos[0]][pos[1]]); + } + blocs.add(bloc); + } + } + } catch (IllegalArgumentException e) { + Console.errorln(e.getMessage()); + } + } + + /** + * Crée des blocs rectangles automatiquement à partir de la taille de la grille + * Ne fonctionne pas pour les tailles de grilles qui sont des carrés parfaits + * + * @param blocRow + * @param blocCol + * @param blocHeight + * @param blocWidth + */ + public void creerBlocRectangulaire(int blocHeight, int blocWidth) { + try { + if (taille % blocHeight != 0 || taille % blocWidth != 0) { + throw new IllegalArgumentException( + "La taille de la grille doit être divisible par les dimensions des blocs."); + } + + int blocsParLigne = taille / blocWidth; + int blocsParColonne = taille / blocHeight; + + // Create blocks in rectangular pattern + for (int blocRow = 0; blocRow < blocsParColonne; blocRow++) { + for (int blocCol = 0; blocCol < blocsParLigne; blocCol++) { + List positions = new ArrayList<>(); + + // Add all positions for current block + for (int i = 0; i < blocHeight; i++) { + for (int j = 0; j < blocWidth; j++) { + positions.add(new int[] { + blocRow * blocHeight + i, + blocCol * blocWidth + j + }); + } + } + + int couleurIndex = getCouleurDisponible(blocRow, blocCol, blocHeight, blocWidth); Bloc bloc = new Bloc(QUATRE_COULEURS[couleurIndex], couleurIndex); for (int[] pos : positions) { @@ -266,6 +316,7 @@ public class Grille { /** * Vérifie si toutes les contraintes sont respectées * S'arrête dès qu'une contrainte n'est pas respectée + * * @param contraintes * @return */ @@ -279,7 +330,8 @@ public class Grille { // Vérifier toutes les contraintes pour cette case for (Contrainte contrainte : contraintes) { if (!contrainte.estRespectee(this, currentCase)) { - Console.errorln("Contrainte non respectée à la position : ligne=" + i + ", colonne=" + j); + Console.errorln( + "GRILLE: Contrainte non respectée à la position : ligne=" + i + ", colonne=" + j); return false; } } @@ -289,7 +341,52 @@ public class Grille { return true; } + public Case getCaseLibre() { + for (int i = 0; i < taille; i++) { + for (int j = 0; j < taille; j++) { + if (cases[i][j].getSymbole() == null) { + return cases[i][j]; + } + } + } + return null; + } + + public int getLongueurSymboleLePlusLong() { + int max = 0; + for (Symbole symbole : symbolesPossibles) { + if (symbole.toString().length() > max) { + max = symbole.toString().length(); + } + } + return max; + } + @Override + // public String toString() { + // StringBuilder sb = new StringBuilder(); + // int plusLongSymbole = this.getLongueurSymboleLePlusLong(); + + // for (int i = 0; i < taille; i++) { + // for (int j = 0; j < taille; j++) { + // Case currentCase = cases[i][j]; + // Bloc bloc = findBlocForCase(currentCase); + + // if (bloc != null) { + // sb.append(bloc.getCouleur()) // Couleur du bloc + // .append(" ".repeat(plusLongSymbole - currentCase.toString().length())) // Alignement + // .append(currentCase.toString()) + // .append("\u001B[0m ") // Réinitialiser la couleur + // .append(" "); + // } else { + // sb.append(currentCase.toString()).append(" "); + // } + // } + // sb.append("\n"); + // } + + // return sb.toString(); + // } public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/app/src/main/java/sudoku/Resolveur.java b/app/src/main/java/sudoku/Resolveur.java new file mode 100644 index 0000000..9b0e5ee --- /dev/null +++ b/app/src/main/java/sudoku/Resolveur.java @@ -0,0 +1,5 @@ +package sudoku; + +public interface Resolveur { + boolean resoudre(Sudoku s, boolean afficherEtape); +} diff --git a/app/src/main/java/sudoku/ResolveurBacktraceSimple.java b/app/src/main/java/sudoku/ResolveurBacktraceSimple.java new file mode 100644 index 0000000..6509f79 --- /dev/null +++ b/app/src/main/java/sudoku/ResolveurBacktraceSimple.java @@ -0,0 +1,62 @@ +package sudoku; + +import java.util.List; + +public class ResolveurBacktraceSimple implements Resolveur { + + private final Sudoku sudoku; + + public ResolveurBacktraceSimple(Sudoku sudoku) { + this.sudoku = sudoku; + } + + @Override + public boolean resoudre(Sudoku s, boolean afficherEtape) { + EtatResolution etat = new EtatResolution(0, 0); + return resoudre(s, afficherEtape, etat); + } + + private boolean resoudre(Sudoku s, boolean afficherEtape, EtatResolution etat) { + Grille g = s.getGrille(); + List symboles = g.getSymbolesPossibles(); + for (int i = 0; i < g.getTaille(); i++) { // Parcours des lignes + for (int j = 0; j < g.getTaille(); j++) { // Parcours des colonnes + Case c = g.getCase(i, j); // Récupération de la case + if (c.getSymbole() == null) { // Si la case est vide + for (Symbole symbole : symboles) { // Parcours des symboles possibles + c.setSymbole(symbole); // Affectation du symbole + etat.compteurGeneral++; // Incrémenter le compteur général + if (afficherEtape) { + afficherEtapeResolution(s, etat.compteur, etat.compteurGeneral); + } + if (s.estValide(c)) { // Si la grille est valide + etat.compteur++; + if (resoudre(s, afficherEtape, etat)) { // Résolution récursive + return true; // Si la grille est résolue + } + etat.compteur--; + } + c.setSymbole(null); // Réinitialisation de la case + } + return false; // Si aucun symbole ne convient + } + } + } + return true; // Si la grille est déjà résolue + } + + private void afficherEtapeResolution(Sudoku s, int compteur, int compteurGeneral) { + System.out.println("Sudoku, Etape " + compteur + " (Tentative " + compteurGeneral + ")"); + System.out.println(s.getGrille().toString()); + } + + private static class EtatResolution { + int compteur; + int compteurGeneral; + + EtatResolution(int compteur, int compteurGeneral) { + this.compteur = compteur; + this.compteurGeneral = compteurGeneral; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/sudoku/Sudoku.java b/app/src/main/java/sudoku/Sudoku.java index 73e5fa5..e416626 100644 --- a/app/src/main/java/sudoku/Sudoku.java +++ b/app/src/main/java/sudoku/Sudoku.java @@ -8,7 +8,7 @@ public class Sudoku { private final List contraintes; public Sudoku(int taille) { - this.grille = new Grille(taille); + this.grille = new Grille(taille, this); this.contraintes = new ArrayList<>(); } @@ -16,9 +16,9 @@ public class Sudoku { contraintes.add(contrainte); } - public void creerBloc(List positions) { - grille.creerBloc(positions); - } + // public void creerBloc(List positions, int blocHeight, int blocWidth) { + // grille.creerBloc(positions, blocHeight, blocWidth); + // } public boolean estValide(Case c) { for (Contrainte contrainte : contraintes) { @@ -35,5 +35,5 @@ public class Sudoku { public Grille getGrille() { return grille; - } + } } \ No newline at end of file diff --git a/app/src/main/java/sudoku/Symbole.java b/app/src/main/java/sudoku/Symbole.java index 7dab4c6..6ba1f9a 100644 --- a/app/src/main/java/sudoku/Symbole.java +++ b/app/src/main/java/sudoku/Symbole.java @@ -48,4 +48,8 @@ public class Symbole { Symbole symbole = (Symbole) obj; return valeur.equals(symbole.valeur); } + + public int getHashCode() { + return valeur.hashCode(); + } } diff --git a/app/src/test/java/sudoku/TestBlocRectangle.java b/app/src/test/java/sudoku/TestBlocRectangle.java new file mode 100644 index 0000000..72e4744 --- /dev/null +++ b/app/src/test/java/sudoku/TestBlocRectangle.java @@ -0,0 +1,55 @@ +package sudoku; + +import java.util.ArrayList; + +import org.junit.jupiter.api.Test; + +public class TestBlocRectangle { + + @Test + public void blocRectangle() { + System.out.println("TEST BLOC RECTANGLE : "); + System.out.println(new App().getGreeting()); + // Create a new Sudoku + Sudoku sudoku = new Sudoku(15); + ArrayList symboles = new ArrayList<>(); + for (int i = 1; i <= 15; i++) { + symboles.add(Symbole.of(i)); + } + sudoku.getGrille().setSymbolesPossibles(symboles); + + sudoku.ajouterContrainte(new ContrainteLigne()); + sudoku.ajouterContrainte(new ContrainteColonne()); + sudoku.ajouterContrainte(new ContrainteBloc()); + + sudoku.getGrille().setCase(0, 0, Symbole.of(1)); + sudoku.getGrille().setCase(6, 1, Symbole.of(2)); + sudoku.getGrille().setCase(2, 2, Symbole.of(3)); + sudoku.getGrille().setCase(0, 3, Symbole.of(4)); + sudoku.getGrille().setCase(4, 4, Symbole.of(5)); + sudoku.getGrille().setCase(0, 5, Symbole.of(6)); + sudoku.getGrille().setCase(5, 6, Symbole.of(7)); + sudoku.getGrille().setCase(0, 7, Symbole.of(8)); + sudoku.getGrille().setCase(4, 8, Symbole.of(9)); + sudoku.getGrille().setCase(0, 3, Symbole.of(9)); + sudoku.getGrille().setCase(3, 0, Symbole.of(4)); + + + sudoku.getGrille().creerBlocCarre(); + + System.out.println("Sudoku :"); + System.out.println(sudoku.getGrille().toString()); + + sudoku.getGrille().creerBlocRectangulaire(3, 5); + System.out.println("Blocs :"); + sudoku.getGrille().printBlocs(); + + System.out.println("Symboles possibles :"); + sudoku.getGrille().printSymbolesPossibles(); + + // blocRectangle.resoudre(sudoku, true); + // System.out.println("Sudoku resolu :"); + // System.out.println(sudoku.getGrille().toString()); + System.out.println("FIN TEST BLOC RECTANGLE"); + } +} diff --git a/app/src/test/java/sudoku/TestLigne.java b/app/src/test/java/sudoku/TestLigne.java index 6309caf..716f75d 100644 --- a/app/src/test/java/sudoku/TestLigne.java +++ b/app/src/test/java/sudoku/TestLigne.java @@ -2,8 +2,6 @@ package sudoku; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertFalse; - import java.util.ArrayList; import java.util.Arrays; @@ -38,7 +36,6 @@ public class TestLigne { sudoku.getGrille().setCase(4, 8, Symbole.of(9)); //doublon ligne sudoku.getGrille().setCase(0, 4, Symbole.of(1)); - assertFalse(sudoku.estValide(sudoku.getGrille().getCase(0, 4))); sudoku.getGrille().creerBlocCarre(); diff --git a/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku16.java b/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku16.java new file mode 100644 index 0000000..323529e --- /dev/null +++ b/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku16.java @@ -0,0 +1,70 @@ +// package sudoku; + +// import java.util.ArrayList; +// import java.util.Arrays; + +// import org.junit.jupiter.api.Test; + +// public class TestResolveurBacktraceSimpleSudoku16 { +// @Test +// public void testResolution() { +// System.out.println("TEST RESOLVEUR BACKTRACE SIMPLE : "); +// System.out.println(new App().getGreeting()); +// // Create a new Sudoku +// Sudoku sudoku = new Sudoku(16); +// sudoku.getGrille().setSymbolesPossibles(new ArrayList<>(Arrays.asList( +// Symbole.of(1), +// Symbole.of(2), +// Symbole.of(3), +// Symbole.of(4), +// Symbole.of(5), +// Symbole.of(6), +// Symbole.of(7), +// Symbole.of(8), +// Symbole.of(9), +// Symbole.of(10), +// Symbole.of(11), +// Symbole.of(12), +// Symbole.of(13), +// Symbole.of(14), +// Symbole.of(15), +// Symbole.of(16) + +// ))); + +// sudoku.ajouterContrainte(new ContrainteLigne()); +// sudoku.ajouterContrainte(new ContrainteColonne()); +// sudoku.ajouterContrainte(new ContrainteBloc()); + +// sudoku.getGrille().setCase(0, 0, Symbole.of(1)); +// sudoku.getGrille().setCase(6, 1, Symbole.of(2)); +// sudoku.getGrille().setCase(2, 2, Symbole.of(3)); +// sudoku.getGrille().setCase(0, 3, Symbole.of(4)); +// sudoku.getGrille().setCase(4, 4, Symbole.of(5)); +// sudoku.getGrille().setCase(0, 5, Symbole.of(6)); +// sudoku.getGrille().setCase(5, 6, Symbole.of(7)); +// sudoku.getGrille().setCase(0, 7, Symbole.of(8)); +// sudoku.getGrille().setCase(4, 8, Symbole.of(9)); +// sudoku.getGrille().setCase(0, 9, Symbole.of(10)); +// sudoku.getGrille().setCase(6, 10, Symbole.of(11)); +// sudoku.getGrille().setCase(2, 11, Symbole.of(12)); +// sudoku.getGrille().setCase(0, 12, Symbole.of(13)); + +// sudoku.getGrille().creerBlocCarre(); + +// System.out.println("Sudoku :"); +// System.out.println(sudoku.getGrille().toString()); + +// System.out.println("Blocs :"); +// sudoku.getGrille().printBlocs(); + +// System.out.println("Symboles possibles :"); +// sudoku.getGrille().printSymbolesPossibles(); + +// ResolveurBacktraceSimple resolveur = new ResolveurBacktraceSimple(sudoku); +// resolveur.resoudre(sudoku, false); +// System.out.println("Sudoku resolu :"); +// System.out.println(sudoku.getGrille().toString()); +// System.out.println("FIN TEST RESOLVEUR BACKTRACE SIMPLE"); +// } +// } diff --git a/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku25.java b/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku25.java new file mode 100644 index 0000000..f224dd0 --- /dev/null +++ b/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku25.java @@ -0,0 +1,56 @@ +// package sudoku; + +// import java.util.ArrayList; + +// import org.junit.jupiter.api.Test; + +// public class TestResolveurBacktraceSimpleSudoku25 { +// @Test +// public void testResolution() { +// System.out.println("TEST RESOLVEUR BACKTRACE SIMPLE : "); +// System.out.println(new App().getGreeting()); +// // Create a new Sudoku +// Sudoku sudoku = new Sudoku(25); + +// ArrayList symboles = new ArrayList<>(); +// for (int i = 1; i <= 25; i++) { +// symboles.add(Symbole.of(i)); +// } +// sudoku.getGrille().setSymbolesPossibles(symboles); + +// sudoku.ajouterContrainte(new ContrainteLigne()); +// sudoku.ajouterContrainte(new ContrainteColonne()); +// sudoku.ajouterContrainte(new ContrainteBloc()); + +// sudoku.getGrille().setCase(0, 0, Symbole.of(1)); +// sudoku.getGrille().setCase(6, 1, Symbole.of(2)); +// sudoku.getGrille().setCase(2, 2, Symbole.of(3)); +// sudoku.getGrille().setCase(0, 3, Symbole.of(4)); +// sudoku.getGrille().setCase(4, 4, Symbole.of(5)); +// sudoku.getGrille().setCase(0, 5, Symbole.of(6)); +// sudoku.getGrille().setCase(5, 6, Symbole.of(7)); +// sudoku.getGrille().setCase(0, 7, Symbole.of(8)); +// sudoku.getGrille().setCase(4, 8, Symbole.of(9)); +// sudoku.getGrille().setCase(0, 9, Symbole.of(25)); +// sudoku.getGrille().setCase(6, 10, Symbole.of(11)); +// sudoku.getGrille().setCase(2, 11, Symbole.of(12)); +// sudoku.getGrille().setCase(0, 12, Symbole.of(13)); + +// sudoku.getGrille().creerBlocCarre(); + +// System.out.println("Sudoku :"); +// System.out.println(sudoku.getGrille().toString()); + +// System.out.println("Blocs :"); +// sudoku.getGrille().printBlocs(); + +// System.out.println("Symboles possibles :"); +// sudoku.getGrille().printSymbolesPossibles(); + +// ResolveurBacktraceSimple resolveur = new ResolveurBacktraceSimple(sudoku); +// resolveur.resoudre(sudoku, false); +// System.out.println("Sudoku resolu :"); +// System.out.println(sudoku.getGrille().toString()); +// System.out.println("FIN TEST RESOLVEUR BACKTRACE SIMPLE"); +// } +// } diff --git a/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku9.java b/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku9.java new file mode 100644 index 0000000..87216c0 --- /dev/null +++ b/app/src/test/java/sudoku/TestResolveurBacktraceSimpleSudoku9.java @@ -0,0 +1,57 @@ +package sudoku; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.junit.jupiter.api.Test; + +public class TestResolveurBacktraceSimpleSudoku9 { + @Test + public void testResolution() { + System.out.println("TEST RESOLVEUR BACKTRACE SIMPLE : "); + System.out.println(new App().getGreeting()); + // Create a new Sudoku + Sudoku sudoku = new Sudoku(9); + sudoku.getGrille().setSymbolesPossibles(new ArrayList<>(Arrays.asList( + Symbole.of(1), + Symbole.of(2), + Symbole.of(3), + Symbole.of(4), + Symbole.of(5), + Symbole.of(6), + Symbole.of(7), + Symbole.of(8), + Symbole.of(9)))); + + sudoku.ajouterContrainte(new ContrainteLigne()); + sudoku.ajouterContrainte(new ContrainteColonne()); + sudoku.ajouterContrainte(new ContrainteBloc()); + + sudoku.getGrille().setCase(0, 0, Symbole.of(1)); + sudoku.getGrille().setCase(6, 1, Symbole.of(2)); + sudoku.getGrille().setCase(2, 2, Symbole.of(3)); + sudoku.getGrille().setCase(0, 3, Symbole.of(4)); + sudoku.getGrille().setCase(4, 4, Symbole.of(5)); + sudoku.getGrille().setCase(0, 5, Symbole.of(6)); + sudoku.getGrille().setCase(5, 6, Symbole.of(7)); + sudoku.getGrille().setCase(0, 7, Symbole.of(8)); + sudoku.getGrille().setCase(4, 8, Symbole.of(9)); + + sudoku.getGrille().creerBlocCarre(); + + System.out.println("Sudoku :"); + System.out.println(sudoku.getGrille().toString()); + + System.out.println("Blocs :"); + sudoku.getGrille().printBlocs(); + + System.out.println("Symboles possibles :"); + sudoku.getGrille().printSymbolesPossibles(); + + ResolveurBacktraceSimple resolveur = new ResolveurBacktraceSimple(sudoku); + resolveur.resoudre(sudoku, false); + System.out.println("Sudoku resolu :"); + System.out.println(sudoku.getGrille().toString()); + System.out.println("FIN TEST RESOLVEUR BACKTRACE SIMPLE"); + } +} diff --git a/readme_files/conception_uml/mermaid-diagram-2025-01-21-124116.svg b/readme_files/conception_uml/mermaid-diagram-2025-01-21-124116.svg new file mode 100644 index 0000000..d40221d --- /dev/null +++ b/readme_files/conception_uml/mermaid-diagram-2025-01-21-124116.svg @@ -0,0 +1 @@ +Sudoku+grille : Grille+blocs : List<Bloc>+contraintes : List<Contrainte>+rentrerSudoku() : void+resoudre(resolveur : Resolveur) : boolean+ajouterContrainte(contrainte : Contrainte) : voidMultiDoku+sudokus : List<Sudoku>+contraintesPartage : List<ContraintePartage>+resoudre(resolveur : Resolveur) : boolean+ajouterContraintePartage(contrainte : ContraintePartage) : voidGrille+taille : int // N×N+cases : Symbole[taille][taille]+afficherGrille() : void+estValide() : boolean+getValeursPossibles(x : int, y : int) : List<Symbole>Bloc+cases : List<Case>+estValide() : boolean«interface»Contrainte+estRespectee(grille : Grille, case : Case) : booleanContrainteLigne+estRespectee(grille : Grille: case : Case) : booleanContrainteColonne+estRespectee(grille : Grille: case : Case) : booleanContrainteBloc+estRespectee(grille : Grille: case : Case) : boolean«interface»ContraintePartage+estRespectee(case : Case) : booleanContrainteLignePartage-casesPartagees : List<Case>+estRespectee(case : Case) : booleanContrainteColonnePartage-casesPartagees : List<Case>+estRespectee(case : Case) : booleanContrainteBlocPartage-casesPartagees : List<Case>+estRespectee(case : Case) : boolean«interface»Resolveur+resoudre(sudoku : Sudoku) : boolean+resoudre(multidoku : MultiDoku) : booleanResolveurRegles+resoudre(sudoku : Sudoku) : boolean+resoudre(multidoku : MultiDoku) : booleanResolveurBacktrace+backtrace : Backtrace+resoudre(sudoku : Sudoku) : boolean+resoudre(multidoku : MultiDoku) : booleanCase+valeur : Symbole+x : int+y : intSymbole+valeur : char+equals(symbole : Symbole) : booleanBacktrace+pile : Stack<Case>+explorer(cases : List<Case>) : booleancontientcontientutilisecontientutilisecontientcontientcontientagit_suragit_surimplémenteimplémenteutiliseimplémenteimplémenteimplémenteimplémenteimplémenteimplémente111111111111N***N*NN111 \ No newline at end of file diff --git a/readme_files/conception_uml/uml-intellij/actuel-classdiagram-intellij.svg b/readme_files/conception_uml/uml-intellij/actuel-classdiagram-intellij.svg new file mode 100644 index 0000000..f3dc858 --- /dev/null +++ b/readme_files/conception_uml/uml-intellij/actuel-classdiagram-intellij.svg @@ -0,0 +1 @@ +«create»«create»«create»«create»1111111cases *symbole 1blocs *cases *symbolesPossibles *contraintes *grille 1AppString greeting+ App()+ main(String[]) : voidBloc- int couleurIndex- List<Case> cases- String couleurString couleurint couleurIndexList<Case> cases+ Bloc(String, int)+ ajouterCase(Case) : void+ contains(Symbole) : boolean+ toString() : StringCase- int ligne- Symbole symbole- int colonneint ligneSymbole symboleint colonne+ Case(int, int, Symbole)+ toString() : StringConsole+ Console()+ warnln(String) : void+ successln(String) : void+ infoln(String) : void+ errorln(String) : void«Interface»Contrainte+ estRespectee(Grille, Case) : booleanContrainteBloc+ ContrainteBloc()+ estRespectee(Grille, Case) : booleanContrainteColonne+ ContrainteColonne()+ estRespectee(Grille, Case) : booleanContrainteLigne+ ContrainteLigne()+ estRespectee(Grille, Case) : booleanGrille- ArrayList<Symbole> symbolesPossibles- int tailleint tailleList<Symbole> symbolesPossibles+ Grille(int)+ setCase(int, int, Symbole) : void+ creerBlocCarre() : void- getCouleurDisponible(int, int) : int+ printBlocs() : void+ askSetSymbolesPossibles() : void+ getCase(int, int) : Case+ toString() : String+ printSymbolesPossibles() : void+ verifierToutesContraintes(List<Contrainte>) : boolean+ creerBloc(List<int[]>) : Bloc- findBlocForCase(Case) : Bloc?«Interface»Resolveur+ resoudre(Sudoku) : booleanResolveurRegles+ ResolveurRegles()+ resoudre(Sudoku) : booleanSudoku- Grille grilleGrille grille+ Sudoku(int)+ verifierToutesContraintes() : boolean+ estValide(Case) : boolean+ ajouterContrainte(Contrainte) : void+ creerBloc(List<int[]>) : voidSymboleboolean intint hashCodeboolean letter+ Symbole(String)+ toString() : String+ of(int) : Symbole+ equals(Object) : boolean+ of(String) : Symbole+ of(char) : Symbole \ No newline at end of file diff --git a/readme_files/conception_uml/uml-intellij/classDiagram.mermaid b/readme_files/conception_uml/uml-intellij/classDiagram.mermaid new file mode 100644 index 0000000..afcfc01 --- /dev/null +++ b/readme_files/conception_uml/uml-intellij/classDiagram.mermaid @@ -0,0 +1,131 @@ +classDiagram + +%% Classes principales +class Sudoku { + +grille : Grille + +blocs : List~Bloc~ + +contraintes : List~Contrainte~ + +rentrerSudoku() void + +resoudre(resolveur : Resolveur) boolean + +ajouterContrainte(contrainte : Contrainte) void +} + +class MultiDoku { + +sudokus : List~Sudoku~ + +contraintesPartage : List~ContraintePartage~ + +resoudre(resolveur : Resolveur) boolean + +ajouterContraintePartage(contrainte : ContraintePartage) void +} + +class Grille { + +taille : int // N×N + +cases : Symbole[taille][taille] + +afficherGrille() void + +estValide() boolean + +getValeursPossibles(x : int, y : int) List~Symbole~ +} + +class Bloc { + +cases : List~Case~ + +estValide() boolean +} + +%% Contraintes classiques +class Contrainte { + <> + +estRespectee(grille : Grille, case : Case) boolean +} + +class ContrainteLigne { + +estRespectee(grille : Grille: case : Case) boolean +} + +class ContrainteColonne { + +estRespectee(grille : Grille: case : Case) boolean +} + +class ContrainteBloc { + +estRespectee(grille : Grille: case : Case) boolean +} + +%% Contraintes Partagées +class ContraintePartage { + <> + +estRespectee(case : Case) boolean +} + +class ContrainteLignePartage { + -casesPartagees : List~Case~ + +estRespectee(case : Case) boolean +} + +class ContrainteColonnePartage { + -casesPartagees : List~Case~ + +estRespectee(case : Case) boolean +} + +class ContrainteBlocPartage { + -casesPartagees : List~Case~ + +estRespectee(case : Case) boolean +} + +%% Résolution +class Resolveur { + <> + +resoudre(sudoku : Sudoku) boolean + +resoudre(multidoku : MultiDoku) boolean +} + +class ResolveurRegles { + +resoudre(sudoku : Sudoku) boolean + +resoudre(multidoku : MultiDoku) boolean +} + +class ResolveurBacktrace { + +backtrace : Backtrace + +resoudre(sudoku : Sudoku) boolean + +resoudre(multidoku : MultiDoku) boolean +} + +%% Classes annexes +class Case { + +valeur : Symbole + +x : int + +y : int +} + +class Symbole { + +valeur : char + +equals(symbole : Symbole) boolean +} + +class Backtrace { + +pile : Stack~Case~ + +explorer(cases : List~Case~) boolean +} + +%% Relations entre classes +Sudoku "1" --> "1" Grille : contient +Sudoku "1" --> "N" Bloc : contient +Sudoku "1" --> "*" Contrainte : utilise +MultiDoku "1" --> "*" Sudoku : contient +MultiDoku "1" --> "*" ContraintePartage : utilise +Grille "1" --> "N*N" Case : contient +Bloc "1" --> "N" Case : contient +Case "1" --> "1" Symbole : contient + +%% Lien entre Resolveur et Sudoku/MultiDoku +Resolveur "1" --> "1" Sudoku : agit_sur +Resolveur "1" --> "1" MultiDoku : agit_sur + +%% Héritages et implémentations +ResolveurRegles --> Resolveur : implémente +ResolveurBacktrace --> Resolveur : implémente +ResolveurBacktrace --> "1" Backtrace : utilise +ContrainteLigne --> Contrainte : implémente +ContrainteColonne --> Contrainte : implémente +ContrainteBloc --> Contrainte : implémente +ContrainteLignePartage --> ContraintePartage : implémente +ContrainteColonnePartage --> ContraintePartage : implémente +ContrainteBlocPartage --> ContraintePartage : implémente +
Sudoku
+grille : Grille
+blocs : List<Bloc>
+contraintes : List<Contrainte>
+rentrerSudoku() : void
+resoudre(resolveur : Resolveur) : boolean
+ajouterContrainte(contrainte : Contrainte) : void
MultiDoku
+sudokus : List<Sudoku>
+contraintesPartage : List<ContraintePartage>
+ajouterContraintePartage(contrainte : ContraintePartage) : void
Grille
+taille : int // N×N
+cases : Symbole[taille][taille]
+afficherGrille() : void
+estValide() : boolean
+getValeursPossibles(x : int, y : int) : List<Symbole>
Bloc
+cases : List<Case>
«interface»
Contrainte
+estRespectee(grille : Grille, case : Case) : boolean
ContrainteLigne
+estRespectee(grille : Grille: case : Case) : boolean
ContrainteColonne
ContrainteBloc
ContraintePartage
+estRespectee(case : Case) : boolean
ContrainteLignePartage
-casesPartagees : List<Case>
ContrainteColonnePartage
ContrainteBlocPartage
Resolveur
+resoudre(sudoku : Sudoku) : boolean
+resoudre(multidoku : MultiDoku) : boolean
ResolveurRegles
ResolveurBacktrace
+backtrace : Backtrace
Case
+valeur : Symbole
+x : int
+y : int
Symbole
+valeur : char
+equals(symbole : Symbole) : boolean
Backtrace
+pile : Stack<Case>
+explorer(cases : List<Case>) : boolean
contient
utilise
agit_sur
implémente
«create»
App
String greeting
+ App()
+ main(String[]) : void
- int couleurIndex
- List<Case> cases
- String couleur
String couleur
int couleurIndex
List<Case> cases
+ Bloc(String, int)
+ ajouterCase(Case) : void
+ contains(Symbole) : boolean
+ toString() : String
- int ligne
- Symbole symbole
- int colonne
int ligne
Symbole symbole
int colonne
+ Case(int, int, Symbole)
Console
+ Console()
+ warnln(String) : void
+ successln(String) : void
+ infoln(String) : void
+ errorln(String) : void
«Interface»
+ estRespectee(Grille, Case) : boolean
+ ContrainteBloc()
+ ContrainteColonne()
+ ContrainteLigne()
- ArrayList<Symbole> symbolesPossibles
- int taille
int taille
List<Symbole> symbolesPossibles
+ Grille(int)
+ setCase(int, int, Symbole) : void
+ creerBlocCarre() : void
- getCouleurDisponible(int, int) : int
+ printBlocs() : void
+ askSetSymbolesPossibles() : void
+ getCase(int, int) : Case
+ printSymbolesPossibles() : void
+ verifierToutesContraintes(List<Contrainte>) : boolean
+ creerBloc(List<int[]>) : Bloc
- findBlocForCase(Case) : Bloc?
+ resoudre(Sudoku) : boolean
+ ResolveurRegles()
- Grille grille
Grille grille
+ Sudoku(int)
+ verifierToutesContraintes() : boolean
+ estValide(Case) : boolean
+ ajouterContrainte(Contrainte) : void
+ creerBloc(List<int[]>) : void
boolean int
int hashCode
boolean letter
+ Symbole(String)
+ of(int) : Symbole
+ equals(Object) : boolean
+ of(String) : Symbole
+ of(char) : Symbole