This commit is contained in:
raban 2024-05-01 21:55:32 +02:00
commit 022ac4299c
16 changed files with 306 additions and 133 deletions

Binary file not shown.

View File

@ -0,0 +1,32 @@
import javax.swing.*;
import java.awt.event.*;
public class AutomatiqueActionListener implements ActionListener {
private JFrame choixFrame;
public AutomatiqueActionListener(JFrame choixFrame) {
this.choixFrame = choixFrame;
}
@Override
public void actionPerformed(ActionEvent e) {
choixFrame.dispose();
int[][] grille = GenerateurSudoku.genererGrille();
System.out.println("Grille Sudoku générée avec succès.");
long startTime = System.nanoTime();
if (Resolveur.resoudreSudoku(grille)) {
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1000000;
FenetrePrincipale fenetrePrincipale = new FenetrePrincipale();
fenetrePrincipale.afficher(true, grille);
JOptionPane.showMessageDialog(null, "Grille résolue avec succès en " + duration + " millisecondes !");
} else {
JOptionPane.showMessageDialog(null, "Impossible de résoudre la grille.");
}
}
}

BIN
CaseMouseListener.class Normal file

Binary file not shown.

78
CaseMouseListener.java Normal file
View File

@ -0,0 +1,78 @@
import javax.swing.*;
import java.awt.event.*;
public class CaseMouseListener extends MouseAdapter {
private SaisieGrille panel;
public CaseMouseListener(SaisieGrille panel) {
this.panel = panel;
}
@Override
public void mouseClicked(MouseEvent e) {
int x = e.getX() / panel.getTailleCellule();
int y = e.getY() / panel.getTailleCellule();
if (x >= 0 && x < panel.getTailleGrille() * panel.getTailleRegion() && y >= 0 && y < panel.getTailleGrille() * panel.getTailleRegion()) {
panel.setLigneSelectionnee(y);
panel.setColonneSelectionnee(x);
System.out.println("Case sélectionnée : (" + panel.getLigneSelectionnee() + ", " + panel.getColonneSelectionnee() + ")");
if (panel.getGrilleInitiale()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] == 0) {
String[] options = {"Incertain", "Valider"};
JTextField textField = new JTextField();
Object[] message = {
"Entrez la valeur pour la cellule sélectionnée :",
textField
};
int option = JOptionPane.showOptionDialog(null, message, "Entrez un nombre", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
if (option == 1) {
String valeurStr = textField.getText();
try {
int valeur = Integer.parseInt(valeurStr);
if (panel.validerChiffre(panel.getLigneSelectionnee(), panel.getColonneSelectionnee(), valeur)) {
panel.getGrille()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] = valeur;
panel.repaint();
} else {
JOptionPane.showMessageDialog(null, "Ce chiffre ne respecte pas les contraintes du Sudoku. Veuillez choisir un autre chiffre.");
}
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Saisie invalide. Veuillez entrer un nombre.");
}
} else if (option == 0) {
// Le joueur a choisi "Incertain"
JTextField[] incertainFields = new JTextField[4];
for (int i = 0; i < 4; i++) {
incertainFields[i] = new JTextField();
}
Object[] incertainMessage = {
"Entrez les valeurs incertaines pour la cellule sélectionnée :",
"Valeur 1 (obligatoire):", incertainFields[0],
"Valeur 2 (obligatoire):", incertainFields[1],
"Valeur 3 (optionnelle):", incertainFields[2],
"Valeur 4 (optionnelle):", incertainFields[3]
};
int incertainOption = JOptionPane.showOptionDialog(null, incertainMessage, "Entrez les valeurs incertaines", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
if (incertainOption == JOptionPane.OK_OPTION) {
// Vérifier que les valeurs obligatoires sont remplies
if (!incertainFields[0].getText().isEmpty() && !incertainFields[1].getText().isEmpty()) {
// Récupérer les valeurs incertaines saisies par le joueur
int valeursIncertaines = 0;
for (int i = 0; i < 4; i++) {
if (!incertainFields[i].getText().isEmpty()) {
int valeur = Integer.parseInt(incertainFields[i].getText());
valeursIncertaines |= (valeur << (i * 4));
}
}
// Mettre à jour la grille avec les valeurs incertaines
panel.getGrille()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] = valeursIncertaines;
panel.repaint();
} else {
JOptionPane.showMessageDialog(null, "Les deux premières valeurs incertaines sont obligatoires.");
}
}
}
} else {
JOptionPane.showMessageDialog(null, "Vous ne pouvez pas modifier la valeur par défaut.");
}
}
}
}

BIN
FenetreChoix.class Normal file

Binary file not shown.

31
FenetreChoix.java Normal file
View File

