PeerWorking : Correction de bugs + Refonte totale du système de création de grille

This commit is contained in:
Moncef STITI 2024-04-16 22:39:23 +02:00
parent 8f6ff0aaf2
commit ff2448dc86
23 changed files with 750 additions and 419 deletions

BIN
src/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -1,88 +0,0 @@
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;
// CODE TEMPORAIRE
// A AMÉLIORER FORTEMENT !!!!!!
/**
* Class to manage grid saving and loading operations.
* @author Moncef STITI
* @author Marco ORFAO
* @version 1.0
*/
public class FileManager {
/**
* Method for save a grid in a file.
* @param grid The grid to save
*/
public static void savegrid(Grille grid) {
// Creating a file selector
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) {
// Obtain user-selected file name
String fileName = fileChooser.getSelectedFile().getAbsolutePath();
// Check and add .gri extension if necessary
if (!fileName.endsWith(".gri")) {
fileName += ".gri";
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
// Writing grid values to file.
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int value = grid.getValue(i, j);
writer.write(value == 0 ? "0" : String.valueOf(value));
}
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Method for loading a grid from a file.
* @return The grid loaded from the file.
*/
public static Grille loadGrid() {
// Creating a file selector
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) {
// Obtain user-selected file name
String fileName = fileChooser.getSelectedFile().getAbsolutePath();
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
Grille grid = 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 value = Character.getNumericValue(caractere);
grid.remplir_case(row, col, value);
}
}
row++;
}
return grid;
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}

View File

@ -0,0 +1,75 @@
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import java.awt.Container;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.Color;
public class GridMakeUserInterfaceView {
private JMenuBar menuBar = new JMenuBar();
private Container content;
private GridMakerGrid grid;
public GridMakeUserInterfaceView(Window window) {
window.setPageTitle("Créateur de grille");
content = window.getContentPane();
BorderLayout gestionnaire = new BorderLayout();
content.setLayout(gestionnaire);
grid = new GridMakerGrid();
// Création des menus
JMenu menuFichier = createMenu("Fichier");
JMenu menuGrille = createMenu("Grille");
JMenu menuAide = createMenu("Aide");
// Ajout des éléments de menu
JMenuItem nouveauItem = createMenuItem("Nouveau", new GridMakerResetGrid(grid));
JMenuItem chargerItem = createMenuItem("Charger", new GridMakerImport(window, grid));
JMenuItem sauvegarderItem = createMenuItem("Sauvegarder", new GridMakerSaver(window, grid));
JMenuItem verifierItem = createMenuItem("Vérifier", new GridMakerChecker(grid));
JMenuItem aideGrilleItem = createMenuItem("Comment créer une grille", new GridMakerHowToCreateController());
JMenuItem reglesSudokuItem = createMenuItem("Règles du Sudoku", new GridMakerRules());
// Ajout du menu "Jouer"
JMenu menuJouer = createMenu("Quitter");
// Création de l'élément de menu "Retour"
JMenuItem retourMenu = createMenuItem("Menu jouer",null);
// Ajout de l'élément "Retour" au menu "Jouer"
menuJouer.add(retourMenu);
// Ajout du menu "Jouer" à la barre de menu
menuBar.add(menuJouer);
// Ajout des menus à la barre de menu
menuFichier.add(nouveauItem);
menuFichier.add(chargerItem);
menuFichier.add(sauvegarderItem);
menuGrille.add(verifierItem);
menuAide.add(aideGrilleItem);
menuAide.add(reglesSudokuItem);
menuBar.add(menuFichier);
menuBar.add(menuGrille);
menuBar.add(menuAide);
window.add(menuBar, BorderLayout.NORTH);
content.add(grid, BorderLayout.CENTER);
window.setDefaultCloseOperation(Window.EXIT_ON_CLOSE);
window.setVisible(true);
}
private JMenu createMenu(String title) {
return new JMenu(title);
}
private JMenuItem createMenuItem(String title, ActionListener listener) {
JMenuItem item = new JMenuItem(title);
item.addActionListener(listener);
return item;
}
}

61
src/GridMakerCase.java Executable file
View File

