Ajout de GridSolver - Avant modification + jointure des classes

This commit is contained in:
Marco ORFAO 2024-04-26 11:29:30 +02:00
parent 8d482356d3
commit 79010f68fd
25 changed files with 1548 additions and 3 deletions

View File

@ -13,7 +13,7 @@ JCFLAGS := -encoding UTF-8 -implicit:none
JVM := java
JVMFLAGS :=
SRCDIR := ./src/GridMaker
SRCDIR := ./src/GridSolver
OUTDIR := ./out
DOCDIR := ./doc
SRC := $(wildcard $(SRCDIR)/*.java)

BIN
src/.DS_Store vendored

Binary file not shown.

View File

@ -110,10 +110,8 @@ public class GridMakerGrid extends JPanel {
for (int j = 0; j < 9; j++) {
temp.append(gridCases[i][j].getCellValue());
}
exportedGrid[i] = Integer.parseInt(temp.toString());
}
return exportedGrid;
}

View File

@ -0,0 +1,61 @@
import javax.swing.*;
import java.awt.*;
/**
* Class containing custom settings for JButtons.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class Button extends JButton {
/**
* Constructor
* @param text The text of the button
*/
public Button (String text) {
super(text);
setFont(new Font("Arial", Font.BOLD, 15));
setBackground(new Color(96, 175, 255));
}
/**
* Constructor
* @param text The text of the button
* @param dimension The dimension of the button
*/
public Button(String text, Dimension dimension) {
super(text);
setPreferredSize(dimension);
setFont(new Font("Arial", Font.BOLD, 20));
setBackground(new Color(96, 175, 255));
}
/**
* Constructor
* @param text The text of the button
* @param dimension The dimension of the button
* @param font The font of the text in the button
*/
public Button(String text, Dimension dimension, Font font) {
super(text);
setPreferredSize(dimension);
setFont(font);
setBackground(new Color(96, 175, 255));
}
/**
* Constructor
* @param text The text of the button
* @param dimension The dimension of the button
* @param font The font of the text in the button
* @param color The background color of the button
*/
public Button(String text, Dimension dimension, Font font, Color color) {
super(text);
setPreferredSize(dimension);
setFont(font);
setBackground(color);
}
}

View File

@ -0,0 +1,39 @@
import javax.swing.JOptionPane;
/**
* Cette classe permet de crée une boîte de dialogue de félicitations pour afficher le temps de résolution d'un Sudoku.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class CongratulationsDialog extends JOptionPane {
/**
* Constructeur de la classe CongratulationsDialog.
* @param solvingStartTime Le temps de démarrage de la résolution du Sudoku en nanosecondes.
*/
public CongratulationsDialog(long solvingStartTime) {
super();
// Obtenir le temps actuel en nanosecondes
long currentTime = System.nanoTime();
// Calculer le temps de résolution en secondes
long solvingTime = (currentTime - solvingStartTime) / 1_000_000_000;
// Créer le message de félicitations en fonction du temps de résolution
String message;
long minutes = solvingTime / 60;
long seconds = solvingTime % 60;
// Gérer le pluriel pour les minutes
String minutesString = (minutes <= 1) ? " minute" : " minutes";
// Gérer le pluriel pour les secondes
String secondsString = (seconds <= 1) ? " seconde" : " secondes";
message = "Félicitations ! Vous avez résolu le Sudoku en " + minutes + minutesString + " et " + seconds + secondsString + ".";
showMessageDialog(null, message, "Félicitations !", JOptionPane.PLAIN_MESSAGE);
}
}

View File