@ -0,0 +1,31 @@
import javax.swing.*;
import java.awt.*;
public class FenetreChoix {
public void afficher() {
JFrame choixFrame = new JFrame("Choix de résolution du Sudoku");
choixFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
choixFrame.setSize(400, 200);
choixFrame.setLayout(new BorderLayout());
choixFrame.setLocationRelativeTo(null);
JLabel label = new JLabel("Choisissez le mode de résolution du Sudoku :");
label.setHorizontalAlignment(JLabel.CENTER);
JButton automatiqueButton = new JButton("Automatique");
JButton manuelButton = new JButton("Manuel");
JPanel boutonsPanel = new JPanel();
boutonsPanel.setLayout(new FlowLayout());
boutonsPanel.add(automatiqueButton);
boutonsPanel.add(manuelButton);
choixFrame.add(label, BorderLayout.NORTH);
choixFrame.add(boutonsPanel, BorderLayout.CENTER);
choixFrame.setVisible(true);
automatiqueButton.addActionListener(new AutomatiqueActionListener(choixFrame));
manuelButton.addActionListener(new ManuelActionListener(choixFrame));
}
}

BIN
FenetrePrincipale.class Normal file

Binary file not shown.

25
FenetrePrincipale.java Normal file
View File

@ -0,0 +1,25 @@
import javax.swing.*;
import java.awt.*;
public class FenetrePrincipale {
public void afficher(boolean modeAutomatique, int[][] grille) {
JFrame frame = new JFrame("Sudoku");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SaisieGrille saisieGrille = new SaisieGrille(grille);
if (!modeAutomatique) {
JButton reinitialiserButton = new JButton("Réinitialiser");
reinitialiserButton.addActionListener(new ReinitialiserActionListener(grille, saisieGrille));
frame.add(reinitialiserButton, BorderLayout.SOUTH);
}
frame.add(saisieGrille, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
System.out.println("La fenêtre Sudoku a été affichée.");
}
}

BIN
GrillePainter.class Normal file

Binary file not shown.

29
GrillePainter.java Normal file
View File

@ -0,0 +1,29 @@
import java.awt.*;
public class GrillePainter {
public static void dessinerGrille(Graphics g, SaisieGrille panel) {
Graphics2D g2d = (Graphics2D) g;
Stroke ancienStroke = g2d.getStroke();
g2d.setStroke(new BasicStroke(4));
for (int i = 0; i <= panel.getTailleGrille() * panel.getTailleRegion(); i++) {
if (i % panel.getTailleRegion() == 0) {
g2d.drawLine(0, i * panel.getTailleCellule(), panel.getTailleGrille() * panel.getTailleRegion() * panel.getTailleCellule(), i * panel.getTailleCellule());
g2d.drawLine(i * panel.getTailleCellule(), 0, i * panel.getTailleCellule(), panel.getTailleGrille() * panel.getTailleRegion() * panel.getTailleCellule());
}
}
g2d.setStroke(ancienStroke);
for (int i = 0; i < panel.getTailleGrille() * panel.getTailleRegion(); i++) {
for (int j = 0; j < panel.getTailleGrille() * panel.getTailleRegion(); j++) {
g.setColor(Color.BLACK);
g.drawRect(j * panel.getTailleCellule(), i * panel.getTailleCellule(), panel.getTailleCellule(), panel.getTailleCellule());
int valeur = panel.getGrille()[i][j];
if (valeur != 0) {
g.drawString(String.valueOf(valeur), j * panel.getTailleCellule() + panel.getTailleCellule() / 2, i * panel.getTailleCellule() + panel.getTailleCellule() / 2);
}
}
}
}
}

View File

@ -1,92 +1,9 @@
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main { public class Main {
public static void main(String[] args) { public static void main(String[] args) {
System.out.println("Le programme Main a démarré."); System.out.println("Le programme Main a démarré.");
// Création de la fenêtre de dialogue pour choisir le mode de résolution FenetreChoix fenetreChoix = new FenetreChoix();
JFrame choixFrame = new JFrame("Choix de résolution du Sudoku"); fenetreChoix.afficher();
choixFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
choixFrame.setSize(400, 200);
choixFrame.setLayout(new BorderLayout());
choixFrame.setLocationRelativeTo(null); // Centrer la fenêtre sur l'écran
JLabel label = new JLabel("Choisissez le mode de résolution du Sudoku :");
label.setHorizontalAlignment(JLabel.CENTER);
JButton automatiqueButton = new JButton("Automatique");
JButton manuelButton = new JButton("Manuel");
JPanel boutonsPanel = new JPanel();
boutonsPanel.setLayout(new FlowLayout());
boutonsPanel.add(automatiqueButton);
boutonsPanel.add(manuelButton);
choixFrame.add(label, BorderLayout.NORTH);
choixFrame.add(boutonsPanel, BorderLayout.CENTER);
choixFrame.setVisible(true);
// Gestion du bouton "Automatique"
automatiqueButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
choixFrame.dispose(); // Fermer la fenêtre de choix
int[][] grille = GenerateurSudoku.genererGrille(); // Obtenir la grille par défaut
System.out.println("Grille Sudoku générée avec succès.");
// Résoudre automatiquement le Sudoku
if (Resolveur.resoudreSudoku(grille)) {
// Créer et afficher la fenêtre principale avec la grille résolue
afficherFenetre(grille, true);
} else {
JOptionPane.showMessageDialog(null, "Impossible de résoudre la grille.");
}
}
});
// Gestion du bouton "Manuel"
manuelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
choixFrame.dispose(); // Fermer la fenêtre de choix
int[][] grille = GenerateurSudoku.genererGrille(); // Obtenir la grille par défaut
System.out.println("Grille Sudoku générée avec succès.");
// Créer et afficher la fenêtre principale pour la saisie manuelle
afficherFenetre(grille, false);
}
});
}
// Fonction pour créer et afficher la fenêtre principale avec la grille spécifiée
private static void afficherFenetre(int[][] grille, boolean modeAutomatique) {
JFrame frame = new JFrame("Sudoku");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SaisieGrille saisieGrille = new SaisieGrille(grille); // Utilisation de la classe SaisieGrille pour permettre la saisie des valeurs
if (!modeAutomatique) { // Ajouter le bouton "Réinitialiser" seulement en mode manuel
JButton reinitialiserButton = new JButton("Réinitialiser");
reinitialiserButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Reinitialiser reinitialiser = new Reinitialiser(grille, saisieGrille);
reinitialiser.actionPerformed(e);
}
});
frame.add(reinitialiserButton, BorderLayout.SOUTH); // Ajouter le bouton "Réinitialiser"
}
frame.add(saisieGrille, BorderLayout.CENTER); // Ajouter la grille à la fenêtre
frame.pack();
frame.setLocationRelativeTo(null); // Centrer la fenêtre sur l'écran
frame.setVisible(true);
System.out.println("La fenêtre Sudoku a été affichée.");
} }
} }