@ -0,0 +1,61 @@
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridMakerCase extends JPanel implements KeyListener {
private int cellValue = 0;
private String displayText = ""; // Case initialement vide
private JButton actionButton = new JButton(displayText);
public GridMakerCase() {
actionButton.setOpaque(false);
actionButton.setContentAreaFilled(false);
actionButton.setBorderPainted(false);
actionButton.setPreferredSize(new Dimension(50, 50));
actionButton.addKeyListener(this); // Ajout du KeyListener au bouton
BorderLayout gestionnaire = new BorderLayout();
setLayout(gestionnaire);
add(actionButton, BorderLayout.CENTER);
setPreferredSize(new Dimension(60, 60));
}
@Override
public void keyPressed(KeyEvent e) {
int keyChar = e.getKeyChar();
if (Character.isDigit(keyChar)) {
int num = Character.getNumericValue(keyChar);
if (num >= 0 && num <= 9) {
setCellValue(num);
}
}
}
@Override
public void keyReleased(KeyEvent e) {
// Pas de traitement nécessaire
}
@Override
public void keyTyped(KeyEvent e) {
// Pas de traitement nécessaire
}
public void updateDisplay() {
actionButton.setText(displayText.isEmpty() ? "" : displayText);
revalidate();
repaint();
}
public void setCellValue(int value) {
this.cellValue = value;
this.displayText = (value == 0) ? "" : String.valueOf(value); // Mettre à jour avec une chaîne vide si la valeur est 0
updateDisplay();
}
public int getCellValue() {
return this.cellValue;
}
}

137
src/GridMakerChecker.java Executable file
View File

@ -0,0 +1,137 @@
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* La classe GridMakerChecker est utilisée pour vérifier la cohérence de la grille.
* Elle vérifie si les lignes, les colonnes et les régions de la grille respectent les règles du jeu.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GridMakerChecker implements ActionListener {
private GridMakerGrid grid;
/**
* Constructeur pour créer une instance de GridMakerChecker.
* @param grid La grille à vérifier
*/
public GridMakerChecker(GridMakerGrid grid) {
this.grid = grid;
}
/**
* Méthode invoquée lorsqu'un bouton est cliqué.
* Lance la vérification de la grille.
* @param e L'événement d'action
*/
public void actionPerformed(ActionEvent e) {
checkGrid();
}
/**
* Vérifie si la grille est correcte.
* @return true si la grille est correcte, false sinon
*/
public boolean checkGrid() {
if (checkRows() || checkColumns() || checkRegions()) {
showMessage("Grille incorrecte !", "Deux mêmes chiffres sont présents dans la même ligne/colonne/région. Veuillez modifier votre grille !");
return false;
} else {
showMessage("Grille cohérente !", "Votre grille est cohérente. Aucune erreur n'a été trouvée. Vous pouvez maintenant sauvegarder votre grille !");
return true;
}
}
/**
* Affiche un message d'information.
* @param title Le titre du message
* @param message Le contenu du message
*/
private void showMessage(String title, String message) {
JOptionPane.showMessageDialog(null, message, title, JOptionPane.INFORMATION_MESSAGE);
}
/**
* Vérifie les lignes de la grille.
* @return true si une ligne contient des doublons, false sinon
*/
private boolean checkRows() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
for (int j_prime = j + 1; j_prime < 9; j_prime++) {
if (grid.getCellValueAt(i, j) == grid.getCellValueAt(i, j_prime) && grid.getCellValueAt(i, j) != 0) {
return true;
}
}
}
}
return false;
}
/**
* Vérifie les colonnes de la grille.
* @return true si une colonne contient des doublons, false sinon
*/
private boolean checkColumns() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
for (int i_prime = i + 1; i_prime < 9; i_prime++) {
if (grid.getCellValueAt(i, j) == grid.getCellValueAt(i_prime, j) && grid.getCellValueAt(i, j) != 0) {
return true;
}
}
}
}
return false;
}
/**
* Vérifie les régions de la grille.
* @return true si une région contient des doublons, false sinon
*/
private boolean checkRegions() {
for (int i = 0; i < 9; i += 3) {
for (int j = 0; j < 9; j += 3) {
if (checkRegion(i, j)) {
return true;
}
}
}
return false;
}
/**
* Vérifie une région de la grille.
* @param x La coordonnée x de la région
* @param y La coordonnée y de la région
* @return true si la région contient des doublons, false sinon
*/
private boolean checkRegion(int x, int y) {
int[] regionValues = new int[9];
int index = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
regionValues[index++] = grid.getCellValueAt(x + i, y + j);
}
}
for (int i = 0; i < 9; i++) {
for (int j = i + 1; j < 9; j++) {
if (regionValues[i] == regionValues[j] && regionValues[i] != 0) {
return true;
}
}
}
return false;
}
/**
* Vérifie si la grille est correcte.
* @return true si la grille est correcte, false sinon
*/
public boolean isCorrect() {
return checkGrid();
}
}

