From 0c03f07345a3d146d5360234fa2b1600d15e2c3b Mon Sep 17 00:00:00 2001 From: Morph01 Date: Wed, 25 Dec 2024 20:53:25 +0100 Subject: [PATCH] feat: premier jet de la conception basique du sudoku --- app/build.gradle | 4 + app/src/main/java/sudoku/App.java | 40 ++++- app/src/main/java/sudoku/Bloc.java | 50 ++++++ app/src/main/java/sudoku/Case.java | 34 ++++ app/src/main/java/sudoku/Grille.java | 191 +++++++++++++++++++++ app/src/main/java/sudoku/Sudoku.java | 13 ++ app/src/main/java/sudoku/Symbole.java | 35 ++++ app/src/main/java/sudoku/core/Console.java | 24 +++ 8 files changed, 388 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/sudoku/Bloc.java create mode 100644 app/src/main/java/sudoku/Case.java create mode 100644 app/src/main/java/sudoku/Grille.java create mode 100644 app/src/main/java/sudoku/Sudoku.java create mode 100644 app/src/main/java/sudoku/Symbole.java create mode 100644 app/src/main/java/sudoku/core/Console.java diff --git a/app/build.gradle b/app/build.gradle index 3c60f56..864291c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,4 +43,8 @@ test { showStackTraces true } useJUnitPlatform() +} + +run { + standardInput = System.in } \ No newline at end of file diff --git a/app/src/main/java/sudoku/App.java b/app/src/main/java/sudoku/App.java index 6aa33d4..e69b858 100644 --- a/app/src/main/java/sudoku/App.java +++ b/app/src/main/java/sudoku/App.java @@ -1,8 +1,8 @@ -/* - * This Java source file was generated by the Gradle 'init' task. - */ package sudoku; +import java.util.ArrayList; +import java.util.Arrays; + public class App { public String getGreeting() { return "Hello World!"; @@ -10,5 +10,39 @@ public class App { public static void main(String[] args) { 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.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().createSquareBlocs(); + + 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(); } } diff --git a/app/src/main/java/sudoku/Bloc.java b/app/src/main/java/sudoku/Bloc.java new file mode 100644 index 0000000..72cddcc --- /dev/null +++ b/app/src/main/java/sudoku/Bloc.java @@ -0,0 +1,50 @@ +package sudoku; + +import java.util.ArrayList; +import java.util.List; + +public class Bloc { + private final List cases; + + public Bloc() { + this.cases = new ArrayList<>(); + } + + public void addCase(Case c) { + cases.add(c); + } + + public boolean contains(Symbole s) { + for (Case c : cases) { + if (c.getSymbole().equals(s)) { + return true; + } + } + return false; + } + + // TO MOVE TO FUTUR CONSTRAINTS + // /** + // * Check if the bloc is valid + // * A bloc is valid if it contains no duplicate symbols + // * + // * @return + // */ + // public boolean isValid() { + // for (int i = 0; i < cases.size(); i++) { + // for (int j = i + 1; j < cases.size(); j++) { + // if (cases.get(i).getSymbole().equals(cases.get(j).getSymbole())) { + // return false; + // } + // } + // } + // return true; + // } + + @Override + public String toString() { + return "Bloc{" + + "cases=" + cases + + '}'; + } +} \ No newline at end of file diff --git a/app/src/main/java/sudoku/Case.java b/app/src/main/java/sudoku/Case.java new file mode 100644 index 0000000..53e96a8 --- /dev/null +++ b/app/src/main/java/sudoku/Case.java @@ -0,0 +1,34 @@ +package sudoku; + +public class Case { + private final int ligne; + private final int colonne; + private Symbole symbole; + + public Case(int ligne, int colonne, Symbole symbole) { + this.ligne = ligne; + this.colonne = colonne; + this.symbole = symbole; + } + + public int getLigne() { + return ligne; + } + + public int getColonne() { + return colonne; + } + + public Symbole getSymbole() { + return symbole; + } + + public void setSymbole(Symbole symbole) { + this.symbole = symbole; + } + + @Override + public String toString() { + return (symbole == null) ? "-" : symbole.toString(); + } +} diff --git a/app/src/main/java/sudoku/Grille.java b/app/src/main/java/sudoku/Grille.java new file mode 100644 index 0000000..a309fdc --- /dev/null +++ b/app/src/main/java/sudoku/Grille.java @@ -0,0 +1,191 @@ +package sudoku; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +import sudoku.core.Console; + +public class Grille { + private final int taille; + private final Case[][] cases; + private final ArrayList blocs; + private ArrayList symbolesPossibles; + + public Grille(int taille) { + this.taille = taille; + this.cases = new Case[taille][taille]; + this.blocs = new ArrayList<>(); + this.symbolesPossibles = new ArrayList<>(); + + // Initialiser les cases + for (int i = 0; i < taille; i++) { + for (int j = 0; j < taille; j++) { + cases[i][j] = new Case(i, j, null); + } + } + } + + public void setCase(int ligne, int colonne, Symbole symbole) { + try { + if (symbole != null && !symbolesPossibles.contains(symbole)) { + throw new IllegalArgumentException("Symbole non autorisé : " + symbole); + } + cases[ligne][colonne].setSymbole(symbole); + } catch (Exception e) { + Console.errorln(e.getMessage()); + } + + } + + public Case getCase(int ligne, int colonne) { + return cases[ligne][colonne]; + } + + /** + * Crée un bloc à partir des positions spécifiées + + Exemple : + sudoku.getGrille().createBloc(Arrays.asList( + new int[] { 0, 0 }, + new int[] { 0, 1 }, + new int[] { 0, 2 }, + new int[] { 1, 0 }, + new int[] { 1, 1 }, + new int[] { 1, 2 }, + new int[] { 2, 0 }, + new int[] { 2, 1 }, + new int[] { 2, 2 })); + * @param positions + * @return + */ + public Bloc createBloc(List positions) { + Bloc bloc = new Bloc(); + for (int[] pos : positions) { + bloc.addCase(cases[pos[0]][pos[1]]); + } + blocs.add(bloc); + return bloc; + } + + public void createSquareBlocs() { + try { + int blocSize = (int) Math.sqrt(taille); + if (blocSize * blocSize != taille) { + throw new IllegalArgumentException("La taille de la grille doit être un carré parfait."); + } + for (int i = 0; i < taille; i += blocSize) { + for (int j = 0; j < taille; j += blocSize) { + List positions = new ArrayList<>(); + for (int k = 0; k < blocSize; k++) { + for (int l = 0; l < blocSize; l++) { + positions.add(new int[] { i + k, j + l }); + } + } + createBloc(positions); + } + } + } catch (IllegalArgumentException e) { + Console.errorln(e.getMessage()); + } + } + + // TO MOVE TO FUTUR CONSTRAINTS + // public boolean isValid() { + // for (Bloc bloc : blocs) { + // if (!bloc.isValid()) { + // return false; + // } + // } + // return true; + // } + + public void printBlocs() { + for (Bloc bloc : blocs) { + System.out.println(bloc.toString()); + } + } + + public void askSetSymbolesPossibles() { + try (Scanner scanner = new Scanner(System.in)) { + System.out.println(("Choisissez le type de symboles :")); + System.out.println(("1. Nombres")); + System.out.println(("2. Caractères")); + System.out.println(("3. Texte/Emoji")); + + int choix = 0; + try { + choix = Integer.parseInt(scanner.nextLine()); + } catch (NumberFormatException e) { + Console.errorln("Choix invalide"); + return; + } + + for (int i = 0; i < taille; i++) { + System.out.println(("Entrez le symbole " + (i + 1) + "/" + taille + " :")); + String input = scanner.nextLine(); + + switch (choix) { + case 1: // Nombres + try { + symbolesPossibles.add(Symbole.of(Integer.parseInt(input))); + } catch (NumberFormatException e) { + Console.errorln("Veuillez entrer un nombre valide"); + i--; + } + break; + + case 2: // Caractères + if (input.length() == 1) { + symbolesPossibles.add(Symbole.of(input.charAt(0))); + } else { + Console.errorln("Veuillez entrer un seul caractère"); + i--; + } + break; + + case 3: // Texte/Emoji + if (!input.isEmpty()) { + symbolesPossibles.add(Symbole.of(input)); + } else { + Console.errorln("Le symbole ne peut pas être vide"); + i--; + } + break; + + default: + Console.errorln("Type non supporté"); + return; + } + } + } + } + + public List getSymbolesPossibles() { + return symbolesPossibles; + } + + public void setSymbolesPossibles(ArrayList symbolesPossibles) { + this.symbolesPossibles = symbolesPossibles; + } + + public void printSymbolesPossibles() { + StringBuilder sb = new StringBuilder(); + for (Symbole symbole : symbolesPossibles) { + sb.append(symbole.toString()).append(" "); + } + System.out.println(sb.toString()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < taille; i++) { + for (int j = 0; j < taille; j++) { + sb.append(cases[i][j].toString()).append(" "); + } + sb.append("\n"); + } + return sb.toString(); + } +} diff --git a/app/src/main/java/sudoku/Sudoku.java b/app/src/main/java/sudoku/Sudoku.java new file mode 100644 index 0000000..40f2fef --- /dev/null +++ b/app/src/main/java/sudoku/Sudoku.java @@ -0,0 +1,13 @@ +package sudoku; + +public class Sudoku { + private final Grille grille; + + public Sudoku(int taille) { + this.grille = new Grille(taille); + } + + 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 new file mode 100644 index 0000000..6be9f85 --- /dev/null +++ b/app/src/main/java/sudoku/Symbole.java @@ -0,0 +1,35 @@ +package sudoku; + +public class Symbole { + private final String valeur; + + public Symbole(String symbole) { + this.valeur = symbole; + } + + // Factory methods pour différents types + public static Symbole of(String s) { + return new Symbole(s); + } + + public static Symbole of(int n) { + return new Symbole(String.valueOf(n)); + } + + public static Symbole of(char c) { + return new Symbole(String.valueOf(c)); + } + + @Override + public String toString() { + return valeur; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Symbole symbole = (Symbole) obj; + return valeur.equals(symbole.valeur); + } +} diff --git a/app/src/main/java/sudoku/core/Console.java b/app/src/main/java/sudoku/core/Console.java new file mode 100644 index 0000000..9c12031 --- /dev/null +++ b/app/src/main/java/sudoku/core/Console.java @@ -0,0 +1,24 @@ +package sudoku.core; + +/** + * Console class to print messages in different colors + */ +public class Console { + private static final String ANSI_RESET = "\u001B[0m"; + private static final String ANSI_RED = "\u001B[31m"; + private static final String ANSI_GREEN = "\u001B[32m"; + private static final String ANSI_YELLOW = "\u001B[33m"; + static final String ANSI_BOLD = "\u001B[1m"; + + public static void errorln(String message) { + System.err.println(ANSI_RED + ANSI_BOLD + message + ANSI_RESET); + } + + public static void successln(String message) { + System.out.println(ANSI_GREEN + ANSI_BOLD + message + ANSI_RESET); + } + + public static void warnln(String message) { + System.out.println(ANSI_YELLOW + ANSI_BOLD+ message + ANSI_RESET); + } +}