diff --git a/GenerateGrid.java b/GenerateGrid.java index 2159b9f..f34b814 100644 --- a/GenerateGrid.java +++ b/GenerateGrid.java @@ -6,24 +6,28 @@ import java.util.Random; public class GenerateGrid { private static final int GRID_SIZE = 9; private static final int EMPTY_CELL = 0; - private static final int MINIMUM_CLUES = 25; // Modifier ce nombre en fonction du nombre de clues désiré + private static int minimumClues = 25; // Nombre de "clues" par défaut /** * Méthode principale pour tester la génération d'une grille ( Seulement pour le debug ). * @param args Arguments de la ligne de commande (non utilisés). */ public static void main(String[] args) { - Grid grid = generateSudokuGrid(); + Grid grid = generateSudokuGrid(minimumClues); // Utilisation de la variable pour générer la grille printGrid(grid); } /** * Génère une grille de Sudoku. + * @param numberOfClues Le nombre de "clues" (indices déjà remplis) à générer. * @return La grille de Sudoku générée. */ - public static Grid generateSudokuGrid() { + public static Grid generateSudokuGrid(int numberOfClues) { + minimumClues = numberOfClues; // Met à jour le nombre de "clues" + Grid grid = new Grid(); solveSudoku(grid); + ensureUniqueSolution(grid); // Vérifie et assure une solution unique removeNumbers(grid); return grid; } @@ -116,6 +120,51 @@ public class GenerateGrid { } } + /** + * Vérifie et assure qu'il y a une solution unique pour la grille de Sudoku. + * @param grid La grille de Sudoku. + * @return True si la grille a une solution unique, sinon False. + */ + private static boolean ensureUniqueSolution(Grid grid) { + return hasUniqueSolution(grid, 0); + } + + /** + * Vérifie si la grille de Sudoku a une solution unique. + * @param grid La grille de Sudoku à vérifier. + * @param count Le nombre de solutions trouvées jusqu'à présent. + * @return True si la grille a une solution unique, sinon False. + */ + private static boolean hasUniqueSolution(Grid grid, int count) { + // Recherche de solutions supplémentaires après la première + if (count > 1) { + return false; + } + + // Recherche de solutions + if (!solveSudoku(grid)) { + return false; // Aucune solution trouvée + } + + count++; // Une solution trouvée + + if (count == 1 && !hasMultipleSolutions(grid)) { + return true; // Une solution unique trouvée + } + + // Plusieurs solutions trouvées + return false; + } + + /** + * Vérifie si la grille de Sudoku a plusieurs solutions. + * @param grid La grille de Sudoku à vérifier. + * @return True si la grille a plusieurs solutions, sinon False. + */ + private static boolean hasMultipleSolutions(Grid grid) { + return solveSudoku(grid); // Si une deuxième solution est trouvée, la grille a plusieurs solutions + } + /** * Supprime les nombres de la grille pour créer une énigme de Sudoku. * @param grid La grille de Sudoku. @@ -123,7 +172,7 @@ public class GenerateGrid { public static void removeNumbers(Grid grid) { Random random = new Random(); - while (countClues(grid) > MINIMUM_CLUES) { + while (countClues(grid) > minimumClues) { int row = random.nextInt(GRID_SIZE); int col = random.nextInt(GRID_SIZE); int value = grid.getCell(row, col).getValue(); diff --git a/Grid.java b/Grid.java index eddebd2..2024f9d 100644 --- a/Grid.java +++ b/Grid.java @@ -9,14 +9,15 @@ import java.io.IOException; */ public class Grid { private Cell[][] cells; + public static final int SIZE = 9; // Ajout de la variable SIZE /** * Constructeur par défaut qui initialise une grille de Sudoku vide. */ public Grid() { - cells = new Cell[9][9]; - for (int ligne = 0; ligne < 9; ligne++) { - for (int column = 0; column < 9; column++) { + cells = new Cell[SIZE][SIZE]; // Utilisation de la variable SIZE + for (int ligne = 0; ligne < SIZE; ligne++) { + for (int column = 0; column < SIZE; column++) { cells[ligne][column] = new Cell(); } } @@ -24,17 +25,18 @@ public class Grid { /** * Charge une grille de Sudoku à partir d'un fichier. + * * @param fileName Le nom du fichier à partir duquel charger la grille avec extension ".gri". */ public void loadGridFromFile(String fileName) { try (DataInputStream input = new DataInputStream(new FileInputStream(fileName))) { - for (int ligne = 0; ligne < 9; ligne++) { + for (int ligne = 0; ligne < SIZE; ligne++) { String line = String.valueOf(input.readInt()); int length = line.length(); - if (length < 9) { + if (length < SIZE) { line = "000000000".substring(length) + line; // Ajoute les zéros au début si nécessaire } - for (int column = 0; column < 9; column++) { + for (int column = 0; column < SIZE; column++) { char number = line.charAt(column); int value = Character.getNumericValue(number); cells[ligne][column].setValue(value); @@ -45,16 +47,17 @@ public class Grid { System.err.println("Error: " + e.getMessage()); } } - + /** * Sauvegarde la grille de Sudoku dans un fichier ".gri". + * * @param fileName Le nom du fichier dans lequel sauvegarder la grille. */ public void saveGridToFile(String fileName) { try (DataOutputStream output = new DataOutputStream(new FileOutputStream(fileName))) { - for (int ligne = 0; ligne < 9; ligne++) { + for (int ligne = 0; ligne < SIZE; ligne++) { StringBuilder line = new StringBuilder(); - for (int column = 0; column < 9; column++) { + for (int column = 0; column < SIZE; column++) { int value = cells[ligne][column].getValue(); line.append(value); } @@ -68,8 +71,9 @@ public class Grid { /** * Obtient la cellule à la position spécifiée dans la grille. + * * @param ligne L'indice de ligne de la cellule. - * @param col L'indice de colonne de la cellule. + * @param col L'indice de colonne de la cellule. * @return La cellule à la position spécifiée. */ public Cell getCell(int ligne, int col) { @@ -78,22 +82,40 @@ public class Grid { /** * Copie le contenu d'une autre grille dans cette grille. + * * @param second_grid La grille à partir de laquelle copier les valeurs. */ public void copyFrom(Grid second_grid) { - for (int row = 0; row < 9; row++) { - for (int col = 0; col < 9; col++) { + for (int row = 0; row < SIZE; row++) { + for (int col = 0; col < SIZE; col++) { this.cells[row][col].setValue(second_grid.cells[row][col].getValue()); } } } + /** + * Vérifie si la grille est complètement remplie. + * + * @return True si toutes les cellules de la grille sont remplies, False sinon. + */ + public boolean isFull() { + for (int row = 0; row < SIZE; row++) { + for (int col = 0; col < SIZE; col++) { + if (getCell(row, col).getValue() == 0) { + return false; + } + } + } + return true; + } + + /** * Affiche la grille de Sudoku dans la console. */ public void printGrid() { - for (int row = 0; row < 9; row++) { - for (int col = 0; col < 9; col++) { + for (int row = 0; row < SIZE; row++) { + for (int col = 0; col < SIZE; col++) { System.out.print(cells[row][col].getValue() + " "); } System.out.println(); diff --git a/Sudoku.java b/Sudoku.java index 6409306..2b17a26 100644 --- a/Sudoku.java +++ b/Sudoku.java @@ -61,4 +61,4 @@ public class Sudoku { } } -} \ No newline at end of file +} diff --git a/SudokuCreator.java b/SudokuCreator.java index f6682f4..71c8bc5 100644 --- a/SudokuCreator.java +++ b/SudokuCreator.java @@ -117,4 +117,4 @@ public class SudokuCreator extends SudokuUI { new SudokuCreator(sudoku); } -} \ No newline at end of file +} diff --git a/SudokuGame.java b/SudokuGame.java index 09b8858..22ce52a 100644 --- a/SudokuGame.java +++ b/SudokuGame.java @@ -1,6 +1,5 @@ import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; - import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -13,6 +12,7 @@ public class SudokuGame extends SudokuUI { /** * Constructeur de la classe SudokuGame. + * * @param sudoku La grille de Sudoku à utiliser pour le jeu. */ public SudokuGame(Sudoku sudoku) { @@ -22,6 +22,7 @@ public class SudokuGame extends SudokuUI { /** * Méthode pour obtenir le texte du titre de l'interface utilisateur. + * * @return Le texte du titre. */ @Override @@ -42,19 +43,26 @@ public class SudokuGame extends SudokuUI { * Méthode pour créer le bouton de résolution. */ private void createSolveButton() { - JButton solveButton = new JButton("Résoudre"); + JButton solveButton = new JButton("Résoudre (Automatique)"); solveButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { + long startTime = System.nanoTime(); // Temps de début de la résolution + SudokuSolver solver = new SudokuSolver(); // Créez une instance de SudokuSolver Grid solvedGrid = new Grid(); // Créez une nouvelle grille pour stocker la solution solvedGrid.copyFrom(sudoku.getGrid()); // Copiez la grille actuelle de Sudoku // Résolvez la grille if (solver.solve(solvedGrid)) { + long endTime = System.nanoTime(); // Temps de fin de la résolution + long duration = (endTime - startTime) / 1_000_000; // Conversion de nanosecondes en millisecondes + // Si une solution est trouvée, mettez à jour la grille Sudoku avec la solution sudoku.getGrid().copyFrom(solvedGrid); updateGrid(); + JOptionPane.showMessageDialog(null, "La grille a été résolue en " + duration + " millisecondes."); + checkGameCompletion(); // Vérifiez si le jeu est terminé après la résolution } else { // Sinon, affichez un message indiquant que la grille est insoluble JOptionPane.showMessageDialog(null, "La grille est insoluble."); @@ -106,8 +114,48 @@ public class SudokuGame extends SudokuUI { } } + /** + * Méthode pour vérifier si la grille est complètement remplie et si la solution est correcte. + * Affiche une alerte si la grille est résolue correctement. + */ + private void checkGameCompletion() { + Grid grid = sudoku.getGrid(); + boolean isFull = true; + boolean hasErrors = false; + + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + int value = grid.getCell(row, col).getValue(); + if (value == 0) { + isFull = false; + } else if (!isValidMove(grid, row, col, value)) { + hasErrors = true; + } + } + } + + if (isFull && !hasErrors) { + JOptionPane.showMessageDialog(null, "Félicitations ! Vous avez résolu la grille avec succès !"); + } + } + + /** + * Vérifie si le placement d'un nombre dans une cellule est sûr. + * + * @param grid La grille de Sudoku. + * @param row L'indice de ligne de la cellule. + * @param col L'indice de colonne de la cellule. + * @param num Le nombre à vérifier. + * @return True si le placement est sûr, False sinon. + */ + private boolean isValidMove(Grid grid, int row, int col, int num) { + // Votre logique de validation ici + return false; + } + /** * Méthode principale pour démarrer le jeu de Sudoku. + * * @param args Les arguments de la ligne de commande (non utilisés). */ public static void main(String[] args) { diff --git a/SudokuSolver.java b/SudokuSolver.java index aa4a525..d24774e 100644 --- a/SudokuSolver.java +++ b/SudokuSolver.java @@ -10,12 +10,12 @@ public class SudokuSolver { * @return True si la grille a été résolue avec succès, False si elle est insoluble. */ public boolean solve(Grid grid) { - long startTime = System.currentTimeMillis(); // Temps de début de la résolution + long startTime = System.nanoTime(); // Temps de début de la résolution boolean isSolved = solveRecursive(grid); - long endTime = System.currentTimeMillis(); // Temps de fin de la résolution - long duration = endTime - startTime; // Calcul de la durée de résolution + long endTime = System.nanoTime(); // Temps de fin de la résolution + long duration = (endTime - startTime) / 1_000_000; // Conversion de nanosecondes en millisecondes if (isSolved) { System.out.println("La grille a été résolue en " + duration + " millisecondes."); @@ -91,4 +91,4 @@ public class SudokuSolver { return true; } -} \ No newline at end of file +} diff --git a/SudokuUI.java b/SudokuUI.java index 482b358..c8cfda5 100644 --- a/SudokuUI.java +++ b/SudokuUI.java @@ -83,4 +83,5 @@ public abstract class SudokuUI extends JFrame { } } } -} \ No newline at end of file +} +