122
src/GridMakerGrid.java Executable file
View File

@ -0,0 +1,122 @@
import javax.swing.*;
import java.awt.*;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
/**
* A custom JPanel class representing a Sudoku grid.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GridMakerGrid extends JPanel {
private int[][] gridValues = new int[9][9]; // Stores the values of each cell in the grid
private GridMakerCase[][] gridCases = new GridMakerCase[9][9]; // Represents the individual cells in the grid
private int[] exportedGrid = new int[9]; // Stores the grid values in an exportable format
/**
* Constructs a new GridMakerGrid object and initializes the grid.
*/
public GridMakerGrid() {
setupGrid();
setBackground(new Color(54, 91, 109)); // On change la couleur de fond (les cotés de la grille)
}
/**
* Sets up the layout of the Sudoku grid.
*/
private void setupGrid() {
// Add padding around the panel
setBorder(new EmptyBorder(15, 15, 15, 15)); // Adjust the values as needed for desired padding
setLayout(new GridLayout(3, 3)); // Set layout for the main grid panel
// Create 9 zones of 3x3
JPanel[][] zones = new JPanel[3][3];
setLayout(new GridLayout(3, 3));
// Create individual zones and add them to the main grid panel
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
zones[i][j] = new JPanel();
zones[i][j].setLayout(new GridLayout(3, 3));
add(zones[i][j]);
}
}
// Create and add cells to each zone
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int zoneRow = i / 3;
int zoneCol = j / 3;
gridCases[i][j] = new GridMakerCase();
zones[zoneRow][zoneCol].add(gridCases[i][j]);
// Add borders to cells based on their position in the grid
if ((i + 1) % 3 == 0 && (j + 1) % 3 == 0) {
gridCases[i][j].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 5, Color.BLACK));
} else if ((i + 1) % 3 == 0) {
gridCases[i][j].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 1, Color.BLACK));
} else if ((j + 1) % 3 == 0) {
gridCases[i][j].setBorder(BorderFactory.createMatteBorder(1, 1, 1, 5, Color.BLACK));
} else {
gridCases[i][j].setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
}
}
}
}
/**
* Imports values to populate the Sudoku grid.
*
* @param values An array of integers representing the Sudoku grid values.
*/
public void importGrid(int[] values) {
for (int i = 0; i < 9; i++) {
int length = String.valueOf(values[i]).length();
for (int j = 0; j < 9 - length; j++) {
gridValues[i][j] = 0;
gridCases[i][j].setCellValue(gridValues[i][j]);
}
String str = Integer.toString(values[i]);
for (int j = 9 - length, k = 0; j < 9; j++, k++) {
gridValues[i][j] = Character.getNumericValue(str.charAt(k));
gridCases[i][j].setCellValue(gridValues[i][j]);
}
}
}
/**
* Exports the current Sudoku grid values.
*
* @return An array of integers representing the current Sudoku grid values.
*/
public int[] exportGrid() {
for (int i = 0; i < 9; i++) {
StringBuilder temp = new StringBuilder();
for (int j = 0; j < 9; j++) {
temp.append(gridCases[i][j].getCellValue());
}
exportedGrid[i] = Integer.parseInt(temp.toString());
}
return exportedGrid;
}
/**
* Retrieves the value of a cell in the Sudoku grid.
*
* @param row The row index of the cell.
* @param column The column index of the cell.
* @return The value of the cell at the specified row and column indices.
*/
public int getCellValueAt(int row, int column) {
return gridCases[row][column].getCellValue();
}
}

View File