BIN
ManuelActionListener.class Normal file

Binary file not shown.

23
ManuelActionListener.java Normal file
View File

@ -0,0 +1,23 @@
import javax.swing.*;
import java.awt.event.*;
public class ManuelActionListener implements ActionListener {
private JFrame choixFrame;
public ManuelActionListener(JFrame choixFrame) {
this.choixFrame = choixFrame;
}
@Override
public void actionPerformed(ActionEvent e) {
choixFrame.dispose();
int[][] grille = GenerateurSudoku.genererGrille();
System.out.println("Grille Sudoku générée avec succès.");
FenetrePrincipale fenetrePrincipale = new FenetrePrincipale();
fenetrePrincipale.afficher(false, grille);
}
}

Binary file not shown.

View File

@ -0,0 +1,20 @@
import javax.swing.*;
import java.awt.event.*;
public class ReinitialiserActionListener implements ActionListener {
private int[][] grille;
private SaisieGrille saisieGrille;
public ReinitialiserActionListener(int[][] grille, SaisieGrille saisieGrille) {
this.grille = grille;
this.saisieGrille = saisieGrille;
}
@Override
public void actionPerformed(ActionEvent e) {
Reinitialiser reinitialiser = new Reinitialiser(grille, saisieGrille);
reinitialiser.actionPerformed(e);
}
}

View File

