From 0c81953d8d2ebca465e4d09e99ed9559c879abe9 Mon Sep 17 00:00:00 2001 From: Vince <vi.teissier@gmail.com> Date: Sat, 4 May 2024 17:56:30 +0200 Subject: [PATCH] =?UTF-8?q?Ajout=20javadoc=20Cell.java,GenerateGrid.java,G?= =?UTF-8?q?rid.java=20|=20Am=C3=A9lioration=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cell.java | 19 +++++++- GenerateGrid.java | 58 ++++++++++++++++++++--- Grid.java | 44 +++++++++++------ Makefile | 2 +- Sudoku.java | 6 --- SudokuCreator.java | 106 +++++++++++++++++++++++++++++++++++++++++ SudokuGame.java | 90 +++++++++++++++++++++++++++++++++++ SudokuUI.java | 114 ++++++++------------------------------------- 8 files changed, 316 insertions(+), 123 deletions(-) create mode 100644 SudokuCreator.java create mode 100644 SudokuGame.java diff --git a/Cell.java b/Cell.java index 8d0fda6..4b8ff09 100644 --- a/Cell.java +++ b/Cell.java @@ -1,19 +1,36 @@ +/** + * La classe Cell représente une cellule individuelle dans une grille de Sudoku. + */ public class Cell { private int value; + /** + * Constructeur par défaut initialisant la valeur de la cellule à zéro. + */ public Cell() { this.value = 0; } - // Constructeur prenant une valeur comme argument + /** + * Constructeur prenant une valeur comme argument et l'assignant à la cellule. + * @param value La valeur à assigner à la cellule. + */ public Cell(int value) { this.value = value; } + /** + * Obtient la valeur actuelle de la cellule. + * @return La valeur de la cellule. + */ public int getValue() { return value; } + /** + * Définit une nouvelle valeur pour la cellule. + * @param value La nouvelle valeur à assigner à la cellule. + */ public void setValue(int value) { this.value = value; } diff --git a/GenerateGrid.java b/GenerateGrid.java index f2de7e2..2159b9f 100644 --- a/GenerateGrid.java +++ b/GenerateGrid.java @@ -1,31 +1,49 @@ import java.util.Random; +/** + * Cette classe génère une grille de Sudoku aléatoire. + */ 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é - + /** + * 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 = generatePuzzleGrid(); + Grid grid = generateSudokuGrid(); printGrid(grid); } - public static Grid generatePuzzleGrid() { - return generateGrid(); - } - - public static Grid generateGrid() { + /** + * Génère une grille de Sudoku. + * @return La grille de Sudoku générée. + */ + public static Grid generateSudokuGrid() { Grid grid = new Grid(); solveSudoku(grid); removeNumbers(grid); return grid; } + /** + * Résout la grille de Sudoku donnée. + * @param grid La grille de Sudoku à résoudre. + * @return True si la grille a été résolue avec succès, sinon False. + */ private static boolean solveSudoku(Grid grid) { return solveSudokuHelper(grid, 0, 0); } + /** + * Méthode auxiliaire récursive pour résoudre la grille de Sudoku. + * @param grid La grille de Sudoku à résoudre. + * @param row L'indice de ligne actuel. + * @param col L'indice de colonne actuel. + * @return True si la grille a été résolue avec succès, sinon False. + */ private static boolean solveSudokuHelper(Grid grid, int row, int col) { if (row == GRID_SIZE) { row = 0; @@ -55,6 +73,14 @@ public class GenerateGrid { return false; } + /** + * Vérifie si un mouvement donné est valide. + * @param grid La grille de Sudoku. + * @param row L'indice de ligne. + * @param col L'indice de colonne. + * @param num Le nombre à placer. + * @return True si le mouvement est valide, sinon False. + */ private static boolean isValidMove(Grid grid, int row, int col, int num) { for (int i = 0; i < GRID_SIZE; i++) { if (grid.getCell(row, i).getValue() == num || grid.getCell(i, col).getValue() == num) { @@ -76,6 +102,11 @@ public class GenerateGrid { return true; } + /** + * Mélange les éléments d'un tableau. + * @param array Le tableau à mélanger. + * @param random L'instance de Random à utiliser. + */ private static void shuffleArray(int[] array, Random random) { for (int i = array.length - 1; i > 0; i--) { int index = random.nextInt(i + 1); @@ -85,6 +116,10 @@ public class GenerateGrid { } } + /** + * Supprime les nombres de la grille pour créer une énigme de Sudoku. + * @param grid La grille de Sudoku. + */ public static void removeNumbers(Grid grid) { Random random = new Random(); @@ -101,6 +136,11 @@ public class GenerateGrid { } } + /** + * Compte le nombre de "clues" dans la grille. + * @param grid La grille de Sudoku. + * @return Le nombre de "clues" dans la grille. + */ private static int countClues(Grid grid) { int count = 0; for (int row = 0; row < GRID_SIZE; row++) { @@ -113,6 +153,10 @@ public class GenerateGrid { return count; } + /** + * Affiche la grille de Sudoku dans la console. + * @param grid La grille de Sudoku à afficher. + */ public static void printGrid(Grid grid) { for (int row = 0; row < GRID_SIZE; row++) { for (int col = 0; col < GRID_SIZE; col++) { diff --git a/Grid.java b/Grid.java index f4254af..eddebd2 100644 --- a/Grid.java +++ b/Grid.java @@ -1,14 +1,18 @@ import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.EOFException; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +/** + * La classe Grid représente une grille de Sudoku composée de cellules. + */ public class Grid { private Cell[][] cells; + /** + * 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++) { @@ -18,6 +22,10 @@ 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++) { @@ -33,16 +41,15 @@ public class Grid { } } System.out.println("Success"); - System.out.println(this); - } catch (FileNotFoundException e) { - System.err.println("Erreur : Fichier non trouvé: " + e.getMessage()); - } catch (EOFException e) { - System.err.println("Erreur : Fin de fichier atteinte prématurément: " + e.getMessage()); } catch (IOException e) { - System.err.println("Erreur d'entrée/sortie: " + e.getMessage()); + 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++) { @@ -54,17 +61,25 @@ public class Grid { output.writeInt(Integer.parseInt(line.toString())); } System.out.println("Grille sauvegardée avec succès dans " + fileName); - } catch (FileNotFoundException e) { - System.err.println("Erreur : Fichier non trouvé: " + e.getMessage()); } catch (IOException e) { - System.err.println("Erreur d'entrée/sortie: " + e.getMessage()); + System.err.println("Erreur lors de la sauvegarde de la grille: " + e.getMessage()); } } + /** + * 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. + * @return La cellule à la position spécifiée. + */ public Cell getCell(int ligne, int col) { return cells[ligne][col]; } + /** + * 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++) { @@ -73,6 +88,9 @@ public class Grid { } } + /** + * 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++) { @@ -81,4 +99,4 @@ public class Grid { System.out.println(); } } -} \ No newline at end of file +} diff --git a/Makefile b/Makefile index 4cec9cb..8712f53 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # List of Java source files -SRCS := Cell.java GenerateGrid.java Grid.java Sudoku.java SudokuButtonListener.java SudokuSolver.java SudokuUI.java +SRCS := Cell.java GenerateGrid.java Grid.java Sudoku.java SudokuButtonListener.java SudokuSolver.java SudokuUI.java SudokuCreator.java # Directory to store compiled class files BUILD_DIR := build diff --git a/Sudoku.java b/Sudoku.java index d3a0d59..ad5828f 100644 --- a/Sudoku.java +++ b/Sudoku.java @@ -6,12 +6,6 @@ public class Sudoku { this.grid = new Grid(); // Initialiser avec une grille vide this.solved = false; } - - public static void main(String[] args) { - Sudoku sudoku = new Sudoku(); - sudoku.printGrid(); // Afficher la grille non résolue dans la console - new SudokuUI(sudoku); - } public Grid getGrid() { return grid; diff --git a/SudokuCreator.java b/SudokuCreator.java new file mode 100644 index 0000000..6f2fbc2 --- /dev/null +++ b/SudokuCreator.java @@ -0,0 +1,106 @@ +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; + +public class SudokuCreator extends SudokuUI { + + public SudokuCreator(Sudoku sudoku) { + super(sudoku); + createAdditionalButtons(); + } + + @Override + protected String getTitleText() { + return "Sudoku Creator"; + } + + protected void createAdditionalButtons() { + createLoadButton(); + createGenerateButton(); + createSaveButton(); + pack(); + } + + private void createLoadButton() { + JButton loadButton = new JButton("Charger"); + loadButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fileChooser = new JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Fichiers de grille Sudoku (*.gri)", "gri"); + fileChooser.setFileFilter(filter); + int returnValue = fileChooser.showOpenDialog(null); + if (returnValue == JFileChooser.APPROVE_OPTION) { + File selectedFile = fileChooser.getSelectedFile(); + sudoku.loadGridFromFile(selectedFile.getAbsolutePath()); + updateGrid(); + } + } + }); + + JPanel buttonPanel = new JPanel(); + buttonPanel.add(loadButton, BorderLayout.NORTH); + add(buttonPanel, BorderLayout.NORTH); + } + + private void createGenerateButton() { + JButton generateButton = new JButton("Générer"); + generateButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Générer une nouvelle grille Sudoku + Grid newGrid = GenerateGrid.generateSudokuGrid(); + // Définir la nouvelle grille dans l'instance de Sudoku + sudoku.setGrid(newGrid); + // Afficher la grille générée dans la console + sudoku.printGrid(); + // Mettre à jour l'interface utilisateur pour afficher la nouvelle grille + updateGrid(); + } + }); + + JPanel buttonPanel = new JPanel(); + buttonPanel.add(generateButton, BorderLayout.EAST); + add(buttonPanel, BorderLayout.EAST); + } + + private void createSaveButton() { + JButton saveButton = new JButton("Sauvegarder"); + saveButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fileChooser = new JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Fichiers de grille Sudoku (*.gri)", "gri"); + fileChooser.setFileFilter(filter); + int returnValue = fileChooser.showSaveDialog(null); + if (returnValue == JFileChooser.APPROVE_OPTION) { + File selectedFile = fileChooser.getSelectedFile(); + sudoku.getGrid().saveGridToFile(selectedFile.getAbsolutePath()); + } + } + }); + + JPanel buttonPanel = new JPanel(); + buttonPanel.add(saveButton, BorderLayout.WEST); + add(buttonPanel, BorderLayout.WEST); + } + + private void updateGrid() { + Grid grid = sudoku.getGrid(); + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + int value = grid.getCell(row, col).getValue(); + buttons[row][col].setText(value == 0 ? "" : String.valueOf(value)); + } + } + } + + public static void main(String[] args) { + Sudoku sudoku = new Sudoku(); + new SudokuCreator(sudoku); + } + +} diff --git a/SudokuGame.java b/SudokuGame.java new file mode 100644 index 0000000..c4b65f4 --- /dev/null +++ b/SudokuGame.java @@ -0,0 +1,90 @@ +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +public class SudokuGame extends SudokuUI { + + public SudokuGame(Sudoku sudoku) { + super(sudoku); + createAdditionalButtons(); + } + + @Override + protected String getTitleText() { + return "Sudoku Game"; + } + + protected void createAdditionalButtons() { + createLoadButton(); + createSolveButton(); + pack(); // Redimensionner la fenêtre pour s'adapter aux nouveaux boutons + } + + + private void createSolveButton() { + JButton solveButton = new JButton("Résoudre"); + solveButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + 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)) { + // Si une solution est trouvée, mettez à jour la grille Sudoku avec la solution + sudoku.getGrid().copyFrom(solvedGrid); + updateGrid(); + } else { + // Sinon, affichez un message indiquant que la grille est insoluble + JOptionPane.showMessageDialog(null, "La grille est insoluble."); + } + } + }); + + JPanel buttonPanel = new JPanel(); + buttonPanel.add(solveButton); + add(buttonPanel, BorderLayout.SOUTH); + } + + private void createLoadButton() { + JButton loadButton = new JButton("Charger"); + loadButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fileChooser = new JFileChooser(); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Fichiers de grille Sudoku (*.gri)", "gri"); + fileChooser.setFileFilter(filter); + int returnValue = fileChooser.showOpenDialog(null); + if (returnValue == JFileChooser.APPROVE_OPTION) { + File selectedFile = fileChooser.getSelectedFile(); + sudoku.loadGridFromFile(selectedFile.getAbsolutePath()); + updateGrid(); + } + } + }); + + JPanel buttonPanel = new JPanel(); + buttonPanel.add(loadButton); + add(buttonPanel, BorderLayout.NORTH); + } + + private void updateGrid() { + Grid grid = sudoku.getGrid(); + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + int value = grid.getCell(row, col).getValue(); + buttons[row][col].setText(value == 0 ? "" : String.valueOf(value)); + } + } + } + + public static void main(String[] args) { + Sudoku sudoku = new Sudoku(); + new SudokuGame(sudoku); + } +} diff --git a/SudokuUI.java b/SudokuUI.java index af5bcb1..4aaa628 100644 --- a/SudokuUI.java +++ b/SudokuUI.java @@ -1,19 +1,15 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import javax.swing.filechooser.FileNameExtensionFilter; -public class SudokuUI extends JFrame { - private Sudoku sudoku; - private JButton[][] buttons; +public abstract class SudokuUI extends JFrame { + protected Sudoku sudoku; + protected JButton[][] buttons; public SudokuUI(Sudoku sudoku) { this.sudoku = sudoku; this.buttons = new JButton[9][9]; - setTitle("Sudoku"); + setTitle(getTitleText()); setDefaultCloseOperation(EXIT_ON_CLOSE); JPanel gridPanel = new JPanel(new GridLayout(9, 9)); gridPanel.setBackground(Color.WHITE); @@ -22,13 +18,6 @@ public class SudokuUI extends JFrame { // Création des boutons de la grille createGridButtons(gridPanel); - // Création du bouton "Résoudre" - createSolveButton(); - - // Création des boutons "Charger" et "Générer" - createLoadButton(); - createGenerateButton(); - // Calcul de la taille préférée de la fenêtre en fonction de la taille de la grille int preferredSize = 50 * 9; // 50 est la taille approximative d'un bouton gridPanel.setPreferredSize(new Dimension(preferredSize, preferredSize)); @@ -39,7 +28,9 @@ public class SudokuUI extends JFrame { setVisible(true); } - private void createGridButtons(JPanel gridPanel) { + protected abstract String getTitleText(); + + protected void createGridButtons(JPanel gridPanel) { Grid grid = sudoku.getGrid(); // Obtenez la grille à partir de Sudoku for (int row = 0; row < 9; row++) { for (int col = 0; col < 9; col++) { @@ -47,94 +38,27 @@ public class SudokuUI extends JFrame { button.setFont(new Font("Arial", Font.BOLD, 24)); button.setContentAreaFilled(false); button.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + button.setMinimumSize(new Dimension(50, 50)); // Taille minimale des boutons + + // Ajout de bordures plus épaisses pour délimiter les carrés de 3x3 + if ((row + 1) % 3 == 0 && (col + 1) % 3 == 0) { + button.setBorder(BorderFactory.createMatteBorder(1, 1, 3, 3, Color.BLACK)); + } else if ((row + 1) % 3 == 0) { + button.setBorder(BorderFactory.createMatteBorder(1, 1, 3, 1, Color.BLACK)); + } else if ((col + 1) % 3 == 0) { + button.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 3, Color.BLACK)); + } + button.addActionListener(new SudokuButtonListener(row, col, sudoku, buttons)); gridPanel.add(button); buttons[row][col] = button; - + // Mettez à jour le texte des boutons avec les valeurs de la grille Sudoku int value = grid.getCell(row, col).getValue(); buttons[row][col].setText(value == 0 ? "" : String.valueOf(value)); } } } - - private void createSolveButton() { - JButton solveButton = new JButton("Résoudre"); - solveButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - 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)) { - // Si une solution est trouvée, mettez à jour la grille Sudoku avec la solution - sudoku.getGrid().copyFrom(solvedGrid); - updateGrid(); - } else { - // Sinon, affichez un message indiquant que la grille est insoluble - JOptionPane.showMessageDialog(null, "La grille est insoluble."); - } - } - }); - - JPanel buttonPanel = new JPanel(); - buttonPanel.add(solveButton); - add(buttonPanel, BorderLayout.SOUTH); - } - - private void createLoadButton() { - JButton loadButton = new JButton("Charger"); - loadButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser fileChooser = new JFileChooser(); - FileNameExtensionFilter filter = new FileNameExtensionFilter("Fichiers de grille Sudoku (*.gri)", "gri"); - fileChooser.setFileFilter(filter); - int returnValue = fileChooser.showOpenDialog(null); - if (returnValue == JFileChooser.APPROVE_OPTION) { - File selectedFile = fileChooser.getSelectedFile(); - sudoku.loadGridFromFile(selectedFile.getAbsolutePath()); - updateGrid(); - } - } - }); - - JPanel buttonPanel = new JPanel(); - buttonPanel.add(loadButton); - add(buttonPanel, BorderLayout.NORTH); - } - - private void createGenerateButton() { - JButton generateButton = new JButton("Générer"); - generateButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - // Générer une nouvelle grille Sudoku - Grid newGrid = GenerateGrid.generatePuzzleGrid(); - // Définir la nouvelle grille dans l'instance de Sudoku - sudoku.setGrid(newGrid); - // Afficher la grille générée dans la console - sudoku.printGrid(); - // Mettre à jour l'interface utilisateur pour afficher la nouvelle grille - updateGrid(); - } - }); - - JPanel buttonPanel = new JPanel(); - buttonPanel.add(generateButton); - add(buttonPanel, BorderLayout.EAST); - } - private void updateGrid() { - Grid grid = sudoku.getGrid(); - for (int row = 0; row < 9; row++) { - for (int col = 0; col < 9; col++) { - int value = grid.getCell(row, col).getValue(); - buttons[row][col].setText(value == 0 ? "" : String.valueOf(value)); - } - } - } }