@ -0,0 +1,10 @@
/**
* Interface containing definition to showDialog box.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public interface DialogManager {
void showDialog();
}

201
src/GridSolver/GSCase.java Executable file
View File

@ -0,0 +1,201 @@
import java.awt.*;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
/**
* La classe GSCase représente une case individuelle dans une grille de Sudoku.
*/
public class GSCase extends JPanel implements MouseListener{
private int primaryValue; // Valeur principale de la case
private int secondaryValue; // Deuxième valeur de la case (utilisée pour les cas spéciaux)
private int tertiaryValue; // Troisième valeur de la case (utilisée pour les cas spéciaux)
private int quaternaryValue; // Quatrième valeur de la case (utilisée pour les cas spéciaux)
private String text = ""; // Texte affiché dans la case
private Boolean isInitial = false; // Indique si la valeur de la case est initiale (fournie avec le puzzle)
private Boolean isActive; // Indique si la case est active (sélectionnée par l'utilisateur)
JLabel label = new JLabel(); // Composant pour afficher le texte dans la case
private byte digitCount = 0; // Compte le nombre de valeurs insérées dans la case
private int positionX; // Position X de la case dans la grille
private int positionY; // Position Y de la case dans la grille
private GSGrid parentGrid; // Référence à la grille parente
/**
* Constructeur de la classe GSCase.
* @param grid La grille parente à laquelle cette case appartient.
* @param x Position X de la case dans la grille.
* @param y Position Y de la case dans la grille.
*/
public GSCase(GSGrid grid, int x, int y) {
this.positionX = x;
this.positionY = y;
this.primaryValue = 0;
this.secondaryValue = 0;
this.tertiaryValue = 0;
this.quaternaryValue = 0;
this.setBackground(Color.white);
this.addMouseListener(this);
this.parentGrid = grid;
this.add(label);
deactivateCell();
layoutSetup();
}
/**
* Configure l'apparence initiale de la case.
*/
public void layoutSetup() {
this.label.setText(this.primaryValue != 0 ? this.text : "");
this.label.setVisible(true);
this.repaint();
}
/**
* Initialise la case avec une valeur initiale.
*/
public void initializeCell() {
label.setText(this.text);
this.setBackground(this.isInitial ? Color.lightGray : Color.white);
layoutSetup();
}
/**
* Définit la valeur de la case.
* @param value La valeur à définir pour la case.
*/
public void setValue(int value) {
this.isInitial = (value != 0);
this.text = (value != 0) ? String.valueOf(value) : "";
this.primaryValue = value;
initializeCell();
}
/**
* Obtient la valeur de la case.
* @return La valeur de la case.
*/
public int getValue(){
return this.primaryValue;
}
/**
* Gère les actions de clic de souris sur la case.
*/
public void mouseClicked(MouseEvent e) {
if (!this.isInitial) {
this.isActive = true;
this.setBackground(Color.GREEN);
this.parentGrid.testActivity(this.positionX, this.positionY);
}
}
// D'autres méthodes de l'interface MouseListener
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
if (!isInitial) {
if (!isActive) {
this.setBackground(Color.yellow);
}
}
}
public void mouseExited(MouseEvent e) {
if (!isInitial) {
if (!isActive) {
this.setBackground(Color.white);
}
}
}
/**
* Désactive la case.
*/
public void deactivateCell(){
this.isActive = false;
this.setBackground(Color.white);
}
/**
* Obtient l'état d'activité de la case.
* @return True si la case est active, sinon False.
*/
public Boolean getActivity(){
return this.isActive;
}
/**
* Met à jour la valeur de la case.
* @param value La nouvelle valeur de la case.
*/
public void updateValue(int value){
if (value == 0) {
this.primaryValue = 0;
this.digitCount = 0;
layoutSetup();
} else {
if (!checkInputValue(value)) {
if (this.primaryValue != value ) {
if (this.digitCount == 0) {
this.digitCount++;
this.primaryValue = value;
this.text = String.valueOf(this.primaryValue);
} else if (this.digitCount == 1 && value != this.primaryValue) {
this.secondaryValue = value;
this.digitCount++;
this.text = String.valueOf(this.primaryValue + ", " + this.secondaryValue);
} else if (this.digitCount == 2 && value != this.primaryValue && value != this.secondaryValue) {
this.tertiaryValue = value;
this.digitCount++;
this.text = String.valueOf(this.primaryValue + ", " + this.secondaryValue + ", " + this.tertiaryValue);
} else if (this.digitCount == 3 && value != this.primaryValue && value != this.secondaryValue && value != this.tertiaryValue) {
this.quaternaryValue = value;
this.digitCount++;
this.text = String.valueOf(this.primaryValue + ", " + this.secondaryValue + ", " + this.tertiaryValue + ", " + this.quaternaryValue);
}
}
this.setBackground(Color.WHITE);
layoutSetup();
} else if (checkInputValue(value)){
this.setBackground(Color.RED);
}
}
}
/**
* Vérifie si la valeur entrée est valide pour la case.
* @param val La valeur à vérifier.
* @return True si la valeur est valide, sinon False.
*/
public Boolean checkInputValue(int val){
int temp = this.primaryValue;
this.primaryValue = val;
GSTest test = new GSTest(this.parentGrid);
Boolean isValid = test.test();
this.primaryValue = temp;
return isValid;
}
/**
* Obtient le nombre de valeurs insérées dans la case.
* @return Le nombre de valeurs insérées.
*/
public int getDigitCount(){
return this.digitCount;
}
/**
* Insère une valeur dans la case.
* @param value La valeur à insérer.
*/
public void insertValue(int value){
this.primaryValue = value;
this.text = String.valueOf(this.primaryValue);
layoutSetup();
}
}

180
src/GridSolver/GSGrid.java Executable file
View File

@ -0,0 +1,180 @@
import javax.swing.*;
import java.awt.*;
import javax.swing.border.Border;
/**
* Cette classe représente la grille de jeu pour le Sudoku.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSGrid extends JLabel {
private static final int GRID_SIZE = 9;
private int[][] tableauGrille = new int[GRID_SIZE][GRID_SIZE];
private GSCase[][] cases = new GSCase[GRID_SIZE][GRID_SIZE];
private GSMenu menu;
private int activeX = 0;
private int activeY = 0;
private Boolean isPlaying;
/**
* Constructeur de la classe GSGrid.
* @param menu Le menu associé à la grille.
*/
public GSGrid(GSMenu menu) {
this.menu = menu;
initializeGrid();
}
// Initialise la grille avec des cases vides
private void initializeGrid() {
FlowLayout gestionnaire = new FlowLayout();
this.setLayout(gestionnaire);
JPanel gridContainer = new JPanel();
gridContainer.setLayout(new GridLayout(GRID_SIZE, GRID_SIZE));
Dimension cellSize = new Dimension(91, 71);
for (int i = 0; i < GRID_SIZE; i++) {
for (int j = 0; j < GRID_SIZE; j++) {
cases[i][j] = new GSCase(this, i, j);
setCellBorder(i, j);
cases[i][j].setPreferredSize(cellSize);
gridContainer.add(cases[i][j]);
}
}
this.add(gridContainer);
}
// Détermine les bordures des cellules de la grille
private Border determineBorder(int i, int j) {
int top = (i == 0) ? 5 : 1;
int bottom = ((i + 1) % 3 == 0) ? 5 : 1;
int left = (j == 0) ? 5 : 1;
int right = ((j + 1) % 3 == 0) ? 5 : 1;
return BorderFactory.createMatteBorder(top, left, bottom, right, Color.BLACK);
}
// Applique les bordures aux cellules de la grille
private void setCellBorder(int i, int j) {
cases[i][j].setBorder(determineBorder(i, j));
}
/**
* Importe les données du Sudoku dans la grille.
* @param go Tableau d'entiers représentant les données du Sudoku.
*/
public void importGrid(int[] go){
int i,j;
int longueur;
for (i = 0; i < 9 ; i++) {
longueur = String.valueOf(go[i]).length();
for ( j = 0; j < 9 - longueur; j++) {
this.tableauGrille[i][j] = 0;
this.cases[i][j].setValue(this.tableauGrille[i][j]);
this.cases[i][j].repaint();
}
int[] transfert = new int[longueur];
String str = Integer.toString(go[i]);
for ( j = 0; j < longueur; j++) {
transfert[j] = (int) Character.getNumericValue(str.charAt(j));
}
int k = 0;
for ( j = 9 - longueur; j < 9; j++) {
this.tableauGrille[i][j] = transfert[k];
k++;
this.cases[i][j].setValue(this.tableauGrille[i][j]);
this.cases[i][j].repaint();
}
}
this.menu.enablePlayOptions();
}
/**
* Récupère la valeur d'une case à une position spécifique dans la grille.
* @param i L'indice de ligne de la case.
* @param j L'indice de colonne de la case.
* @return La valeur de la case à la position spécifiée.
*/
public int getCellValue(int i, int j) {
return cases[i][j].getValue();
}
// Désactive les cases autres que celle indiquée
public void testActivity(int x, int y){
for (int i = 0 ; i < GRID_SIZE ; i++ ) {
for (int j = 0 ; j < GRID_SIZE ; j++ ) {
if (cases[i][j].getActivity() && (i != x || j != y)) {
activeX = x;
activeY = y;
cases[i][j].deactivateCell();
}
}
}
}
// Retourne l'index X de la case active
public int whoIsActive_X() {
return activeX;
}
// Retourne l'index Y de la case active
public int whoIsActive_Y() {
return activeY;
}
// Met à jour la valeur d'une case dans la grille
public void setValuetoCase(int x, int y, int val) {
if (cases[x][y].getActivity() && getMode()) {
cases[x][y].updateValue(val);
}
}
// Vérifie si la grille est complète
public Boolean isComplete(){
for (int i = 0 ; i < 9 ; i++ ) {
for (int j = 0 ; j < 9 ; j++ ) {
if (this.cases[i][j].getDigitCount() != 1 && this.cases[i][j].getValue() == 0) {
return true;
}
}
}
return false;
}
// Active ou désactive le mode de jeu
public void isPlaying(Boolean _bool) {
this.isPlaying = _bool;
}
// Retourne le mode de jeu
public Boolean getMode() {
return this.isPlaying;
}
// Résout le Sudoku
public boolean solve() {
for (int row = 0; row < 9; row++) {
for (int column = 0; column < 9; column++) {
if (this.tableauGrille[row][column] == 0) {
for (int k = 1; k <= 9; k++) {
this.tableauGrille[row][column] = k;
this.cases[row][column].insertValue(k);
GSTest _test = new GSTest(this);
if (_test.isValid(row, column) && solve()) {
return true;
}
this.tableauGrille[row][column] = 0;
this.cases[row][column].insertValue(0);
}
return false;
}
}
}
return true;
}
}

