From 627617656f3cfb4d160f2eab776fe624d7a677f7 Mon Sep 17 00:00:00 2001 From: stiti Date: Thu, 11 Apr 2024 21:50:08 +0200 Subject: [PATCH] =?UTF-8?q?Par=20MARCO=20:=20Ajout=20du=20FileManager=20+?= =?UTF-8?q?=20G=C3=A9n=C3=A9ration=20de=20grille?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/DialogManager.java | 7 ++- src/FileManager.java | 84 ++++++++++++++++++++++++++ src/Grille.java | 90 ++++++++++------------------ src/GrilleView.java | 15 +++++ src/HomeButtonClickListener.java | 2 - src/PlayButtonClickListener.java | 8 ++- src/SudokuGenerator.java | 100 +++++++++++++++++++++++++++++++ src/SudokuSolver.java | 40 +++++++++++++ 8 files changed, 284 insertions(+), 62 deletions(-) create mode 100644 src/FileManager.java create mode 100644 src/GrilleView.java create mode 100644 src/SudokuGenerator.java create mode 100644 src/SudokuSolver.java diff --git a/src/DialogManager.java b/src/DialogManager.java index 317f750..567a6d6 100644 --- a/src/DialogManager.java +++ b/src/DialogManager.java @@ -1,5 +1,10 @@ - +/** + * Interface containing definition to showDialog box. + * @version 1.0 + * @author Moncef STITI + * @author Marco ORFAO + */ public interface DialogManager { void showDialog(); } \ No newline at end of file diff --git a/src/FileManager.java b/src/FileManager.java new file mode 100644 index 0000000..ccc1b8e --- /dev/null +++ b/src/FileManager.java @@ -0,0 +1,84 @@ +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.BufferedWriter; +import java.io.BufferedReader; +import java.io.FileWriter; +import java.io.FileReader; +import java.io.IOException; + +/** + * Classe pour gérer les opérations de sauvegarde et de chargement de grille. + * @author Moncef STITI + * @author Marco ORFAO + * @version 1.0 + */ +public class FileManager { + + /** + * Méthode pour sauvegarder une grille dans un fichier. + * @param grille La grille à sauvegarder + */ + public static void sauvegarderGrille(Grille grille) { + // Création d'un sélecteur de fichier + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setDialogTitle("Enregistrer la grille"); + fileChooser.setFileFilter(new FileNameExtensionFilter("Fichiers de grille (.gri)", "gri")); + int userSelection = fileChooser.showSaveDialog(null); + if (userSelection == JFileChooser.APPROVE_OPTION) { + // Obtention du nom de fichier choisi par l'utilisateur + String nomFichier = fileChooser.getSelectedFile().getAbsolutePath(); + // Vérification et ajout de l'extension .gri si nécessaire + if (!nomFichier.endsWith(".gri")) { + nomFichier += ".gri"; + } + try (BufferedWriter writer = new BufferedWriter(new FileWriter(nomFichier))) { + // Écriture des valeurs de la grille dans le fichier + for (int i = 0; i < 9; i++) { + for (int j = 0; j < 9; j++) { + int valeur = grille.getValeur(i, j); + writer.write(valeur == 0 ? "0" : String.valueOf(valeur)); + } + writer.newLine(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * Méthode pour charger une grille à partir d'un fichier. + * @return La grille chargée depuis le fichier + */ + public static Grille chargerGrille() { + // Création d'un sélecteur de fichier + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setDialogTitle("Charger une grille"); + fileChooser.setFileFilter(new FileNameExtensionFilter("Fichiers de grille (.gri)", "gri")); + int userSelection = fileChooser.showOpenDialog(null); + if (userSelection == JFileChooser.APPROVE_OPTION) { + // Obtention du nom de fichier choisi par l'utilisateur + String nomFichier = fileChooser.getSelectedFile().getAbsolutePath(); + try (BufferedReader reader = new BufferedReader(new FileReader(nomFichier))) { + Grille grille = new Grille(); + String ligne; + int row = 0; + // Lecture des lignes du fichier et remplissage de la grille + while ((ligne = reader.readLine()) != null && row < 9) { + for (int col = 0; col < 9 && col < ligne.length(); col++) { + char caractere = ligne.charAt(col); + if (caractere != ' ') { + int valeur = Character.getNumericValue(caractere); + grille.remplir_case(row, col, valeur); + } + } + row++; + } + return grille; + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } +} diff --git a/src/Grille.java b/src/Grille.java index 8250938..b7e3370 100644 --- a/src/Grille.java +++ b/src/Grille.java @@ -1,76 +1,52 @@ public class Grille { - private int[] grille = null; + private int[][] grille; - public Grille(){ - this.grille = new int[81]; - int x; - - for (x=0 ; x < 81 ; x++) { - this.grille[x]=0; //remplie la grille de "0" -> "0" est un marqueur signifiant que la case est vide + public Grille() { + grille = new int[9][9]; + // Initialiser la grille avec des zéros pour représenter des cases vides + for (int i = 0; i < 9; i++) { + for (int j = 0; j < 9; j++) { + grille[i][j] = 0; + } } } - public boolean case_vide(int position){ - if (this.grille[position] == 0) { - return true; - } else { - return false; - } - } - - public boolean est_valide(int position, int nbr){ - - /* check si le numéro se répète sur la colonne */ - - int colonne = position%9; - int id_test = colonne; - while (id_test != (72+colonne)) { - if ((this.grille[id_test]==nbr) && (id_test != position)) { + public boolean est_valide(int row, int col, int num) { + // Vérifier si le nombre est présent dans la même ligne ou colonne + for (int i = 0; i < 9; i++) { + if (grille[row][i] == num || grille[i][col] == num) { return false; } - id_test += 9; - } - - /* check si le numéro se répète sur la ligne */ - - int ligne = position/9; - id_test = ligne * 9; - - while (id_test != ((ligne +1)*9)) { - if ((this.grille[id_test]==nbr) && (id_test != position)) { - return false; - } - id_test += 1; } - /* check si le numéro se répète dans le carré auquel il appartient */ - - int Vcase = ligne/3; // permet de connaître la position du carré sur un axe vertical - int Hcase = colonne/3; // permet de connaître la position du carré sur un axe horizontal - int x,y; - - for (x=0; x<3 ;x++) { - for (y=0; y<3 ;y++) { - id_test = Vcase*27+(y+Hcase*3)+(x*9); - if ((this.grille[id_test]==nbr) && (id_test != position)) { + // Vérifier si le nombre est présent dans le carré 3x3 + int startRow = row - row % 3; + int startCol = col - col % 3; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (grille[i + startRow][j + startCol] == num) { return false; } } } + return true; } - public void remplir_case(int position,int nbr){ - if ((nbr > 0) && (nbr < 10)){ - this.grille[position] = nbr; - } else { - System.out.println("veuillez choisir un nombre entre 1 et 9"); - } + public void remplir_case(int row, int col, int num) { + grille[row][col] = num; } - /*public static void main(String[] args){ - Grille grille = new Grille(); - grille.remplir_case(3,59); - System.out.println(grille.case_vide(3)); - }*/ + public boolean case_vide(int row, int col) { + return grille[row][col] == 0; + } + + public void vider_case(int row, int col) { + grille[row][col] = 0; + } + + public int getValeur(int row, int col) { + return grille[row][col]; + } } + diff --git a/src/GrilleView.java b/src/GrilleView.java new file mode 100644 index 0000000..ff3fcaf --- /dev/null +++ b/src/GrilleView.java @@ -0,0 +1,15 @@ +import javax.swing.*; +import java.awt.*; + +public class GrilleView extends JFrame { + private Grille grille; + + public GrilleView(Grille grille) { + this.grille = grille; + initUI(); + } + + private void initUI() { + // EN COURS + } +} diff --git a/src/HomeButtonClickListener.java b/src/HomeButtonClickListener.java index e09da4f..45f3ae7 100644 --- a/src/HomeButtonClickListener.java +++ b/src/HomeButtonClickListener.java @@ -1,8 +1,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; - - /** * Listener for button clicks in the menu. * It performs different actions based on the button clicked. diff --git a/src/PlayButtonClickListener.java b/src/PlayButtonClickListener.java index c52b017..51f3222 100644 --- a/src/PlayButtonClickListener.java +++ b/src/PlayButtonClickListener.java @@ -15,9 +15,13 @@ public class PlayButtonClickListener implements ActionListener { // Handle different button actions based on their text if (buttonText.equals("Générer une grille")) { - System.out.println("Générer une grille"); + Grille nouvelleGrille = new Grille(); + SudokuGenerator sudokuGenerator = new SudokuGenerator(nouvelleGrille); + Grille grilleGeneree = sudokuGenerator.genererGrille(); // Générer la grille + FileManager.sauvegarderGrille(grilleGeneree); } else if (buttonText.equals("Charger une grille")) { - System.out.println("Chargement de la grille"); + Grille grille = FileManager.chargerGrille(); + GrilleView test = new GrilleView(grille); } else if (buttonText.equals("Retour au menu principal")) { if (window.getContentPane().getComponent(0) instanceof PlayMenuView) { PlayMenuView playMenuView = (PlayMenuView) window.getContentPane().getComponent(0); diff --git a/src/SudokuGenerator.java b/src/SudokuGenerator.java new file mode 100644 index 0000000..bf6c319 --- /dev/null +++ b/src/SudokuGenerator.java @@ -0,0 +1,100 @@ +import java.util.Random; + +public class SudokuGenerator { + private int nombreCasesVides = 40; + private Grille grille; + + public SudokuGenerator(Grille grille) { + this.grille = grille; + } + + public Grille genererGrille() { + remplirDiagonales(); // Remplir les diagonales pour assurer la validité initiale + // Remplir le reste de la grille de manière récursive + remplirGrille(0); + // Supprimer certains nombres pour obtenir une grille incomplète mais résolva ble + supprimerNombres(); + return grille; + } + + private void supprimerNombres() { + Random random = new Random(); + while (this.nombreCasesVides > 0) { + int row = random.nextInt(9); + int col = random.nextInt(9); + if (grille.case_vide(row, col)) { + continue; // La case est déjà vide, passer à la suivante + } + + int temp = grille.getValeur(row, col); + grille.vider_case(row, col); + // Vérifier s'il existe une seule solution après avoir vidé la case + if (aUneSeuleSolution()) { + // Il y a encore une solution, la suppression est sûre + this.nombreCasesVides--; + } else { + // Il n'y a plus de solution, remettre le nombre dans la case + grille.remplir_case(row, col, temp); + } + } + } + + private boolean aUneSeuleSolution() { + Grille grilleTemp = new Grille(); + for (int i = 0; i < 9; i++) { + for (int j = 0; j < 9; j++) { + grilleTemp.remplir_case(i, j, grille.getValeur(i, j)); + } + } + SudokuSolver solver = new SudokuSolver(); + return solver.resoudreSudoku(grilleTemp); + } + + + + // Méthode de remplissage de la grille et remplissage des diagonales... + private void remplirDiagonales() { + for (int i = 0; i < 9; i += 3) { + remplirCarre(i, i); + } + } + + private void remplirCarre(int row, int col) { + Random random = new Random(); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + int num; + do { + num = random.nextInt(9) + 1; // Générer un nombre aléatoire entre 1 et 9 + } while (!grille.est_valide(row + i, col + j, num)); // Vérifier la validité du nombre + grille.remplir_case(row + i, col + j, num); + } + } + } + + private boolean remplirGrille(int position) { + if (position == 81) { + return true; // La grille est remplie + } + + int row = position / 9; + int col = position % 9; + + if (grille.case_vide(row, col)) { + for (int num = 1; num <= 9; num++) { + if (grille.est_valide(row, col, num)) { + grille.remplir_case(row, col, num); + + if (remplirGrille(position + 1)) { + return true; + } + + grille.vider_case(row, col); + } + } + return false; + } else { + return remplirGrille(position + 1); + } + } +} diff --git a/src/SudokuSolver.java b/src/SudokuSolver.java new file mode 100644 index 0000000..2d8755a --- /dev/null +++ b/src/SudokuSolver.java @@ -0,0 +1,40 @@ +/** + * Classe pour résoudre un Sudoku. + * @author Moncef STITI + * @author Marco ORFAO + * @version 1.0 + */ +public class SudokuSolver { + + /** + * Méthode pour résoudre un Sudoku en utilisant la récursivité. + * @param grille La grille de Sudoku à résoudre + * @return true si le Sudoku est résolu avec succès, false sinon + */ + public boolean resoudreSudoku(Grille grille) { + // Parcours de chaque case de la grille + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + // Vérification si la case est vide + if (grille.case_vide(row, col)) { + // Essayer chaque chiffre de 1 à 9 + for (int num = 1; num <= 9; num++) { + // Vérifier si le chiffre est valide dans cette case + if (grille.est_valide(row, col, num)) { + // Remplir la case avec le chiffre + grille.remplir_case(row, col, num); + // Appel récursif pour résoudre le reste du Sudoku + if (resoudreSudoku(grille)) { + return true; // Si le Sudoku est résolu, retourner true + } + // Si le Sudoku n'est pas résolu avec ce chiffre, vider la case et essayer un autre chiffre + grille.vider_case(row, col); + } + } + return false; // Si aucun chiffre ne convient, retourner false + } + } + } + return true; // Si toutes les cases sont remplies, le Sudoku est résolu + } +}