@ -0,0 +1,30 @@
import java.awt.event.*;
/**
* La classe GridMakerHowToCreateController est un contrôleur qui gère l'affichage de la fenêtre de création de grille.
* Elle implémente l'interface ActionListener pour réagir aux événements de clic sur un bouton.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GridMakerHowToCreateController implements ActionListener {
private GridMakerHowToCreateDialogManager howToCreateGrid;
/**
* Constructeur pour créer une instance de GridMakerHowToCreateController.
* Initialise le gestionnaire de dialogue pour la création de grille.
*/
public GridMakerHowToCreateController(){
this.howToCreateGrid = new GridMakerHowToCreateDialogManager();
}
/**
* Méthode invoquée lorsqu'un événement d'action est déclenché, comme un clic sur un bouton.
* Affiche la fenêtre de dialogue pour expliquer comment créer une grille.
* @param e L'événement d'action
*/
@Override
public void actionPerformed(ActionEvent e) {
howToCreateGrid.showDialog(); // On appelle la méthode qui affiche la fenêtre de dialogue
}
}

View File

@ -0,0 +1,21 @@
import javax.swing.JOptionPane;
/**
* La classe GridMakerHowToCreateDialogManager est un gestionnaire de dialogue qui affiche des instructions
* sur la manière de créer une grille dans une boîte de dialogue.
* Elle implémente l'interface DialogManager.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GridMakerHowToCreateDialogManager implements DialogManager {
/**
* Méthode pour afficher la boîte de dialogue avec les instructions de création de grille.
*/
@Override
public void showDialog() {
GridMakerHowToCreateView howToCreateGrid = new GridMakerHowToCreateView();
JOptionPane.showMessageDialog(null, howToCreateGrid, "Comment créer une grille ?", JOptionPane.PLAIN_MESSAGE);
}
}

View File

@ -0,0 +1,52 @@
import javax.swing.*;
import java.awt.*;
/**
* La classe GridMakerHowToCreateView est une vue qui affiche les instructions pour créer une grille dans une boîte de dialogue.
* Elle hérite de JPanel pour servir de composant d'interface utilisateur.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GridMakerHowToCreateView extends JPanel {
private Dimension FRAME_SIZE = new Dimension(600, 500);
private Color BACKGROUND_COLOR = new Color(54, 91, 109);
private String TITLE = "Comment créer une grille";
private Color TITLE_COLOR = new Color(255, 255, 255);
private Font TITLE_FONT = new Font("Copperplate", Font.BOLD, 40);
private String TEXT = "Comment créer une grille :\n\n 1. EXPLICATION \n\n 2. EXPLICATION\n\n 3. EXPLICATION.\n\n 4. EXPLICATION";
private Color TEXT_COLOR = new Color(255, 255, 255);
private Font TEXT_FONT = new Font("Arial", Font.PLAIN, 20);
/**
* Constructeur pour créer une instance de GridMakerHowToCreateView.
* Initialise les composants de la vue et les dispose selon un BorderLayout.
*/
public GridMakerHowToCreateView() {
BorderLayout borderLayout = new BorderLayout();
this.setLayout(borderLayout);
this.setBackground(this.BACKGROUND_COLOR); // Définit la couleur d'arrière-plan du panneau
JLabel titleLabel = new JLabel(this.TITLE);
titleLabel.setFont(this.TITLE_FONT); // Définit la police du titre
titleLabel.setForeground(this.TITLE_COLOR); // Définit la couleur du titre
JTextArea textArea = new JTextArea();
textArea.setText(this.TEXT);
textArea.setEditable(false);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setFont(this.TEXT_FONT); // Définit la police du texte
textArea.setForeground(this.TEXT_COLOR); // Définit la couleur du texte
textArea.setBackground(this.BACKGROUND_COLOR); // Définit la couleur d'arrière-plan du texte
JScrollPane scrollPane = new JScrollPane(textArea);
this.add(titleLabel, BorderLayout.NORTH); // Ajoute le titre en haut du panneau
this.add(scrollPane, BorderLayout.CENTER); // Ajoute le texte avec barre de défilement au centre du panneau
this.setPreferredSize(this.FRAME_SIZE); // Définit la taille préférée du panneau
}
}

87
src/GridMakerImport.java Executable file
View File