84
src/GridSolver/GSImport.java Executable file
View File

@ -0,0 +1,84 @@
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
/**
* La classe GSImport est utilisée pour importer une grille à partir d'un fichier.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSImport {
private Window previousFrame;
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 GSImport(Window frame) {
this.previousFrame = frame;
}
/**
* 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;
}
}
public boolean isAccessible() {
return accessible;
}
/**
* Gets the array of imported values.
* @return the array of imported values
*/
public int[] getImportedValues() {
return importedValues;
}
}

88
src/GridSolver/GSMenu.java Executable file
View File

@ -0,0 +1,88 @@
import javax.swing.*;
import java.awt.*;
/**
* La classe GSMenu représente le menu jouer du jeu Sudoku.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSMenu {
private Window window; // Fenêtre dans laquelle le menu est affiché
private JPanel titlePanel; // Panneau pour le titre
private JPanel buttonPanel; // Panneau pour les boutons
private Title titleLabel; // Étiquette pour le titre
private Button importerButton; // Bouton pour importer une grille
private Button jouerButton; // Bouton pour commencer à jouer
private Button autoSolveButton; // Bouton pour résoudre automatiquement la grille
/**
* Constructeur de la classe GSMenu.
* @param window La fenêtre dans laquelle afficher le menu.
*/
public GSMenu(Window window) {
this.window = window;
this.window.setLayout(new BorderLayout());
// Initialisation du panneau de titre
this.titlePanel = new JPanel();
this.titlePanel.setBackground(new Color(54, 91, 109));
this.titlePanel.setLayout(new GridLayout(2, 1));
// Création des étiquettes de titre et sous-titre
this.titleLabel = new Title("Jouer", new Font("Copperplate", Font.BOLD, 45), Color.WHITE);
// Ajout des étiquettes au panneau de titre
this.titlePanel.add(this.titleLabel);
// Initialisation du panneau de boutons
this.buttonPanel = new JPanel();
this.buttonPanel.setLayout(new GridLayout(1, 3, 10, 0));
this.buttonPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
this.buttonPanel.setBackground(new Color(54, 91, 109));
// Création des boutons
this.importerButton = new Button("Charger une grille");
this.jouerButton = new Button("Jouer");
this.jouerButton.setEnabled(false); // Le bouton "Jouer" est désactivé par défaut
this.autoSolveButton = new Button("Résolution automatique");
this.autoSolveButton.setEnabled(false); // Le bouton "Résolution automatique" est désactivé par défaut
// Ajout des boutons au panneau de boutons
this.buttonPanel.add(this.importerButton);
this.buttonPanel.add(this.jouerButton);
this.buttonPanel.add(this.autoSolveButton);
// Ajout des panneaux à la fenêtre
this.window.add(this.titlePanel, BorderLayout.NORTH);
this.window.add(this.buttonPanel, BorderLayout.CENTER);
// Définition du titre de la page
this.window.setPageTitle("Menu jouer");
// Ajustement de la taille de la fenêtre en fonction de son contenu
this.window.pack();
}
/**
* Active les options de jeu dans le menu.
*/
public void enablePlayOptions() {
this.jouerButton.setEnabled(true); // Active le bouton "Jouer"
this.autoSolveButton.setEnabled(true); // Active le bouton "Résolution automatique"
}
// Méthodes getters pour les composants
public Button getImporterButton() {
return this.importerButton;
}
public Button getJouerButton() {
return this.jouerButton;
}
public Button getAutoSolveButton() {
return this.autoSolveButton;
}
}

