diff --git a/Grilles/GrilMakeTest b/Grilles/GrilMakeTest deleted file mode 100644 index dee2404..0000000 Binary files a/Grilles/GrilMakeTest and /dev/null differ diff --git a/Grilles/Grille1 b/Grilles/Grille1 deleted file mode 100644 index a0527ea..0000000 --- a/Grilles/Grille1 +++ /dev/null @@ -1,9 +0,0 @@ -000095004 -530408702 -000700603 -900034080 -040010070 -020570006 -409002000 -607903021 -200650000 \ No newline at end of file diff --git a/Grilles/Grille2 b/Grilles/Grille2 deleted file mode 100644 index a0077de..0000000 --- a/Grilles/Grille2 +++ /dev/null @@ -1,9 +0,0 @@ -062500090 -100029000 -059008602 -047190300 -906302104 -001087920 -604800510 -000940007 -090001480 \ No newline at end of file diff --git a/Grilles/Grille3-fausse b/Grilles/Grille3-fausse deleted file mode 100644 index 98569bc..0000000 --- a/Grilles/Grille3-fausse +++ /dev/null @@ -1,9 +0,0 @@ -062506090 -100029000 -059008602 -047190300 -906302104 -001087920 -604800510 -000940007 -090001480 \ No newline at end of file diff --git a/Grilles/Grille4-dur b/Grilles/Grille4-dur deleted file mode 100644 index a149970..0000000 --- a/Grilles/Grille4-dur +++ /dev/null @@ -1,9 +0,0 @@ -010400005 -460007000 -057020001 -000610000 -801000509 -000035000 -300060950 -000500048 -700004010 \ No newline at end of file diff --git a/Grilles/TestGrille2 b/Grilles/TestGrille2 deleted file mode 100644 index 5564bba..0000000 Binary files a/Grilles/TestGrille2 and /dev/null differ diff --git a/Grilles/exemplecomplet.gri b/Grilles/exemplecomplet.gri new file mode 100644 index 0000000..93c0a8c --- /dev/null +++ b/Grilles/exemplecomplet.gri @@ -0,0 +1 @@ +-q<¦­‘ř5T^u:0&ÉśĽ×©÷l^‘)/a Ľ)T \ No newline at end of file diff --git a/Grilles/info.txt b/Grilles/info.txt deleted file mode 100644 index bf8397d..0000000 --- a/Grilles/info.txt +++ /dev/null @@ -1 +0,0 @@ -grille 2 et 4 : https://la-conjugaison.nouvelobs.com/sudoku/ \ No newline at end of file diff --git a/README.md b/README.md index 56cac89..4a12007 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,14 @@ -## Compilation -Utiliser la commande suivante pour compiler les programmes : -```bash -make -``` - ## Lancement des programmes ### Compiler et lancer le programme de Jeu Utiliser la commande suivante : ```bash -make run jeu +make jeu ``` ### Compiler et lancer le programme de CrĂ©ation Utiliser la commande suivante : ```bash -make run creation +make creation ``` # Documentation diff --git a/src/AutomatiqueActionListener.java b/src/AutomatiqueActionListener.java index 6164e25..4168113 100644 --- a/src/AutomatiqueActionListener.java +++ b/src/AutomatiqueActionListener.java @@ -1,7 +1,6 @@ - import javax.swing.*; import java.awt.event.*; - +import java.io.File; public class AutomatiqueActionListener implements ActionListener { private JFrame choixFrame; @@ -14,19 +13,30 @@ public class AutomatiqueActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { choixFrame.dispose(); - int[][] grille = GenerateurSudoku.genererGrille(); - System.out.println("Grille Sudoku gĂ©nĂ©rĂ©e avec succès."); + int[][] grille = new int[9][9]; // CrĂ©ation d'une grille vide - long startTime = System.nanoTime(); - if (Resolveur.resoudreSudoku(grille)) { - long endTime = System.nanoTime(); - long duration = (endTime - startTime) / 1000000; + // Ouverture du sĂ©lecteur de fichiers pour que l'utilisateur choisisse un fichier de grille + JFileChooser fileChooser = new JFileChooser(); + int returnValue = fileChooser.showOpenDialog(null); - FenetrePrincipale fenetrePrincipale = new FenetrePrincipale(); - fenetrePrincipale.afficher(true, grille); - JOptionPane.showMessageDialog(null, "Grille rĂ©solue avec succès en " + duration + " millisecondes !"); - } else { - JOptionPane.showMessageDialog(null, "Impossible de rĂ©soudre la grille."); + if (returnValue == JFileChooser.APPROVE_OPTION) { + File selectedFile = fileChooser.getSelectedFile(); + + // Lecture de la grille Ă  partir du fichier sĂ©lectionnĂ© + Lecteur.lecture(selectedFile, grille); + + // RĂ©solution du Sudoku + long startTime = System.nanoTime(); + if (Resolveur.resoudreSudoku(grille)) { + long endTime = System.nanoTime(); + long duration = (endTime - startTime) / 1000000; + + FenetrePrincipale fenetrePrincipale = new FenetrePrincipale(); + fenetrePrincipale.afficher(true, grille); + JOptionPane.showMessageDialog(null, "Grille rĂ©solue avec succès en " + duration + " millisecondes !"); + } else { + JOptionPane.showMessageDialog(null, "Impossible de rĂ©soudre la grille."); + } } } } diff --git a/src/CaseMouseListener.java b/src/CaseMouseListener.java index e9bb759..fc4a43a 100644 --- a/src/CaseMouseListener.java +++ b/src/CaseMouseListener.java @@ -31,6 +31,9 @@ public class CaseMouseListener extends MouseAdapter { if (panel.validerChiffre(panel.getLigneSelectionnee(), panel.getColonneSelectionnee(), valeur)) { panel.getGrille()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] = valeur; panel.repaint(); + if (panel.grilleComplete()) { + panel.afficherBravo(); + } } else { JOptionPane.showMessageDialog(null, "Ce chiffre ne respecte pas les contraintes du Sudoku. Veuillez choisir un autre chiffre."); } @@ -54,17 +57,32 @@ public class CaseMouseListener extends MouseAdapter { if (incertainOption == JOptionPane.OK_OPTION) { // VĂ©rifier que les valeurs obligatoires sont remplies if (!incertainFields[0].getText().isEmpty() && !incertainFields[1].getText().isEmpty()) { - // RĂ©cupĂ©rer les valeurs incertaines saisies par le joueur - int valeursIncertaines = 0; + // VĂ©rifier que les valeurs incertaines sont valides + boolean valeursValides = true; for (int i = 0; i < 4; i++) { if (!incertainFields[i].getText().isEmpty()) { int valeur = Integer.parseInt(incertainFields[i].getText()); - valeursIncertaines |= (valeur << (i * 4)); + if (valeur < 1 || valeur > 9) { + valeursValides = false; + break; + } } } - // Mettre Ă  jour la grille avec les valeurs incertaines - panel.getGrille()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] = valeursIncertaines; - panel.repaint(); + if (valeursValides) { + // RĂ©cupĂ©rer les valeurs incertaines saisies par le joueur + int valeursIncertaines = 0; + for (int i = 0; i < 4; i++) { + if (!incertainFields[i].getText().isEmpty()) { + int valeur = Integer.parseInt(incertainFields[i].getText()); + valeursIncertaines |= (valeur << (i * 4)); + } + } + // Mettre Ă  jour la grille avec les valeurs incertaines + panel.getGrille()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] = valeursIncertaines; + panel.repaint(); + } else { + JOptionPane.showMessageDialog(null, "Les valeurs incertaines doivent ĂŞtre des nombres entre 1 et 9."); + } } else { JOptionPane.showMessageDialog(null, "Les deux premières valeurs incertaines sont obligatoires."); } diff --git a/src/GrillePainter.java b/src/GrillePainter.java index 9742d80..f60250f 100644 --- a/src/GrillePainter.java +++ b/src/GrillePainter.java @@ -19,11 +19,29 @@ public class GrillePainter { for (int j = 0; j < panel.getTailleGrille() * panel.getTailleRegion(); j++) { g.setColor(Color.BLACK); g.drawRect(j * panel.getTailleCellule(), i * panel.getTailleCellule(), panel.getTailleCellule(), panel.getTailleCellule()); + int valeur = panel.getGrille()[i][j]; if (valeur != 0) { - g.drawString(String.valueOf(valeur), j * panel.getTailleCellule() + panel.getTailleCellule() / 2, i * panel.getTailleCellule() + panel.getTailleCellule() / 2); + if (valeur < 10) { + g.drawString(String.valueOf(valeur), j * panel.getTailleCellule() + panel.getTailleCellule() / 2, i * panel.getTailleCellule() + panel.getTailleCellule() / 2); + } else { + int[] valeurs = decomposerValeurs(valeur); + for (int k = 0; k < valeurs.length; k++) { + int xOffset = (k % 2) * panel.getTailleCellule() / 2; + int yOffset = (k / 2) * panel.getTailleCellule() / 2; + g.drawString(String.valueOf(valeurs[k]), j * panel.getTailleCellule() + xOffset + panel.getTailleCellule() / 4, i * panel.getTailleCellule() + yOffset + panel.getTailleCellule() / 4); + } + } } } } } + + private static int[] decomposerValeurs(int valeursIncertaines) { + int[] valeurs = new int[4]; + for (int i = 0; i < 4; i++) { + valeurs[i] = (valeursIncertaines >> (i * 4)) & 0xF; + } + return valeurs; + } } diff --git a/src/GrilleSudokuDessin.java b/src/GrilleSudokuDessin.java deleted file mode 100644 index 9c27d7c..0000000 --- a/src/GrilleSudokuDessin.java +++ /dev/null @@ -1,46 +0,0 @@ -import javax.swing.*; -import java.awt.*; - -public class GrilleSudokuDessin extends JPanel { - private static final int TAILLE_GRILLE = 3; - private static final int TAILLE_REGION = 3; - private static final int TAILLE_CELLULE = 50; - - private int[][] grille; - - public GrilleSudokuDessin(int[][] grille) { - this.grille = grille; - setPreferredSize(new Dimension(TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE)); - } - - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - - Graphics2D g2d = (Graphics2D) g; - // DĂ©finir l'Ă©paisseur de la ligne - g2d.setStroke(new BasicStroke(20)); // Épaisseur de ligne de 4 pixels - - // Dessiner les lignes de la grille (en gras pour les contours) - for (int i = 0; i <= TAILLE_GRILLE * TAILLE_REGION; i++) { - if (i % TAILLE_REGION == 0) { - g2d.drawRect(0, i * TAILLE_CELLULE - 2, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, 4); - g2d.drawRect(i * TAILLE_CELLULE - 2, 0, 4, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE); - } else { - g2d.drawRect(0, i * TAILLE_CELLULE - 1, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, 2); - g2d.drawRect(i * TAILLE_CELLULE - 1, 0, 2, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE); - } - } - - // Dessiner les valeurs de la grille - g.setColor(Color.BLACK); - for (int i = 0; i < grille.length; i++) { - for (int j = 0; j < grille[i].length; j++) { - int valeur = grille[i][j]; - if (valeur != 0) { - g.drawString(String.valueOf(valeur), j * TAILLE_CELLULE + TAILLE_CELLULE / 2, i * TAILLE_CELLULE + TAILLE_CELLULE / 2); - } - } - } - } -} diff --git a/src/ManuelActionListener.java b/src/ManuelActionListener.java index 2d21105..6342f73 100644 --- a/src/ManuelActionListener.java +++ b/src/ManuelActionListener.java @@ -1,7 +1,6 @@ - import javax.swing.*; import java.awt.event.*; - +import java.io.File; public class ManuelActionListener implements ActionListener { private JFrame choixFrame; @@ -14,10 +13,21 @@ public class ManuelActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { choixFrame.dispose(); - int[][] grille = GenerateurSudoku.genererGrille(); - System.out.println("Grille Sudoku gĂ©nĂ©rĂ©e avec succès."); + int[][] grille = new int[9][9]; // CrĂ©ation d'une grille vide - FenetrePrincipale fenetrePrincipale = new FenetrePrincipale(); - fenetrePrincipale.afficher(false, grille); + // Ouverture du sĂ©lecteur de fichiers pour que l'utilisateur choisisse un fichier de grille + JFileChooser fileChooser = new JFileChooser(); + int returnValue = fileChooser.showOpenDialog(null); + + if (returnValue == JFileChooser.APPROVE_OPTION) { + File selectedFile = fileChooser.getSelectedFile(); + + // Lecture de la grille Ă  partir du fichier sĂ©lectionnĂ© + Lecteur.lecture(selectedFile, grille); + + // Affichage de la grille dans la fenĂŞtre principale en mode manuel + FenetrePrincipale fenetrePrincipale = new FenetrePrincipale(); + fenetrePrincipale.afficher(false, grille); + } } } diff --git a/src/OuvertureFichier.java b/src/OuvertureFichier.java deleted file mode 100644 index 7da196c..0000000 --- a/src/OuvertureFichier.java +++ /dev/null @@ -1,27 +0,0 @@ -import java.io.*; - -public class OuvertureFichier { - public static int[][] lireFichier(File fichier) { - int[][] grille = new int[9][9]; - try (BufferedReader br = new BufferedReader(new FileReader(fichier))) { - String ligne; - int i = 0; - while ((ligne = br.readLine()) != null && i < 9) { - for (int j = 0; j < Math.min(ligne.length(), 9); j++) { - char caractere = ligne.charAt(j); - if (caractere != ' ') { - // Convertir chaque caractère en valeur numĂ©rique - int valeur = Integer.parseInt(String.valueOf(caractere), 16); - grille[i][j] = valeur; - } - } - i++; - } - } catch (IOException e) { - e.printStackTrace(); - } - return grille; -} - - -} diff --git a/src/SaisieGrille.java b/src/SaisieGrille.java index 79b889f..0174b9c 100644 --- a/src/SaisieGrille.java +++ b/src/SaisieGrille.java @@ -92,6 +92,26 @@ public class SaisieGrille extends JPanel { } } + // VĂ©rifier les valeurs incertaines dans la cellule + int valeursIncertaines = grille[ligne][colonne]; + for (int i = 0; i < 4; i++) { + int valeur = (valeursIncertaines >> (i * 4)) & 0xF; + if (valeur != 0 && valeur == chiffre) { + return false; + } + } + + return true; + } + + public boolean grilleComplete() { + for (int i = 0; i < grille.length; i++) { + for (int j = 0; j < grille[i].length; j++) { + if (grille[i][j] == 0) { + return false; + } + } + } return true; } @@ -101,5 +121,7 @@ public class SaisieGrille extends JPanel { GrillePainter.dessinerGrille(g, this); } - + public void afficherBravo() { + JOptionPane.showMessageDialog(this, "Bravo ! La grille est complĂ©tĂ©e avec succès."); + } } diff --git a/src/SudokuGenerator.java b/src/SudokuGenerator.java deleted file mode 100644 index 6ffa151..0000000 --- a/src/SudokuGenerator.java +++ /dev/null @@ -1,114 +0,0 @@ -import javax.swing.*; -import java.io.*; - -public class SudokuGenerator { - public static int[][] generateGrid() { - // grille par dĂ©faut - int[][] grid = { - {0, 0, 0, 9, 0, 5, 0, 0, 4}, - {5, 0, 3, 0, 0, 4, 0, 8, 7}, - {0, 0, 0, 7, 0, 0, 6, 0, 3}, - {9, 0, 0, 0, 3, 4, 0, 8, 0}, - {0, 4, 0, 0, 1, 0, 0, 7, 0}, - {0, 2, 0, 5, 7, 0, 0, 0, 6}, - {4, 0, 9, 0, 0, 2, 0, 0, 0}, - {6, 0, 7, 9, 0, 3, 0, 2, 1}, - {2, 0, 0, 6, 5, 0, 0, 0, 0} - }; - - return grid; - } - - public static int[][] readGridFromFile() { - int[][] grid = new int[9][9]; - JFileChooser fileChooser = new JFileChooser(); - int result = fileChooser.showOpenDialog(null); - if (result == JFileChooser.APPROVE_OPTION) { - File selectedFile = fileChooser.getSelectedFile(); - try (BufferedReader reader = new BufferedReader(new FileReader(selectedFile))) { - for (int i = 0; i < 9; i++) { - String line = reader.readLine(); - // VĂ©rifier la longueur de la ligne lue - if (line.length() != 9) { - JOptionPane.showMessageDialog(null, "Invalid file format. Please select a file with correct Sudoku grid format."); - return generateGrid(); // Charger la grille par dĂ©faut en cas d'erreur - } - for (int j = 0; j < 9; j++) { - char ch = line.charAt(j); - if (ch >= '1' && ch <= '9') { - grid[i][j] = Character.getNumericValue(ch); - } else { - grid[i][j] = 0; - } - } - } - if (!isGridValid(grid)) { - JOptionPane.showMessageDialog(null, "Invalid Sudoku grid. Loading default grid."); - return generateGrid(); // Charger la grille par dĂ©faut en cas de grille invalide - } - } catch (IOException e) { - e.printStackTrace(); - } - } - return grid; - } - - // MĂ©thode pour vĂ©rifier si la grille est valide - private static boolean isGridValid(int[][] grid) { - for (int i = 0; i < 9; i++) { - if (!isRowValid(grid, i) || !isColumnValid(grid, i) || !isRegionValid(grid, i)) { - return false; - } - } - return true; - } - - // MĂ©thode pour vĂ©rifier s'il n'y a pas de chiffres en double sur une ligne donnĂ©e - private static boolean isRowValid(int[][] grid, int row) { - boolean[] seen = new boolean[10]; // Tableau pour suivre les chiffres dĂ©jĂ  rencontrĂ©s - for (int i = 0; i < 9; i++) { - int num = grid[row][i]; - if (num != 0) { - if (seen[num]) { - return false; // Le chiffre est dĂ©jĂ  apparu sur cette ligne - } - seen[num] = true; - } - } - return true; // Aucun chiffre en double sur la ligne - } - - // MĂ©thode pour vĂ©rifier s'il n'y a pas de chiffres en double sur une colonne donnĂ©e - private static boolean isColumnValid(int[][] grid, int col) { - boolean[] seen = new boolean[10]; // Tableau pour suivre les chiffres dĂ©jĂ  rencontrĂ©s - for (int i = 0; i < 9; i++) { - int num = grid[i][col]; - if (num != 0) { - if (seen[num]) { - return false; // Le chiffre est dĂ©jĂ  apparu sur cette colonne - } - seen[num] = true; - } - } - return true; // Aucun chiffre en double sur la colonne - } - - // MĂ©thode pour vĂ©rifier s'il n'y a pas de chiffres en double dans une rĂ©gion donnĂ©e - private static boolean isRegionValid(int[][] grid, int region) { - int rowOffset = (region / 3) * 3; - int colOffset = (region % 3) * 3; - boolean[] seen = new boolean[10]; // Tableau pour suivre les chiffres dĂ©jĂ  rencontrĂ©s - for (int i = rowOffset; i < rowOffset + 3; i++) { - for (int j = colOffset; j < colOffset + 3; j++) { - int num = grid[i][j]; - if (num != 0) { - if (seen[num]) { - return false; // Le chiffre est dĂ©jĂ  apparu dans cette rĂ©gion - } - seen[num] = true; - } - } - } - return true; // Aucun chiffre en double dans la rĂ©gion - } -}