@ -0,0 +1,87 @@
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
/**
* La classe GridMakerImport est utilisée pour importer une grille à partir d'un fichier.
* Elle implémente l'interface ActionListener pour réagir aux événements de clic sur un bouton.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GridMakerImport implements ActionListener {
private JFrame previousFrame;
private GridMakerGrid grid;
private boolean accessible;
private File file;
private int[] importedValues = new int[9];
/**
* Constructeur pour créer une instance de GridMakerImport.
* @param frame La fenêtre précédente
* @param sudokuGrid La grille Sudoku
*/
public GridMakerImport(JFrame frame, GridMakerGrid sudokuGrid) {
this.previousFrame = frame;
this.grid = sudokuGrid;
}
/**
* Méthode invoquée lorsqu'un événement d'action est déclenché, comme un clic sur un bouton.
* Importe la grille à partir du fichier sélectionné.
* @param e L'événement d'action
*/
public void actionPerformed(ActionEvent e) {
importGrid();
if (accessible) {
grid.importGrid(importedValues);
}
}
/**
* Affiche une boîte de dialogue de sélection de fichier et importe la grille à partir du fichier sélectionné.
*/
public void importGrid() {
JFileChooser fileChooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("Grid files (*.gri)", "gri");
fileChooser.setFileFilter(filter);
int returnVal = fileChooser.showOpenDialog(previousFrame);
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fileChooser.getSelectedFile();
if (readFile()) {
accessible = true;
} else {
accessible = false;
}
}
}
/**
* Lit les données à partir du fichier sélectionné et les stocke dans un tableau.
* @return true si la lecture est réussie, false sinon
*/
public boolean readFile() {
try {
FileInputStream fileInputStream = new FileInputStream(file);
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
int incrementable = 0;
while (dataInputStream.available() > 0 && incrementable < 9) {
importedValues[incrementable] = dataInputStream.readInt();
incrementable++;
}
dataInputStream.close();
return true;
} catch (FileNotFoundException e) {
System.err.println("File not found.");
return false;
} catch (IOException e) {
System.err.println("IOException.");
return false;
} catch (NumberFormatException e) {
System.err.println("NumberFormatException.");
return false;
}
}
}

48
src/GridMakerResetGrid.java Executable file
View File

@ -0,0 +1,48 @@
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* La classe GridMakerResetGrid ... à compléter
*
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GridMakerResetGrid implements ActionListener {
/**
* La grille à réinitialiser.
*/
private GridMakerGrid myGrid;
/**
* Constructeur pour créer une instance de GridMakerResetGrid.
* @param grid Grille à réinitialiser
*/
public GridMakerResetGrid(GridMakerGrid grid) {
this.myGrid = grid;
}
/**
* Lance la réinitialisation de la grille lors du clic sur le bouton Reset.
* @param e ActionEvent lié à la classe
*/
@Override
public void actionPerformed(ActionEvent e) { // TEMPORAIRE !! À MODIFIER DANS UN FICHIER SÉPARÉ
ResetGrid();
}
/**
* Cette méthode crée une grille vide.
*/
public void ResetGrid() {
int[] array = new int[9];
for (int i = 0; i < 9 ; i++) {
array[i] = 0;
}
this.myGrid.importGrid(array);
}
}

14
src/GridMakerRules.java Executable file
View File

@ -0,0 +1,14 @@
import java.awt.event.*;
public class GridMakerRules implements ActionListener {
private RulesDialogManager rulesDialog;
public GridMakerRules(){
this.rulesDialog = new RulesDialogManager();
}
@Override
public void actionPerformed(ActionEvent e) {
rulesDialog.showDialog(); // On appelle la méthode qui affiche la fenêtre de dialogue
}
}

84
src/GridMakerSaver.java Executable file
View File