View File

@ -0,0 +1,60 @@
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* La classe GSMenuController gère les actions déclenchées par les boutons du menu.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSMenuController implements ActionListener {
private GSMenu gsMenu; // Menu Sudoku
private Window mainWindow; // Fenêtre principale
private GSGrid sudokuGrid; // Grille de Sudoku
/**
* Constructeur de la classe GSMenuController.
* @param gsMenu Le menu Sudoku à contrôler.
* @param mainWindow La fenêtre principale.
*/
public GSMenuController(GSMenu gsMenu, Window mainWindow) {
this.gsMenu = gsMenu;
this.mainWindow = mainWindow;
this.sudokuGrid = new GSGrid(gsMenu); // Initialise la grille de Sudoku
// Ajout de l'action listener pour les boutons du menu
gsMenu.getImporterButton().addActionListener(this);
gsMenu.getJouerButton().addActionListener(this);
gsMenu.getAutoSolveButton().addActionListener(this);
}
/**
* Méthode appelée lorsqu'une action est effectuée (clic sur un bouton).
* @param e L'événement associé à l'action.
*/
@Override
public void actionPerformed(ActionEvent e) {
// Si le bouton "Importer" est cliqué
if (e.getSource() == gsMenu.getImporterButton()) {
GSImport importer = new GSImport(mainWindow); // Crée un gestionnaire d'importation de grille
importer.importGrid(); // Importe une grille
if (importer.isAccessible()) {
sudokuGrid.importGrid(importer.getImportedValues()); // Met à jour la grille avec les valeurs importées
// Réactive les options de jeu dans le menu
gsMenu.enablePlayOptions();
sudokuGrid.isPlaying(true); // Indique que le jeu est en cours
}
}
// Si le bouton "Jouer" est cliqué
else if (e.getSource() == gsMenu.getJouerButton()) {
GSPlay jeu = new GSPlay(this.mainWindow,this.sudokuGrid); // Crée un jeu Sudoku
GSPlayController jeuController = new GSPlayController(jeu); // Crée un contrôleur pour le jeu
gsMenu.getJouerButton().addKeyListener(jeuController); // Ajoute un écouteur de touches pour le jeu
jeu.showGame(); // Affiche le jeu
}
// Si le bouton "Résoudre automatiquement" est cliqué
else if (e.getSource() == gsMenu.getAutoSolveButton()) {
GSSolver resolveurDeGrille = new GSSolver(this.sudokuGrid,this.mainWindow); // Crée un résolveur de grille
}
}
}

108
src/GridSolver/GSPlay.java Executable file
View File

@ -0,0 +1,108 @@
import java.awt.*;
import java.awt.event.*;
/**
* Classe GSPlay pour jouer au Sudoku.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSPlay {
// Valeur représentant une case vide
private static final int EMPTY_VALUE = 0;
// Codes des touches numériques du pavé numérique
private static final int[] NUM_KEYS = {KeyEvent.VK_NUMPAD1, KeyEvent.VK_NUMPAD2, KeyEvent.VK_NUMPAD3, KeyEvent.VK_NUMPAD4, KeyEvent.VK_NUMPAD5,
KeyEvent.VK_NUMPAD6, KeyEvent.VK_NUMPAD7, KeyEvent.VK_NUMPAD8, KeyEvent.VK_NUMPAD9};
// Codes des touches numériques du clavier
private static final int[] KEY_NUMBERS = {KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_3, KeyEvent.VK_4, KeyEvent.VK_5,
KeyEvent.VK_6, KeyEvent.VK_7, KeyEvent.VK_8, KeyEvent.VK_9};
// Code de la touche de suppression
private static final int DELETE_KEY = KeyEvent.VK_BACK_SPACE;
private Container content;
private GSGrid ma_Grille;
private Button boutonValider = new Button("Valider");
private long startTime;
private long vraiTime;
private Window gameplay;
private GSPlayController gsPlayController;
/**
* Constructeur de la classe GSPlay.
* @param grille La grille de Sudoku.
* @param frame La fenêtre principale.
*/
public GSPlay(Window window, GSGrid grille) {
this.ma_Grille = grille;
this.gameplay = window;
this.gsPlayController = new GSPlayController(this);
}
/**
* Méthode pour afficher la fenêtre de jeu.
*/
public void showGame() {
Window.removeAllComponents(this.gameplay);
this.gameplay.setPageTitle("Jouer");
this.startTime = System.nanoTime();
content = this.gameplay.getContentPane();
BorderLayout gestionnaireGameplay = new BorderLayout();
this.gameplay.setLayout(gestionnaireGameplay);
this.gameplay.setSize(650, 730);
this.gameplay.setFocusable(true);
this.gameplay.requestFocusInWindow();
this.gameplay.addKeyListener(gsPlayController);
this.boutonValider.setEnabled(false);
this.vraiTime = System.nanoTime() - this.startTime;
boutonValider.addActionListener(gsPlayController);
this.gameplay.add(boutonValider, BorderLayout.SOUTH);
content.add(this.ma_Grille, BorderLayout.CENTER);
}
/**
* Méthode pour obtenir la valeur associée à une touche.
* @param e L'événement KeyEvent associé à la touche.
* @return La valeur correspondante à la touche ou -1 si aucune correspondance.
*/
public int getKeyValue(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == DELETE_KEY) {
return EMPTY_VALUE;
}
for (int i = 0; i < NUM_KEYS.length; i++) {
if (keyCode == NUM_KEYS[i] || keyCode == KEY_NUMBERS[i]) {
return i + 1;
}
}
return -1;
}
/**
* Méthode pour vérifier si le jeu est terminé.
* @return true si le jeu est terminé, sinon false.
*/
public Boolean isGameOver() {
return !this.ma_Grille.isComplete();
}
public Button getBoutonValider() {
return boutonValider;
}
public GSGrid getMaGrille() {
return ma_Grille;
}
/**
* Méthode pour obtenir le temps de démarrage du jeu.
* @return Le temps de démarrage du jeu.
*/
public long getStartTime() {
return this.startTime;
}
}

