diff --git a/AutomatiqueActionListener.class b/AutomatiqueActionListener.class new file mode 100644 index 0000000..c66d6db Binary files /dev/null and b/AutomatiqueActionListener.class differ diff --git a/AutomatiqueActionListener.java b/AutomatiqueActionListener.java new file mode 100644 index 0000000..6164e25 --- /dev/null +++ b/AutomatiqueActionListener.java @@ -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."); + } + } +} diff --git a/CaseMouseListener.class b/CaseMouseListener.class new file mode 100644 index 0000000..fd52052 Binary files /dev/null and b/CaseMouseListener.class differ diff --git a/CaseMouseListener.java b/CaseMouseListener.java new file mode 100644 index 0000000..e9bb759 --- /dev/null +++ b/CaseMouseListener.java @@ -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."); + } + } + } +} diff --git a/FenetreChoix.class b/FenetreChoix.class new file mode 100644 index 0000000..dacb400 Binary files /dev/null and b/FenetreChoix.class differ diff --git a/FenetreChoix.java b/FenetreChoix.java new file mode 100644 index 0000000..d34c45c --- /dev/null +++ b/FenetreChoix.java @@ -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)); + } +} diff --git a/FenetrePrincipale.class b/FenetrePrincipale.class new file mode 100644 index 0000000..36ba0cc Binary files /dev/null and b/FenetrePrincipale.class differ diff --git a/FenetrePrincipale.java b/FenetrePrincipale.java new file mode 100644 index 0000000..3a3f703 --- /dev/null +++ b/FenetrePrincipale.java @@ -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."); + } +} diff --git a/GrillePainter.class b/GrillePainter.class new file mode 100644 index 0000000..f389392 Binary files /dev/null and b/GrillePainter.class differ diff --git a/GrillePainter.java b/GrillePainter.java new file mode 100644 index 0000000..9742d80 --- /dev/null +++ b/GrillePainter.java @@ -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); + } + } + } + } +} diff --git a/Main.java b/Main.java index 2f71e29..1699f78 100644 --- a/Main.java +++ b/Main.java @@ -1,92 +1,9 @@ -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; public class Main { public static void main(String[] args) { System.out.println("Le programme Main a démarré."); - // Création de la fenêtre de dialogue pour choisir le mode de résolution - 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); // 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."); + FenetreChoix fenetreChoix = new FenetreChoix(); + fenetreChoix.afficher(); } } diff --git a/ManuelActionListener.class b/ManuelActionListener.class new file mode 100644 index 0000000..92d4880 Binary files /dev/null and b/ManuelActionListener.class differ diff --git a/ManuelActionListener.java b/ManuelActionListener.java new file mode 100644 index 0000000..2d21105 --- /dev/null +++ b/ManuelActionListener.java @@ -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); + } +} diff --git a/ReinitialiserActionListener.class b/ReinitialiserActionListener.class new file mode 100644 index 0000000..8378a28 Binary files /dev/null and b/ReinitialiserActionListener.class differ diff --git a/ReinitialiserActionListener.java b/ReinitialiserActionListener.java new file mode 100644 index 0000000..75818ab --- /dev/null +++ b/ReinitialiserActionListener.java @@ -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); + } +} diff --git a/SaisieGrille.java b/SaisieGrille.java index aa1947b..79b889f 100644 --- a/SaisieGrille.java +++ b/SaisieGrille.java @@ -7,13 +7,12 @@ public class SaisieGrille extends JPanel { private static final int TAILLE_REGION = 3; private static final int TAILLE_CELLULE = 50; private int[][] grille; - private int[][] grilleInitiale; // Pour stocker la grille initiale + private int[][] grilleInitiale; private int ligneSelectionnee = -1; private int colonneSelectionnee = -1; public SaisieGrille(int[][] grille) { this.grille = grille; - // Copie de la grille initiale this.grilleInitiale = new int[grille.length][grille[0].length]; for (int i = 0; i < grille.length; i++) { 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)); - setFocusable(true); // Permet au JPanel de recevoir les événements de souris + setFocusable(true); - addMouseListener(new MouseAdapter() { - @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."); - } - } - } - }); + addMouseListener(new CaseMouseListener(this)); } public int[][] getGrilleInitiale() { return grilleInitiale; } - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); + public int getTailleGrille() { + return TAILLE_GRILLE; + } - // Dessiner les contours de la grille (en gras) - Graphics2D g2d = (Graphics2D) g; - Stroke ancienStroke = g2d.getStroke(); // Sauvegarder le style de ligne précédent - g2d.setStroke(new BasicStroke(4)); // Épaisseur de ligne de 4 pixels + public int getTailleRegion() { + return TAILLE_REGION; + } - for (int i = 0; i <= TAILLE_GRILLE * TAILLE_REGION; i++) { - if (i % TAILLE_REGION == 0) { - 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 int getTailleCellule() { + return 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 - g2d.setStroke(ancienStroke); + // Vérifier la colonne + for (int i = 0; i < grille.length; i++) { + if (grille[i][colonne] == chiffre && i != ligne) { + return false; + } + } - // Dessiner les cellules de la grille - for (int i = 0; i < TAILLE_GRILLE * TAILLE_REGION; i++) { - for (int j = 0; j < TAILLE_GRILLE * TAILLE_REGION; j++) { - g.setColor(Color.BLACK); - g.drawRect(j * TAILLE_CELLULE, i * TAILLE_CELLULE, TAILLE_CELLULE, TAILLE_CELLULE); - int valeur = grille[i][j]; - if (valeur != 0) { - g.drawString(String.valueOf(valeur), j * TAILLE_CELLULE + TAILLE_CELLULE / 2, i * TAILLE_CELLULE + TAILLE_CELLULE / 2); + // Vérifier la région + int regionX = colonne / TAILLE_REGION; + int regionY = ligne / TAILLE_REGION; + for (int i = regionY * TAILLE_REGION; i < (regionY + 1) * TAILLE_REGION; i++) { + for (int j = regionX * TAILLE_REGION; j < (regionX + 1) * TAILLE_REGION; j++) { + if (grille[i][j] == chiffre && (i != ligne || j != colonne)) { + return false; } } } + + return true; } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + GrillePainter.dessinerGrille(g, this); + } + + }