@ -0,0 +1,84 @@
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
* Cette classe implémente un gestionnaire d'enregistrement de grille de jeu.
* Elle permet à l'utilisateur de sauvegarder une grille de jeu dans un fichier spécifié.
* Les fichiers de grille sont sauvegardés avec l'extension ".gri".
* Cette classe écoute les événements d'action déclenchés par un composant d'interface utilisateur.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GridMakerSaver implements ActionListener {
private File selectedFile; // Le fichier sélectionné pour sauvegarde
private JFrame parentFrame; // La fenêtre parent
private GridMakerGrid grid; // La grille de jeu à sauvegarder
/**
* Constructeur de la classe GridMakerSaver.
* @param parentFrame La fenêtre parent.
* @param grid La grille de jeu à sauvegarder.
*/
public GridMakerSaver(JFrame parentFrame, GridMakerGrid grid) {
this.parentFrame = parentFrame;
this.grid = grid;
}
/**
* Méthode invoquée lorsqu'un événement d'action est déclenché.
* Elle vérifie si la grille est valide, puis la sauvegarde si c'est le cas.
* Sinon, elle affiche un message d'erreur.
* @param e L'événement d'action déclenché.
*/
public void actionPerformed(ActionEvent e) {
if (isValidGrid()) {
saveGrid();
} else {
JOptionPane.showMessageDialog(parentFrame, "Format de grille non valide.", "Erreur", JOptionPane.ERROR_MESSAGE);
}
}
/**
* Vérifie si la grille est valide en utilisant un test spécifique.
* @return true si la grille est valide, sinon false.
*/
private boolean isValidGrid() {
GridMakerChecker test = new GridMakerChecker(grid);
return test.isCorrect();
}
/**
* Sauvegarde la grille de jeu dans un fichier spécifié par l'utilisateur.
* Affiche un message de succès ou d'erreur selon le résultat de la sauvegarde.
*/
private void saveGrid() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Enregistrer la grille");
FileNameExtensionFilter filter = new FileNameExtensionFilter("Fichiers de grille (*.gri)", "gri");
fileChooser.setFileFilter(filter);
int userSelection = fileChooser.showSaveDialog(parentFrame);
if (userSelection == JFileChooser.APPROVE_OPTION) {
selectedFile = fileChooser.getSelectedFile(); // on stock le fichier choisie au cas ou
try (FileOutputStream fileOutputStream = new FileOutputStream(selectedFile);
DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream)) {
int[] gridData = grid.exportGrid();
for (int i = 0; i < 9; i++) {
dataOutputStream.writeInt(gridData[i]);
}
JOptionPane.showMessageDialog(parentFrame, "Grille sauvegardée avec succès !", "Succès", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException ex) {
JOptionPane.showMessageDialog(parentFrame, "Erreur lors de la sauvegarde de la grille : " + ex.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
}
}
}
}

View File

@ -1,52 +0,0 @@
public class Grille {
private int[][] grille;
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 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;
}
}
// 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 row, int col, int num) {
grille[row][col] = num;
}
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 getValue(int row, int col) {
return grille[row][col];
}
}

View File

@ -1,25 +0,0 @@
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GrilleButtonClickListener implements ActionListener {
private Window window;
public GrilleButtonClickListener(Window window) {
this.window = window;
}
@Override
public void actionPerformed(ActionEvent e) {
Button sourceButton = (Button) e.getSource();
String buttonText = sourceButton.getText();
// Si le bouton "Retour au menu principal" est cliqué, on efface ce qui est présent et on met le menu jouer
if (buttonText.equals("Retour au menu principal")) {
if (window.getContentPane().getComponent(0) instanceof GrilleView) {
GrilleView grilleView = (GrilleView) window.getContentPane().getComponent(0);
grilleView.removeAllComponents(window);
window.changeMenu(new PlayMenuView(this.window)); // PAS BON CAR ON VA CRÉE UN MENU JOUER À CHAQUE FOIS AU LIEU DE RÉUTILISER L'ANCIEN
}
}
}
}

View File

@ -1,69 +0,0 @@
import javax.swing.*;
import java.awt.*;
public class GrilleView extends JPanel {
private final Font BUTTON_FONT = new Font("Copperplate", Font.BOLD, 24);
private final String[] BUTTON_TEXTS = {"Retour au menu principal"};
private final Dimension BUTTON_SIZE = new Dimension(450, 60);
private Grille grille;
private Window window;
private JTextField[][] cases;
public GrilleView(Grille grille, Window window) {
super();
this.grille = grille;
this.window = window;
initialize();
}
private void initialize() {
// Définir le style de fond similaire à HomeView
this.setBackground(new Color(54, 91, 109));
// Définir le gestionnaire de disposition et créer le tableau de cases
this.setLayout(new BorderLayout());
JPanel grillePanel = new JPanel(new GridLayout(9, 9));
grillePanel.setBackground(new Color(54, 91, 109));
this.add(grillePanel, BorderLayout.CENTER);
this.cases = new JTextField[9][9];
// Créer les cases et les ajoutez à la grille
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
int valeur = this.grille.getValeur(row, col);
JTextField caseField = new JTextField(1);
if (valeur != 0) {
caseField.setText(Integer.toString(valeur));
}
caseField.setHorizontalAlignment(JTextField.CENTER);
caseField.setEditable(false);
this.cases[row][col] = caseField;
grillePanel.add(caseField);
}
}
// Ajouter un bouton "Retour au menu principal" en bas
Button retourButton = new Button(BUTTON_TEXTS[0], BUTTON_SIZE, BUTTON_FONT);
retourButton.addActionListener(new GrilleButtonClickListener(window));
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
buttonPanel.setBackground(new Color(54, 91, 109));
buttonPanel.add(retourButton);
this.add(buttonPanel, BorderLayout.SOUTH);
}
public void addComponentsToWindow() {
window.getContentPane().add(this);
window.setPageTitle("Grille");
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
// Method to remove all components from the window
public void removeAllComponents(Window window) {
window.remove(this);
window.revalidate();
window.repaint();
}
}