View File

@ -0,0 +1,69 @@
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
* Le contrôleur pour le jeu de la grille.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSPlayController implements KeyListener, ActionListener {
private GSPlay gsPlay;
/**
* Constructeur du contrôleur du jeu de la grille.
* @param gsPlay Le jeu de la grille associé à ce contrôleur.
*/
public GSPlayController(GSPlay gsPlay) {
this.gsPlay = gsPlay;
}
/**
* Gère les actions lorsqu'un événement se produit.
* @param e L'événement déclenché.
*/
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == gsPlay.getBoutonValider()) {
// Crée une fenêtre de dialogue pour afficher le temps écoulé depuis le début du jeu.
GSWin gestionVictoire = new GSWin(gsPlay.getStartTime());
gestionVictoire.showDialog();
}
}
/**
* Gère les événements lorsque la touche est enfoncée.
* @param e L'événement de la touche enfoncée.
*/
@Override
public void keyPressed(KeyEvent e) {
int keyValue = gsPlay.getKeyValue(e);
if (keyValue != -1) {
// Met à jour la valeur dans la case active de la grille avec la touche appuyée.
gsPlay.getMaGrille().setValuetoCase(gsPlay.getMaGrille().whoIsActive_X(), gsPlay.getMaGrille().whoIsActive_Y(), keyValue);
// Active le bouton de validation si le jeu est terminé.
if (gsPlay.isGameOver()) {
gsPlay.getBoutonValider().setEnabled(true);
}
}
}
/**
* Gère les événements lorsque la touche est relâchée.
* @param e L'événement de la touche relâchée.
*/
@Override
public void keyReleased(KeyEvent e) {
}
/**
* Gère les événements lorsque la touche est tapée.
* @param e L'événement de la touche tapée.
*/
@Override
public void keyTyped(KeyEvent e) {
// Non utilisé
}
}

56
src/GridSolver/GSSolver.java Executable file
View File

@ -0,0 +1,56 @@
import javax.swing.*;
import java.awt.*;
/**
* La classe GSSolver résout une grille de Sudoku et affiche le résultat dans une fenêtre.
* @version 1.O
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSSolver {
private GSGrid grid; // Grille de Sudoku à résoudre
private Window window; // Fenêtre dans laquelle afficher la résolution
private JLabel label = new JLabel("Resolution en cours..."); // Étiquette pour afficher le statut de la résolution
private long startTime; // Temps de début de la résolution
/**
* Constructeur de la classe GSSolver.
* @param grid La grille de Sudoku à résoudre.
* @param window La fenêtre dans laquelle afficher la résolution.
*/
public GSSolver(GSGrid grid, Window window) {
this.grid = grid;
this.window = window;
Window.removeAllComponents(this.window); // Efface tous les composants de la fenêtre
this.window.setPageTitle("Résolution automatique");
this.startSolving(); // Démarre la résolution
}
/**
* Démarre le processus de résolution de la grille de Sudoku.
*/
private void startSolving() {
startTime = System.nanoTime(); // Enregistre le temps de début de la résolution
BorderLayout layout = new BorderLayout(); // Gestionnaire de mise en page pour la fenêtre
window.setLayout(layout); // Définit le gestionnaire de mise en page pour la fenêtre
window.getContentPane().add(label, BorderLayout.SOUTH); // Ajoute l'étiquette au bas de la fenêtre
window.getContentPane().add(grid, BorderLayout.CENTER); // Ajoute la grille au centre de la fenêtre
grid.solve(); // Résout la grille de Sudoku
// Vérifie si le jeu est terminé
if (isGameOver()) {
double time = (double) (System.nanoTime() - startTime) / 1_000_000_000; // Calcule le temps écoulé en secondes
label.setText("Résolu en " + time + " secondes."); // Met à jour le texte de l'étiquette avec le temps écoulé
label.setForeground(Color.WHITE); // Définit la couleur du texte sur blanc
}
}
/**
* Vérifie si le jeu est terminé.
* @return true si le jeu est terminé, false sinon.
*/
private boolean isGameOver() {
return !grid.isComplete(); // Vérifie si la grille est complète
}
}

137
src/GridSolver/GSTest.java Executable file
View File