@ -7,13 +7,12 @@ public class SaisieGrille extends JPanel {
private static final int TAILLE_REGION = 3; private static final int TAILLE_REGION = 3;
private static final int TAILLE_CELLULE = 50; private static final int TAILLE_CELLULE = 50;
private int[][] grille; private int[][] grille;
private int[][] grilleInitiale; // Pour stocker la grille initiale private int[][] grilleInitiale;
private int ligneSelectionnee = -1; private int ligneSelectionnee = -1;
private int colonneSelectionnee = -1; private int colonneSelectionnee = -1;
public SaisieGrille(int[][] grille) { public SaisieGrille(int[][] grille) {
this.grille = grille; this.grille = grille;
// Copie de la grille initiale
this.grilleInitiale = new int[grille.length][grille[0].length]; this.grilleInitiale = new int[grille.length][grille[0].length];
for (int i = 0; i < grille.length; i++) { for (int i = 0; i < grille.length; i++) {
for (int j = 0; j < grille[i].length; j++) { for (int j = 0; j < grille[i].length; j++) {
@ -21,67 +20,86 @@ public class SaisieGrille extends JPanel {
} }
} }
setPreferredSize(new Dimension(TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE)); setPreferredSize(new Dimension(TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE));
setFocusable(true); // Permet au JPanel de recevoir les événements de souris setFocusable(true);
addMouseListener(new MouseAdapter() { addMouseListener(new CaseMouseListener(this));
@Override
public void mouseClicked(MouseEvent e) {
int x = e.getX() / TAILLE_CELLULE;
int y = e.getY() / TAILLE_CELLULE;
if (x >= 0 && x < TAILLE_GRILLE * TAILLE_REGION && y >= 0 && y < TAILLE_GRILLE * TAILLE_REGION) {
ligneSelectionnee = y;
colonneSelectionnee = x;
System.out.println("Case sélectionnée : (" + ligneSelectionnee + ", " + colonneSelectionnee + ")");
if (grilleInitiale[ligneSelectionnee][colonneSelectionnee] == 0) { // Ne permet la modification que pour les cellules vides
String valeurStr = JOptionPane.showInputDialog(null, "Entrez la valeur pour la cellule sélectionnée :");
try {
int valeur = Integer.parseInt(valeurStr);
grille[ligneSelectionnee][colonneSelectionnee] = valeur;
repaint();
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Saisie invalide. Veuillez entrer un nombre.");
}
} else {
JOptionPane.showMessageDialog(null, "Vous ne pouvez pas modifier la valeur par défaut.");
}
}
}
});
} }
public int[][] getGrilleInitiale() { public int[][] getGrilleInitiale() {
return grilleInitiale; return grilleInitiale;
} }
@Override public int getTailleGrille() {
protected void paintComponent(Graphics g) { return TAILLE_GRILLE;
super.paintComponent(g); }
// Dessiner les contours de la grille (en gras) public int getTailleRegion() {
Graphics2D g2d = (Graphics2D) g; return TAILLE_REGION;
Stroke ancienStroke = g2d.getStroke(); // Sauvegarder le style de ligne précédent }
g2d.setStroke(new BasicStroke(4)); // Épaisseur de ligne de 4 pixels
for (int i = 0; i <= TAILLE_GRILLE * TAILLE_REGION; i++) { public int getTailleCellule() {
if (i % TAILLE_REGION == 0) { return TAILLE_CELLULE;
g2d.drawLine(0, i * TAILLE_CELLULE, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, i * TAILLE_CELLULE); }
g2d.drawLine(i * TAILLE_CELLULE, 0, i * TAILLE_CELLULE, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE);
public void setLigneSelectionnee(int ligneSelectionnee) {
this.ligneSelectionnee = ligneSelectionnee;
}
public void setColonneSelectionnee(int colonneSelectionnee) {
this.colonneSelectionnee = colonneSelectionnee;
}
public int getLigneSelectionnee() {
return ligneSelectionnee;
}
public int getColonneSelectionnee() {
return colonneSelectionnee;
}
public int[][] getGrille() {
return grille;
}
public boolean validerChiffre(int ligne, int colonne, int chiffre) {
// Vérifier si le chiffre est entre 1 et 9
if (chiffre < 1 || chiffre > 9) {
return false;
}
// Vérifier la ligne
for (int j = 0; j < grille.length; j++) {
if (grille[ligne][j] == chiffre && j != colonne) {
return false;
} }
} }
// Rétablir le style de ligne précédent // Vérifier la colonne
g2d.setStroke(ancienStroke); for (int i = 0; i < grille.length; i++) {
if (grille[i][colonne] == chiffre && i != ligne) {
return false;
}
}
// Dessiner les cellules de la grille // Vérifier la région
for (int i = 0; i < TAILLE_GRILLE * TAILLE_REGION; i++) { int regionX = colonne / TAILLE_REGION;
for (int j = 0; j < TAILLE_GRILLE * TAILLE_REGION; j++) { int regionY = ligne / TAILLE_REGION;
g.setColor(Color.BLACK); for (int i = regionY * TAILLE_REGION; i < (regionY + 1) * TAILLE_REGION; i++) {
g.drawRect(j * TAILLE_CELLULE, i * TAILLE_CELLULE, TAILLE_CELLULE, TAILLE_CELLULE); for (int j = regionX * TAILLE_REGION; j < (regionX + 1) * TAILLE_REGION; j++) {
int valeur = grille[i][j]; if (grille[i][j] == chiffre && (i != ligne || j != colonne)) {
if (valeur != 0) { return false;
g.drawString(String.valueOf(valeur), j * TAILLE_CELLULE + TAILLE_CELLULE / 2, i * TAILLE_CELLULE + TAILLE_CELLULE / 2);
} }
} }
} }
return true;
} }
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
GrillePainter.dessinerGrille(g, this);
}
} }