View File

@ -64,7 +64,7 @@ public class HomeView extends JPanel {
window.add(titlePanel, BorderLayout.NORTH); window.add(titlePanel, BorderLayout.NORTH);
window.add(buttonPanel, BorderLayout.WEST); window.add(buttonPanel, BorderLayout.WEST);
window.add(imageLabel, BorderLayout.EAST); window.add(imageLabel, BorderLayout.EAST);
window.setPageTitle("Menu"); window.setPageTitle("Menu principal");
FlowLayout controlPanelLayout = new FlowLayout(FlowLayout.RIGHT); FlowLayout controlPanelLayout = new FlowLayout(FlowLayout.RIGHT);
JPanel controlPanel = new JPanel(controlPanelLayout); JPanel controlPanel = new JPanel(controlPanelLayout);

View File

@ -16,47 +16,18 @@ public class PlayButtonClickListener implements ActionListener {
String buttonText = sourceButton.getText(); String buttonText = sourceButton.getText();
if (buttonText.equals("Jouer sans grille")) { if (buttonText.equals("Jouer sans grille")) {
Grille nouvelleGrille = new Grille();
SudokuGenerator sudokuGenerator = new SudokuGenerator(nouvelleGrille,81); // 81 = générer une grille avec 81 espaces vides
Grille grilleGeneree = sudokuGenerator.genererGrille(); // Générer la grille
GrilleView grilleView1 = new GrilleView(grilleGeneree, window); // Créer la vue de la grille
window.changeMenu(grilleView1); // Modifier le menu pour afficher la grille générée
} }
else if (buttonText.equals("Générer une grille")) { else if (buttonText.equals("Générer une grille")) {
// Demander à l'utilisateur combien de cases vides ils souhaite sur sa grille Window.removeAllComponents(this.window);
String input = JOptionPane.showInputDialog(window, "Combien de cases vides voulez-vous sur la grille ?", "Nombre de cases vides", JOptionPane.QUESTION_MESSAGE); new GridMakeUserInterfaceView(this.window);
// Vérifier si l'utilisateur a annulé la saisie ou a fermé la fenêtre de dialogue
if (input != null && !input.isEmpty()) {
int nombreChiffres = Integer.parseInt(input);
// Vérifier que le nombre est compris entre 0 et 81
if (nombreChiffres >= 0 && nombreChiffres <= 81) {
Grille nouvelleGrille = new Grille();
SudokuGenerator sudokuGenerator = new SudokuGenerator(nouvelleGrille, nombreChiffres);
Grille grilleGeneree = sudokuGenerator.genererGrille(); // Générer la grille
// Créer la vue de la grille
GrilleView grilleView1 = new GrilleView(grilleGeneree, window);
// Modifier le menu pour afficher la grille générée
window.changeMenu(grilleView1);
} else {
JOptionPane.showMessageDialog(window, "Veuillez saisir un nombre entre 0 et 81.", "Erreur", JOptionPane.ERROR_MESSAGE);
}
} else {
// L'utilisateur a annulé la saisie ou fermé la fenêtre de dialogue, traitement en conséquence
}
} else if (buttonText.equals("Charger une grille")) {
Grille grille = FileManager.loadGrid();
GrilleView grilleView = new GrilleView(grille, window);
window.changeMenu(grilleView);
} else if (buttonText.equals("Charger une grille")) {
} else if (buttonText.equals("Retour au menu principal")) { } else if (buttonText.equals("Retour au menu principal")) {
if (window.getContentPane().getComponent(0) instanceof PlayMenuView) { if (window.getContentPane().getComponent(0) instanceof PlayMenuView) {
PlayMenuView playMenuView = (PlayMenuView) window.getContentPane().getComponent(0); Window.removeAllComponents(window);
playMenuView.removeAllComponents(window);
HomeView homeView = new HomeView(window); HomeView homeView = new HomeView(window);
} }
} }

View File

@ -50,6 +50,7 @@ public class PlayMenuView extends JPanel {
// Method to add components to the window // Method to add components to the window
private void addComponentsToWindow(Window window) { private void addComponentsToWindow(Window window) {
// Layout // Layout
window.setPageTitle("Menu jouer");
setLayout(new BorderLayout()); setLayout(new BorderLayout());
setBackground(BACKGROUND_COLOR); setBackground(BACKGROUND_COLOR);
@ -62,11 +63,4 @@ public class PlayMenuView extends JPanel {
// Add panel to the window // Add panel to the window
window.add(this); window.add(this);
} }
// Method to remove all components from the window
public void removeAllComponents(Window window) {
window.remove(this);
window.revalidate();
window.repaint();
}
} }

View File

@ -2,11 +2,13 @@ import javax.swing.*;
import java.awt.*; import java.awt.*;
public class RulesSudoku extends JPanel { public class RulesSudoku extends JPanel {
private Dimension FRAME_SIZE = new Dimension(400, 500);
private Color BACKGROUND_COLOR = new Color(54, 91, 109);
public RulesSudoku() { public RulesSudoku() {
BorderLayout gestionnaireBorderLayout = new BorderLayout(); BorderLayout gestionnaireBorderLayout = new BorderLayout();
this.setLayout(gestionnaireBorderLayout); this.setLayout(gestionnaireBorderLayout);
this.setBackground(new Color(54, 91, 109)); // Couleur d'arrière-plan du menu principal this.setBackground(this.BACKGROUND_COLOR); // Couleur d'arrière-plan du menu principal
JLabel titleLabel = new JLabel("Règles du Sudoku"); JLabel titleLabel = new JLabel("Règles du Sudoku");
titleLabel.setFont(new Font("Copperplate", Font.BOLD, 40)); // Police du titre titleLabel.setFont(new Font("Copperplate", Font.BOLD, 40)); // Police du titre
@ -23,13 +25,13 @@ public class RulesSudoku extends JPanel {
rulesTextArea.setWrapStyleWord(true); rulesTextArea.setWrapStyleWord(true);
rulesTextArea.setFont(new Font("Arial", Font.PLAIN, 20)); // Police du texte des règles rulesTextArea.setFont(new Font("Arial", Font.PLAIN, 20)); // Police du texte des règles
rulesTextArea.setForeground(Color.WHITE); // Couleur du texte des règles rulesTextArea.setForeground(Color.WHITE); // Couleur du texte des règles
rulesTextArea.setBackground(new Color(54, 91, 109)); // Couleur d'arrière-plan du texte des règles rulesTextArea.setBackground(this.BACKGROUND_COLOR); // Couleur d'arrière-plan du texte des règles
JScrollPane scrollPane = new JScrollPane(rulesTextArea); JScrollPane scrollPane = new JScrollPane(rulesTextArea);
this.add(titleLabel, BorderLayout.NORTH); this.add(titleLabel, BorderLayout.NORTH);
this.add(scrollPane, BorderLayout.CENTER); this.add(scrollPane, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(400, 500)); // Taille de la fenêtre des règles this.setPreferredSize(this.FRAME_SIZE); // Taille de la fenêtre des règles
} }
} }

View File

@ -1,99 +0,0 @@
import java.util.Random;
public class SudokuGenerator {
private int nombreCasesVides;
private Grille grille;
public SudokuGenerator(Grille grille, int nombreCasesVides) {
this.grille = grille;
this.nombreCasesVides = nombreCasesVides;
}
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.getValue(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.getValue(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);
}
}
}

View File

@ -1,40 +0,0 @@
/**
* 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
}
}

View File

@ -51,4 +51,10 @@ public class Window extends JFrame {
revalidate(); revalidate();
repaint(); repaint();
} }
public static void removeAllComponents(Window window) {
window.getContentPane().removeAll();
window.revalidate();
window.repaint();
}
} }