@ -0,0 +1,137 @@
/**
* La classe GSTest contient les méthodes pour tester la validité d'une grille de Sudoku.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSTest {
private GSGrid ma_Grille;
/**
* Constructeur de la classe GSTest.
* @param Grid La grille de Sudoku à tester.
*/
public GSTest(GSGrid Grid) {
this.ma_Grille = Grid;
}
/**
* Vérifie s'il y a des doublons dans la grille de Sudoku.
* @return true s'il y a des doublons, false sinon.
*/
public boolean test() {
// Vérification colonne
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 (this.ma_Grille.getCellValue(i, j) == this.ma_Grille.getCellValue(i_prime, j) && this.ma_Grille.getCellValue(i, j) != 0) {
return true;
}
}
}
}
// Vérification ligne
for (int j = 0; j < 9; j++) {
for (int i = 0; i < 9; i++) {
for (int j_prime = j + 1; j_prime < 9; j_prime++) {
if (this.ma_Grille.getCellValue(i, j) == this.ma_Grille.getCellValue(i, j_prime) && this.ma_Grille.getCellValue(i, j) != 0) {
return true;
}
}
}
}
// Vérification région
for (int i = 0; i < 9; i += 3) {
for (int j = 0; j < 9; j += 3) {
if (verificationRegion(i, j)) {
return true;
}
}
}
return false; // Aucun doublon trouvé dans la grille
}
/**
* Vérifie s'il y a des doublons dans une région spécifique de la grille.
* @param x L'indice x du coin supérieur gauche de la région.
* @param y L'indice y du coin supérieur gauche de la région.
* @return true s'il y a des doublons, false sinon.
*/
public boolean verificationRegion(int x, int y) {
final int REGION_SIZE = 3; // Taille de chaque région (3x3)
// Calcul des coordonnées du coin supérieur gauche de la région spécifiée
int regionX = (x / REGION_SIZE) * REGION_SIZE;
int regionY = (y / REGION_SIZE) * REGION_SIZE;
// Tableau pour suivre les valeurs déjà vues dans la région (de 1 à 9)
boolean[] seen = new boolean[10];
// Parcours de chaque cellule de la région spécifiée
for (int i = 0; i < REGION_SIZE; i++) {
for (int j = 0; j < REGION_SIZE; j++) {
// Obtention de la valeur de la cellule
int value = this.ma_Grille.getCellValue(regionX + i, regionY + j);
// Vérification si la valeur est différente de zéro (cellule remplie)
if (value != 0) {
// Si la valeur a déjà été vue dans la région, il y a un doublon
if (seen[value]) {
return true; // Valeur en double trouvée
}
seen[value] = true; // Marquage de la valeur comme vue
}
}
}
return false; // Aucune valeur en double trouvée dans la région
}
/**
* Vérifie s'il y a des doublons dans une ligne spécifique de la grille.
* @param x L'indice de la ligne à vérifier.
* @return true s'il y a des doublons, false sinon.
*/
public boolean verificationLigne(int x) {
int i = x;
for (int j = 0; j < 8; j++) { // Parcours des colonnes jusqu'à l'avant-dernière colonne
for (int j_prime = j + 1; j_prime < 9; j_prime++) { // Parcours des colonnes suivantes
// Comparaison des valeurs des cellules
if (ma_Grille.getCellValue(i, j) == ma_Grille.getCellValue(i, j_prime) && ma_Grille.getCellValue(i, j) != 0) {
return true; // Doublon trouvé, on peut retourner true directement
}
}
}
return false; // Aucun doublon trouvé dans la ligne
}
/**
* Vérifie s'il y a des doublons dans une colonne spécifique de la grille.
* @param y L'indice de la colonne à vérifier.
* @return true s'il y a des doublons, false sinon.
*/
public boolean verificationColonne(int y) {
int j = y;
for (int i = 0; i < 8; i++) { // Parcours des lignes jusqu'à l'avant-dernière ligne
for (int i_prime = i + 1; i_prime < 9; i_prime++) { // Parcours des lignes suivantes
// Comparaison des valeurs des cellules
if (ma_Grille.getCellValue(i, j) == ma_Grille.getCellValue(i_prime, j) && ma_Grille.getCellValue(i, j) != 0) {
return true; // Doublon trouvé, on peut retourner true directement
}
}
}
return false; // Aucun doublon trouvé dans la colonne
}
/**
* Vérifie si une cellule spécifique de la grille est valide.
* @param row L'indice de la ligne de la cellule.
* @param column L'indice de la colonne de la cellule.
* @return true si la cellule est valide, false sinon.
*/
public Boolean isValid(int row, int column){
return (!verificationLigne(row) && !verificationColonne(column) && !verificationRegion(row, column));
}
}

27
src/GridSolver/GSWin.java Executable file
View File

@ -0,0 +1,27 @@
/**
* La classe GSWin gère l'affichage d'une fenêtre de félicitations pour avoir résolu le Sudoku.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class GSWin implements DialogManager {
private long solvingTime; // Temps de résolution du Sudoku
/**
* Constructeur de la classe GSWin.
* @param solvingTime Le temps de résolution du Sudoku.
*/
public GSWin(long solvingTime) {
this.solvingTime = solvingTime;
}
/**
* Affiche la fenêtre de félicitations pour avoir résolu le Sudoku.
*/
@Override
public void showDialog() {
// Créer et afficher une nouvelle fenêtre de félicitations
CongratulationsDialog congratsWindow = new CongratulationsDialog(solvingTime);
}
}

View File

@ -0,0 +1,48 @@
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.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
class HomeButtonClickListener implements ActionListener {
private Window window;
private DialogManager rulesDialogManager;
private GSMenu menuJeu;
/**
* Constructs a ButtonClickListener with the specified window.
* @param window The window where the actions will be performed.
*/
public HomeButtonClickListener(Window window) {
this.window = window;
this.rulesDialogManager = new RulesDialogManager();
}
/**
* Performs an action based on the button clicked.
* @param e The ActionEvent representing the button click.
*/
@Override
public void actionPerformed(ActionEvent e) {
String buttonText = ((Button) e.getSource()).getText();
switch (buttonText) {
case "Jouer":
Window.removeAllComponents(this.window);
this.menuJeu = new GSMenu(this.window);
GSMenuController menuController = new GSMenuController(this.menuJeu, this.window);
break;
case "Règles":
rulesDialogManager.showDialog(); // Afficher les règles
break;
case "Quitter":
System.exit(0); // Quitter le programme
break;
default:
break;
}
}
}

View File

