feat: enhance menu, colors, sudoku, all is working, now multidoku ^^
This commit is contained in:
@@ -6,6 +6,7 @@ import java.util.Objects;
|
||||
import java.util.Scanner;
|
||||
|
||||
import sudoku.core.Console;
|
||||
import sudoku.gui.ColorGenerator;
|
||||
|
||||
public class Grille {
|
||||
private final int taille;
|
||||
@@ -13,6 +14,7 @@ public class Grille {
|
||||
private final ArrayList<Bloc> blocs;
|
||||
private ArrayList<Symbole> symbolesPossibles;
|
||||
private final Sudoku sudoku;
|
||||
private List<String> generatedColors;
|
||||
|
||||
public Grille(int taille, Sudoku sudoku) {
|
||||
this.taille = taille;
|
||||
@@ -20,6 +22,10 @@ public class Grille {
|
||||
this.blocs = new ArrayList<>();
|
||||
this.symbolesPossibles = new ArrayList<>();
|
||||
this.sudoku = sudoku;
|
||||
// Ici, on génère une palette de couleurs (par exemple 4 couleurs).
|
||||
// Si vous souhaitez avoir autant de couleurs qu'il y a de blocs,
|
||||
// vous pouvez adapter le nombre passé à greatScheme/greatPalette.
|
||||
initColors();
|
||||
|
||||
// Initialiser les cases
|
||||
for (int i = 0; i < taille; i++) {
|
||||
@@ -29,20 +35,36 @@ public class Grille {
|
||||
}
|
||||
}
|
||||
|
||||
private void initColors() {
|
||||
int numberOfColors = 4; // ou un autre nombre souhaité
|
||||
List<ColorGenerator.Color> colors = ColorGenerator.greatScheme(numberOfColors);
|
||||
generatedColors = new ArrayList<>();
|
||||
for (ColorGenerator.Color color : colors) {
|
||||
generatedColors.add(convertToAnsi(color));
|
||||
}
|
||||
}
|
||||
|
||||
private String convertToAnsi(ColorGenerator.Color color) {
|
||||
int r = Math.round(color.r * 255);
|
||||
int g = Math.round(color.g * 255);
|
||||
int b = Math.round(color.b * 255);
|
||||
return String.format("\u001B[38;2;%d;%d;%dm", r, g, b);
|
||||
}
|
||||
|
||||
public void setCase(int ligne, int colonne, Symbole symbole) {
|
||||
try {
|
||||
if (symbole != null && !symbolesPossibles.contains(symbole)) {
|
||||
throw new IllegalArgumentException("Symbole non autorisé : " + symbole);
|
||||
}
|
||||
// Save ancien symbole
|
||||
// Sauvegarder l'ancien symbole
|
||||
Symbole ancienSymbole = cases[ligne][colonne].getSymbole();
|
||||
|
||||
// Set nouveau symbole
|
||||
// Affecter le nouveau symbole
|
||||
cases[ligne][colonne].setSymbole(symbole);
|
||||
|
||||
// Vérifier les contraintes
|
||||
if (!sudoku.verifierToutesContraintes()) {
|
||||
// Revert to ancien symbole
|
||||
// Revenir sur le changement
|
||||
cases[ligne][colonne].setSymbole(ancienSymbole);
|
||||
throw new IllegalArgumentException("SET CASE: Les contraintes ne sont pas respectées pour la case ("
|
||||
+ ligne + ", " + colonne + ")");
|
||||
@@ -56,54 +78,12 @@ public class Grille {
|
||||
return cases[ligne][colonne];
|
||||
}
|
||||
|
||||
private static final String[] QUATRE_COULEURS = {
|
||||
"\u001B[31m", // Rouge
|
||||
"\u001B[32m", // Vert
|
||||
"\u001B[34m", // Bleu
|
||||
"\u001B[33m" // Jaune
|
||||
};
|
||||
|
||||
private int getCouleurDisponible(int blocRow, int blocCol, int blocHeight, int blocWidth) {
|
||||
List<Integer> couleursUtilisees = new ArrayList<>();
|
||||
int blocsParLigne = taille / blocWidth;
|
||||
int blocsParColonne = taille / blocHeight;
|
||||
|
||||
// Parcourir les voisins (haut, bas, gauche, droite, et diagonaux)
|
||||
for (int dRow = -1; dRow <= 1; dRow++) {
|
||||
for (int dCol = -1; dCol <= 1; dCol++) {
|
||||
if (dRow == 0 && dCol == 0)
|
||||
continue; // Ignorer le bloc courant
|
||||
|
||||
int voisinRow = blocRow + dRow;
|
||||
int voisinCol = blocCol + dCol;
|
||||
|
||||
// Vérifier si le voisin est dans les limites
|
||||
if (voisinRow >= 0 && voisinRow < blocsParColonne &&
|
||||
voisinCol >= 0 && voisinCol < blocsParLigne) {
|
||||
int blockIndex = voisinRow * blocsParLigne + voisinCol;
|
||||
if (blockIndex < blocs.size()) {
|
||||
couleursUtilisees.add(blocs.get(blockIndex).getCouleurIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trouver une couleur non utilisée
|
||||
for (int c = 0; c < QUATRE_COULEURS.length; c++) {
|
||||
if (!couleursUtilisees.contains(c)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
// Retourner une couleur par défaut (ne devrait pas arriver avec 4 couleurs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un bloc à partir des positions spécifiées
|
||||
*
|
||||
* Exemple :
|
||||
* sudoku.getGrille().creerBloc(Arrays.asList(
|
||||
* Crée un bloc personnalisé à partir des positions spécifiées.
|
||||
* La couleur du bloc est choisie de façon cyclique dans la palette générée.
|
||||
*
|
||||
* Exemple d'utilisation :
|
||||
* sudoku.getGrille().creerBlocPersonnalise(Arrays.asList(
|
||||
* new int[] { 0, 0 },
|
||||
* new int[] { 0, 1 },
|
||||
* new int[] { 0, 2 },
|
||||
@@ -112,10 +92,8 @@ public class Grille {
|
||||
* new int[] { 1, 2 },
|
||||
* new int[] { 2, 0 },
|
||||
* new int[] { 2, 1 },
|
||||
* new int[] { 2, 2 }));
|
||||
*
|
||||
* @param positions
|
||||
* @return
|
||||
* new int[] { 2, 2 }
|
||||
* ));
|
||||
*/
|
||||
public void creerBlocPersonnalise(List<int[]> positions) {
|
||||
try {
|
||||
@@ -126,38 +104,10 @@ public class Grille {
|
||||
}
|
||||
}
|
||||
|
||||
// Collecter les couleurs des blocs voisins
|
||||
List<Integer> couleursVoisines = new ArrayList<>();
|
||||
for (int[] pos : positions) {
|
||||
// Vérifier les cases adjacentes
|
||||
int[][] directions = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
|
||||
for (int[] dir : directions) {
|
||||
int neighborRow = pos[0] + dir[0];
|
||||
int neighborCol = pos[1] + dir[1];
|
||||
if (neighborRow >= 0 && neighborRow < taille && neighborCol >= 0 && neighborCol < taille) {
|
||||
Case neighborCase = cases[neighborRow][neighborCol];
|
||||
Bloc neighborBloc = findBlocForCase(neighborCase);
|
||||
if (neighborBloc != null) {
|
||||
couleursVoisines.add(neighborBloc.getCouleurIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Choisir la couleur suivante en fonction du nombre de blocs déjà créés
|
||||
int couleurIndex = blocs.size() % generatedColors.size();
|
||||
Bloc bloc = new Bloc(generatedColors.get(couleurIndex), couleurIndex);
|
||||
|
||||
// Trouver une couleur disponible
|
||||
int couleurIndex = -1;
|
||||
for (int c = 0; c < QUATRE_COULEURS.length; c++) {
|
||||
if (!couleursVoisines.contains(c)) {
|
||||
couleurIndex = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (couleurIndex == -1) {
|
||||
couleurIndex = 0; // Fallback
|
||||
}
|
||||
|
||||
// Créer et ajouter le bloc
|
||||
Bloc bloc = new Bloc(QUATRE_COULEURS[couleurIndex], couleurIndex);
|
||||
for (int[] pos : positions) {
|
||||
bloc.ajouterCase(cases[pos[0]][pos[1]]);
|
||||
}
|
||||
@@ -168,6 +118,9 @@ public class Grille {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée des blocs carrés (par exemple pour un sudoku classique).
|
||||
*/
|
||||
public void creerBlocCarre() {
|
||||
try {
|
||||
int blocSize = (int) Math.sqrt(taille);
|
||||
@@ -175,12 +128,12 @@ public class Grille {
|
||||
throw new IllegalArgumentException("La taille de la grille doit être un carré parfait.");
|
||||
}
|
||||
|
||||
// Create blocks in 3x3 pattern
|
||||
// Création des blocs en motif 3x3 (ou autre selon la taille)
|
||||
for (int blocRow = 0; blocRow < blocSize; blocRow++) {
|
||||
for (int blocCol = 0; blocCol < blocSize; blocCol++) {
|
||||
List<int[]> positions = new ArrayList<>();
|
||||
|
||||
// Add all positions for current block
|
||||
// Ajouter toutes les positions pour le bloc courant
|
||||
for (int i = 0; i < blocSize; i++) {
|
||||
for (int j = 0; j < blocSize; j++) {
|
||||
positions.add(new int[] {
|
||||
@@ -190,8 +143,9 @@ public class Grille {
|
||||
}
|
||||
}
|
||||
|
||||
int couleurIndex = getCouleurDisponible(blocRow, blocCol, blocSize, blocSize);
|
||||
Bloc bloc = new Bloc(QUATRE_COULEURS[couleurIndex], couleurIndex);
|
||||
// Affectation cyclique d'une couleur issue de la palette générée
|
||||
int couleurIndex = blocs.size() % generatedColors.size();
|
||||
Bloc bloc = new Bloc(generatedColors.get(couleurIndex), couleurIndex);
|
||||
|
||||
for (int[] pos : positions) {
|
||||
bloc.ajouterCase(cases[pos[0]][pos[1]]);
|
||||
@@ -205,13 +159,9 @@ public class Grille {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Crée des blocs rectangulaires automatiquement à partir de la taille de la
|
||||
* grille.
|
||||
* Ne fonctionne pas pour les grilles dont la taille est un carré parfait.
|
||||
*/
|
||||
public void creerBlocRectangulaire(int blocHeight, int blocWidth) {
|
||||
try {
|
||||
@@ -223,12 +173,12 @@ public class Grille {
|
||||
int blocsParLigne = taille / blocWidth;
|
||||
int blocsParColonne = taille / blocHeight;
|
||||
|
||||
// Create blocks in rectangular pattern
|
||||
// Création des blocs en motif rectangulaire
|
||||
for (int blocRow = 0; blocRow < blocsParColonne; blocRow++) {
|
||||
for (int blocCol = 0; blocCol < blocsParLigne; blocCol++) {
|
||||
List<int[]> positions = new ArrayList<>();
|
||||
|
||||
// Add all positions for current block
|
||||
// Ajouter toutes les positions pour le bloc courant
|
||||
for (int i = 0; i < blocHeight; i++) {
|
||||
for (int j = 0; j < blocWidth; j++) {
|
||||
positions.add(new int[] {
|
||||
@@ -238,8 +188,8 @@ public class Grille {
|
||||
}
|
||||
}
|
||||
|
||||
int couleurIndex = getCouleurDisponible(blocRow, blocCol, blocHeight, blocWidth);
|
||||
Bloc bloc = new Bloc(QUATRE_COULEURS[couleurIndex], couleurIndex);
|
||||
int couleurIndex = blocs.size() % generatedColors.size();
|
||||
Bloc bloc = new Bloc(generatedColors.get(couleurIndex), couleurIndex);
|
||||
|
||||
for (int[] pos : positions) {
|
||||
bloc.ajouterCase(cases[pos[0]][pos[1]]);
|
||||
@@ -258,47 +208,51 @@ public class Grille {
|
||||
}
|
||||
}
|
||||
|
||||
public void askSetSymbolesPossibles() {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
try {
|
||||
Console.infoln("Choisissez le type de symboles :");
|
||||
Console.infoln("1. Nombres");
|
||||
Console.infoln("2. Lettres");
|
||||
Console.infoln("3. Texte/Emoji");
|
||||
public static int choisirTypeSymbole(Scanner scanner) {
|
||||
while (true) {
|
||||
System.out.println("Choisissez le type de symbole :");
|
||||
System.out.println("1 : Entiers");
|
||||
System.out.println("2 : Lettres");
|
||||
System.out.println("3 : Chaînes de caractères / Emoji");
|
||||
|
||||
int choix = 0;
|
||||
String input = scanner.nextLine();
|
||||
try {
|
||||
choix = Integer.parseInt(scanner.nextLine());
|
||||
if (choix < 1 || choix > 3) {
|
||||
throw new NumberFormatException("Choix invalide");
|
||||
int choix = Integer.parseInt(input);
|
||||
if (choix >= 1 && choix <= 3) {
|
||||
return choix;
|
||||
} else {
|
||||
System.out.println("Choix invalide. Veuillez entrer 1, 2 ou 3.");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
Console.errorln("Choix invalide");
|
||||
return;
|
||||
System.out.println("Entrée invalide. Veuillez entrer un nombre.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void askSetSymbolesPossibles(int choix, Scanner scanner) {
|
||||
try {
|
||||
for (int i = 0; i < taille; i++) {
|
||||
System.out.println(("Entrez le symbole " + (i + 1) + "/" + taille + " :"));
|
||||
System.out.println("Entrez le symbole " + (i + 1) + "/" + taille + " :");
|
||||
String input = scanner.nextLine();
|
||||
|
||||
switch (choix) {
|
||||
case 1: // Nombres
|
||||
Symbole intTemp = Symbole.of(input);
|
||||
if (intTemp.isInt()) {
|
||||
try {
|
||||
Symbole intTemp = Symbole.of(Integer.parseInt(input));
|
||||
if (symbolesPossibles.contains(intTemp)) {
|
||||
Console.errorln("Ce symbole existe déjà, veuillez entrer un autre symbole");
|
||||
i--;
|
||||
} else {
|
||||
symbolesPossibles.add(intTemp);
|
||||
}
|
||||
} else {
|
||||
} catch (NumberFormatException e) {
|
||||
Console.errorln("Veuillez entrer un nombre valide");
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Lettres
|
||||
if (input.length() == 1 && Symbole.of(input.charAt(0)).isLetter()) {
|
||||
if (input.length() == 1 && Character.isLetter(input.charAt(0))) {
|
||||
Symbole charTemp = Symbole.of(input.charAt(0));
|
||||
if (symbolesPossibles.contains(charTemp)) {
|
||||
Console.errorln("Ce symbole existe déjà, veuillez entrer un autre symbole");
|
||||
@@ -327,10 +281,11 @@ public class Grille {
|
||||
|
||||
default:
|
||||
Console.errorln("Type non supporté");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Une erreur est survenue : " + e.getMessage());
|
||||
Console.errorln("Une erreur est survenue : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,9 +319,9 @@ 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
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
@@ -413,51 +368,35 @@ public class Grille {
|
||||
}
|
||||
|
||||
@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();
|
||||
int maxLen = getLongueurSymboleLePlusLong(); // longueur maximale des symboles
|
||||
|
||||
for (int i = 0; i < taille; i++) {
|
||||
for (int j = 0; j < taille; j++) {
|
||||
Case currentCase = cases[i][j];
|
||||
String cellStr = currentCase.toString();
|
||||
// Calculer le nombre d'espaces à ajouter pour atteindre maxLen
|
||||
int pad = maxLen - cellStr.length();
|
||||
String padding = " ".repeat(pad); // nécessite Java 11 ou ultérieur
|
||||
|
||||
Bloc bloc = findBlocForCase(currentCase);
|
||||
|
||||
if (bloc != null) {
|
||||
sb.append(bloc.getCouleur()) // Couleur du bloc
|
||||
.append(currentCase.toString()) // Contenu de la case
|
||||
.append("\u001B[0m ") // Réinitialiser la couleur
|
||||
sb.append(bloc.getCouleur()) // couleur du bloc
|
||||
.append(cellStr)
|
||||
.append(padding)
|
||||
.append("\u001B[0m ") // réinitialiser la couleur
|
||||
.append(" ");
|
||||
} else {
|
||||
sb.append(currentCase.toString()).append(" ");
|
||||
sb.append(cellStr)
|
||||
.append(padding)
|
||||
.append(" ");
|
||||
}
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user