@ -0,0 +1,103 @@
import javax.swing.*;
import java.awt.*;
/**
* HomeView représente la vue de la page d'accueil de l'application Sudoku.
* Cette classe étend JPanel et affiche les éléments de la page d'accueil, y compris le titre, les boutons et les contrôles audio.
* Elle utilise également les classes Title, Button, et MusicButton.
*
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class HomeView extends JPanel {
// Constantes pour les chemins des icônes et des fichiers audio, ainsi que pour les dimensions et les couleurs
private final String AUDIO_ON = "img/iconeAudio.png";
private final String AUDIO_OFF = "img/iconeAudioMuted.png";
private final String MUSIC_FILE = "audio/musiqueDeFond.wav";
private final Dimension BUTTON_SIZE = new Dimension(300, 60);
private final Color BACKGROUND_COLOR = new Color(54, 91, 109);
private final Color TITLE_TEXT_COLOR = Color.WHITE;
private final Font TITLE_FONT = new Font("Copperplate", Font.BOLD, 75);
private final Font SUBTITLE_FONT = new Font("Copperplate", Font.PLAIN, 24);
private final Font BUTTON_FONT = new Font("Copperplate", Font.BOLD, 24);
private final String[] BUTTON_TEXTS = {"Jouer", "Règles", "Quitter"};
// Tableau de titres pour le titre principal et le sous-titre
private final Title[] labels = {
new Title("Sudoku Game", TITLE_FONT, TITLE_TEXT_COLOR),
new Title("Par Moncef & Marco", SUBTITLE_FONT, TITLE_TEXT_COLOR)
};
private MusicButton musicButton; // Bouton pour contrôler la musique
private final Window window; // Fenêtre parente
private JPanel titlePanel; // Panneau pour le titre
private JPanel buttonPanel; // Panneau pour les boutons
private JLabel imageLabel; // Étiquette pour l'image
/**
* Constructeur de la classe HomeView.
* Initialise la fenêtre parente et crée les composants de la page d'accueil.
* @param window La fenêtre parente.
*/
public HomeView(Window window) {
this.window = window;
createComponents();
addComponentsToWindow();
}
/**
* Crée les composants de la page d'accueil, y compris les panneaux de titre et de boutons.
*/
private void createComponents() {
titlePanel = new JPanel();
buttonPanel = new JPanel();
ImageIcon iconeSudoku = new ImageIcon("img/sudoku.png");
imageLabel = new JLabel(iconeSudoku);
// Configuration du panneau de titre
GridLayout titleLayout = new GridLayout(2, 1);
titlePanel.setLayout(titleLayout);
titlePanel.setBackground(BACKGROUND_COLOR);
// Utilisation de la classe Title pour le titre et le sous-titre
for (Title label : labels) {
titlePanel.add(label);
}
// Configuration du panneau de boutons
GridLayout buttonLayout = new GridLayout(BUTTON_TEXTS.length, 1, 0, 10);
buttonPanel.setLayout(buttonLayout);
buttonPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
buttonPanel.setBackground(BACKGROUND_COLOR);
HomeButtonClickListener listenerButton = new HomeButtonClickListener(window);
for (String text : BUTTON_TEXTS) {
Button button = new Button(text, BUTTON_SIZE, BUTTON_FONT, BACKGROUND_COLOR);
button.addActionListener(listenerButton);
buttonPanel.add(button);
}
musicButton = new MusicButton(AUDIO_ON, AUDIO_OFF, MUSIC_FILE); // Bouton pour contrôler la musique
}
/**
* Ajoute les composants créés à la fenêtre parente.
*/
public void addComponentsToWindow() {
BorderLayout layout = new BorderLayout();
window.getContentPane().setLayout(layout);
window.add(titlePanel, BorderLayout.NORTH);
window.add(buttonPanel, BorderLayout.WEST);
window.add(imageLabel, BorderLayout.EAST);
window.setPageTitle("Menu principal"); // Définit le titre de la page dans la fenêtre
FlowLayout controlPanelLayout = new FlowLayout(FlowLayout.RIGHT);
JPanel controlPanel = new JPanel(controlPanelLayout); // Panneau pour les contrôles audio
controlPanel.setBackground(BACKGROUND_COLOR);
controlPanel.add(musicButton); // Ajoute le bouton de contrôle audio
window.add(controlPanel, BorderLayout.SOUTH); // Ajoute le panneau de contrôles à la fenêtre
window.pack(); // Ajuste la taille de la fenêtre pour s'adapter à son contenu
window.setVisible(true); // Rend la fenêtre visible
}
}

6
src/GridSolver/Main.java Normal file
View File

@ -0,0 +1,6 @@
public class Main{
public static void main(String[] args) {
Window fenetre = new Window(); // Création d'une fenêtre
HomeView menu = new HomeView(fenetre); // Création du menu sur la fenêtre
}
}

View File

@ -0,0 +1,47 @@
import javax.swing.*;
/**
* It provides a button that toggles between playing and stopping music when clicked.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class MusicButton extends JButton {
private static MusicPlayer currentMusicPlayer;
private ImageIcon iconOn;
private ImageIcon iconOff;
private MusicPlayer musicPlayer;
/**
* Constructs a MusicButton.
* @param onIconPath The file path for the icon when music is on.
* @param offIconPath The file path for the icon when music is off.
* @param musicFilePath The file path for the music file to be played.
*/
public MusicButton(String onIconPath, String offIconPath, String musicFilePath) {
this.iconOn = new ImageIcon(onIconPath);
this.iconOff = new ImageIcon(offIconPath);
setIcon(this.iconOff);
// Vérifie s'il y a déjà une musique en cours de lecture et l'arrête si nécessaire
if (currentMusicPlayer != null && currentMusicPlayer.isPlaying()) {
currentMusicPlayer.stop();
currentMusicPlayer = null;
}
this.musicPlayer = new MusicPlayer(musicFilePath);
addActionListener(e -> {
if (currentMusicPlayer != null && currentMusicPlayer.isPlaying()) {
currentMusicPlayer.stop();
currentMusicPlayer = null;
setIcon(this.iconOff);
} else {
this.musicPlayer.play();
setIcon(this.iconOn);
currentMusicPlayer = this.musicPlayer;
}
});
}
}

View File

@ -0,0 +1,57 @@
import java.io.File;
import javax.sound.sampled.*;
/**
* Class containign a simple music player that allows playing and stopping music.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class MusicPlayer {
private Clip clip;
private boolean isPlaying;
/**
* Constructs a MusicPlayer with the specified file path.
* @param filePath The path to the music file to be played.
*/
public MusicPlayer(String filePath) {
try {
File file = new File(filePath);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
this.clip = AudioSystem.getClip();
this.clip.open(audioInputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Starts playing the music.
*/
public void play() {
if (this.clip != null && !this.isPlaying) {
this.clip.start();
this.isPlaying = true;
}
}
/**
* Stops the music.
*/
public void stop() {
if (this.clip != null && this.isPlaying) {
this.clip.stop();
this.isPlaying = false;
}
}
/**
* Checks if the music is currently playing.
* @return true if the music is playing, false otherwise.
*/
public boolean isPlaying() {
return this.isPlaying;
}
}

View File

@ -0,0 +1,20 @@
import javax.swing.JOptionPane;
/**
* RulesDialogManager gère l'affichage de la boîte de dialogue des règles.
* Cette classe implémente DialogManager pour définir la méthode showDialog.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class RulesDialogManager implements DialogManager {
/**
* Affiche la boîte de dialogue des règles du Sudoku.
*/
@Override
public void showDialog() {
RulesSudoku rulesPanel = new RulesSudoku(); // Création du panneau contenant les règles
JOptionPane.showMessageDialog(null, rulesPanel, "Règles du Sudoku", JOptionPane.PLAIN_MESSAGE); // Affichage de la boîte de dialogue
}
}

View File

@ -0,0 +1,49 @@
import javax.swing.*;
import java.awt.*;
/**
* RulesSudoku représente le panneau affichant les règles du Sudoku.
* Cette classe étend JPanel et définit le contenu des règles.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class RulesSudoku extends JPanel {
private Dimension FRAME_SIZE = new Dimension(400, 500); // Taille de la fenêtre des règles
private Color BACKGROUND_COLOR = new Color(54, 91, 109); // Couleur d'arrière-plan du panneau
/**
* Constructeur par défaut de RulesSudoku.
* Initialise le contenu des règles et configure l'apparence du panneau.
*/
public RulesSudoku() {
BorderLayout gestionnaireBorderLayout = new BorderLayout();
this.setLayout(gestionnaireBorderLayout);
this.setBackground(this.BACKGROUND_COLOR); // Couleur d'arrière-plan du panneau
JLabel titleLabel = new JLabel("Règles du Sudoku");
titleLabel.setFont(new Font("Copperplate", Font.BOLD, 40)); // Police du titre
titleLabel.setForeground(Color.WHITE); // Couleur du titre
JTextArea rulesTextArea = new JTextArea();
rulesTextArea.setText("Les règles du Sudoku :\n\n" +
"1. Le but du jeu est de remplir la grille avec une série de chiffres de 1 à 9 de telle sorte que chaque ligne, chaque colonne et chaque région de 3x3 contienne tous les chiffres de 1 à 9 sans répétition.\n\n" +
"2. Certains chiffres sont déjà placés dans la grille au départ et ne peuvent pas être modifiés.\n\n" +
"3. Utilisez la logique et le raisonnement pour remplir la grille avec les chiffres manquants.\n\n" +
"4. Le jeu est terminé lorsqu'il n'y a plus de cases vides et que toutes les règles sont respectées.");
rulesTextArea.setEditable(false);
rulesTextArea.setLineWrap(true);
rulesTextArea.setWrapStyleWord(true);
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.setBackground(this.BACKGROUND_COLOR); // Couleur d'arrière-plan du texte des règles
JScrollPane scrollPane = new JScrollPane(rulesTextArea);
this.add(titleLabel, BorderLayout.NORTH);
this.add(scrollPane, BorderLayout.CENTER);
this.setPreferredSize(this.FRAME_SIZE); // Taille de la fenêtre des règles
}
}

26
src/GridSolver/Title.java Normal file
View File

@ -0,0 +1,26 @@
import javax.swing.*;
import java.awt.*;
/**
* Title est une étiquette Swing personnalisée utilisée pour afficher un titre centré avec une police et une couleur spécifiées.
* Cette classe étend JLabel.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class Title extends JLabel {
/**
* Constructeur de Title.
* Crée une étiquette avec le texte, la police et la couleur spécifiés, et la centre horizontalement.
* @param text Le texte à afficher.
* @param font La police à utiliser pour le texte.
* @param color La couleur du texte.
*/
public Title(String text, Font font, Color color) {
super(text, SwingConstants.CENTER); // Centre le texte horizontalement
setFont(font); // Définit la police du texte
setForeground(color); // Définit la couleur du texte
}
}

View File

@ -0,0 +1,71 @@
import javax.swing.*;
import java.awt.*;
/**
* Window est une classe représentant la fenêtre principale de l'application Sudoku.
* Cette classe étend JFrame et gère l'affichage des différentes pages de l'application.
* @version 1.0
* @author Moncef STITI
* @author Marco ORFAO
*/
public class Window extends JFrame {
/**
* La taille minimale de la fenêtre.
*/
private static final Dimension MIN_WINDOW_SIZE = new Dimension(850, 700);
/**
* Le titre du programme.
*/
private static final String PROGRAM_TITLE = "Sudoku";
/**
* La couleur d'arrière plan par défaut de la fenêtre
*/
private static final Color BACKGROUND_COLOR = new Color(54, 91, 109);
/**
* Le titre de la page actuelle.
*/
private String PAGE_TITLE = "";
/**
* Constructeur de la classe Window.
* Initialise la fenêtre avec le titre du programme, la taille minimale et la couleur de fond.
*/
public Window() {
super(PROGRAM_TITLE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setMinimumSize(MIN_WINDOW_SIZE);
this.setLocationRelativeTo(null);
getContentPane().setBackground(BACKGROUND_COLOR);
}
/**
* Obtient le titre de la page actuelle.
* @return Le titre de la page actuelle.
*/
public String getPageTitle() {
return this.PAGE_TITLE;
}
/**
* Définit le titre de la page actuelle.
* Met à jour le titre de la fenêtre pour inclure le titre de la page et le titre du programme.
* @param title Le titre de la page actuelle.
*/
public void setPageTitle(String title) {
this.PAGE_TITLE = title;
this.setTitle(this.PAGE_TITLE + " - " + Window.PROGRAM_TITLE);
}
/**
* Supprime tous les composants de la fenêtre.
* Utilisé pour effacer le contenu de la fenêtre.
* @param window La fenêtre à nettoyer.
*/
public static void removeAllComponents(Window window) {
window.getContentPane().removeAll(); // Supprime tous les composants de la fenêtre
window.revalidate(); // Revalide la disposition des composants
window.repaint(); // Redessine la fenêtre
}
}