2024-04-02 12:35:30 +02:00
|
|
|
import javax.swing.*;
|
|
|
|
import java.awt.*;
|
2024-04-18 19:29:38 +02:00
|
|
|
import java.awt.event.ActionEvent;
|
|
|
|
import java.awt.event.ActionListener;
|
2024-05-04 14:25:52 +02:00
|
|
|
import java.awt.event.FocusEvent;
|
|
|
|
import java.awt.event.FocusAdapter;
|
2024-04-02 12:35:30 +02:00
|
|
|
import java.io.*;
|
2024-04-30 02:12:14 +02:00
|
|
|
|
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
/**
|
|
|
|
* La classe Grille est une composante Swing pour représenter une grille de Sudoku.
|
|
|
|
*
|
|
|
|
* @author Julian GALLEGO
|
|
|
|
* @author Wilfried BRIGITTE
|
|
|
|
*/
|
|
|
|
public class Grille extends JComponent {
|
|
|
|
private static JLabel etat_exportation = new JLabel();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tableau des valeurs de la grille de Sudoku.
|
|
|
|
*/
|
|
|
|
public static int[][] grid_values = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Panneau pour la grille.
|
|
|
|
*/
|
|
|
|
public static JPanel place_grille = new JPanel();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fenêtre de l'application.
|
|
|
|
*/
|
|
|
|
public static JFrame fenetre = new JFrame();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Affiche graphiquement la grille de Sudoku.
|
|
|
|
*
|
|
|
|
* @param grille La grille de Sudoku à afficher.
|
|
|
|
* @param editable Indique si la grille est éditable.
|
|
|
|
* @param resolutionManuel Indique si la résolution est manuelle.
|
|
|
|
* @param duree La durée de résolution (en nanosecondes).
|
|
|
|
*/
|
2024-04-30 12:56:06 +02:00
|
|
|
public static void AfficherGrille (int[][] grille, boolean editable, boolean resolutionManuel, long duree) {
|
2024-05-04 16:04:24 +02:00
|
|
|
//paramètre de base de la fenetre
|
2024-04-22 15:38:29 +02:00
|
|
|
fenetre.setSize(900, 950);
|
2024-05-04 14:25:52 +02:00
|
|
|
fenetre.setResizable(false);
|
2024-04-02 12:35:30 +02:00
|
|
|
fenetre.setLocationRelativeTo(null);
|
|
|
|
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
2024-04-29 19:15:12 +02:00
|
|
|
|
2024-04-15 18:46:05 +02:00
|
|
|
place_grille.setSize(900,900);
|
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
//creation grille
|
2024-04-13 20:13:24 +02:00
|
|
|
GridLayout gestionnaire = new GridLayout(9,9,-2,-2);
|
2024-04-15 18:46:05 +02:00
|
|
|
place_grille.setLayout(gestionnaire);
|
2024-04-02 12:35:30 +02:00
|
|
|
|
2024-05-04 14:25:52 +02:00
|
|
|
JTextField[][] case_editable = null;
|
|
|
|
case_editable = new JTextField[9][9];
|
2024-05-04 16:04:24 +02:00
|
|
|
//si la grille peut etre entierement éditée (dans le cas du programme1
|
2024-04-14 18:50:05 +02:00
|
|
|
if(editable){
|
2024-04-30 02:12:14 +02:00
|
|
|
|
2024-04-27 05:18:18 +02:00
|
|
|
for (int ligne = 0; ligne < 9; ligne++) {
|
|
|
|
for (int col = 0; col < 9; col++) {
|
|
|
|
if (grille[ligne][col] == 0){
|
|
|
|
case_editable[ligne][col] = new JTextField("", 1);
|
2024-04-30 11:18:29 +02:00
|
|
|
case_editable[ligne][col].setDocument(new JTextFieldCharLimit(4));
|
2024-04-14 23:59:14 +02:00
|
|
|
}else{
|
2024-04-30 11:18:29 +02:00
|
|
|
case_editable[ligne][col] = new JTextField(1);
|
|
|
|
case_editable[ligne][col].setDocument(new JTextFieldCharLimit(4));
|
|
|
|
case_editable[ligne][col].setText(String.valueOf(grille[ligne][col]));
|
2024-04-14 23:59:14 +02:00
|
|
|
}
|
2024-04-27 05:18:18 +02:00
|
|
|
case_editable[ligne][col].setFont(new Font("Arial", Font.PLAIN, 30));
|
|
|
|
case_editable[ligne][col].setHorizontalAlignment(JTextField.CENTER);
|
|
|
|
if ((ligne % 3 == 0) && (ligne != 0) && (col % 3 == 0) && (col != 0)){
|
|
|
|
case_editable[ligne][col].setBorder(BorderFactory.createMatteBorder(5,5,2,2,Color.BLACK));
|
|
|
|
} else if((ligne % 3 == 0) && (ligne != 0)){
|
|
|
|
case_editable[ligne][col].setBorder(BorderFactory.createMatteBorder(5,2,2,2,Color.BLACK));
|
|
|
|
} else if ((col % 3 == 0) && (col != 0)){
|
|
|
|
case_editable[ligne][col].setBorder(BorderFactory.createMatteBorder(2,5,2,2,Color.BLACK));
|
|
|
|
} else {
|
|
|
|
case_editable[ligne][col].setBorder(BorderFactory.createMatteBorder(2,2,2,2,Color.BLACK));
|
|
|
|
}
|
|
|
|
place_grille.add(case_editable[ligne][col]);
|
|
|
|
}
|
2024-04-14 18:50:05 +02:00
|
|
|
}
|
2024-04-27 05:18:18 +02:00
|
|
|
|
|
|
|
} else {
|
2024-04-02 12:35:30 +02:00
|
|
|
|
2024-04-14 23:59:14 +02:00
|
|
|
JLabel[][] case_depart = null;
|
|
|
|
case_depart = new JLabel[9][9];
|
2024-04-30 02:12:14 +02:00
|
|
|
|
2024-04-27 05:18:18 +02:00
|
|
|
for (int ligne = 0; ligne < 9; ligne++) {
|
|
|
|
for (int col = 0; col < 9; col++) {
|
|
|
|
if ((grid_values[ligne][col]) == 0) {
|
2024-05-04 14:25:52 +02:00
|
|
|
case_editable[ligne][col] = new JTextField("", 1);
|
|
|
|
case_editable[ligne][col].setDocument(new JTextFieldCharLimit(4));
|
|
|
|
case_editable[ligne][col].setFont(new Font("Arial", Font.PLAIN, 30));
|
|
|
|
case_editable[ligne][col].setHorizontalAlignment(JTextField.CENTER);
|
2024-04-27 13:34:13 +02:00
|
|
|
if ((ligne % 3 == 0) && (ligne != 0) && (col % 3 == 0) && (col != 0)){
|
2024-05-04 14:25:52 +02:00
|
|
|
case_editable[ligne][col].setBorder(BorderFactory.createMatteBorder(5,5,2,2,Color.BLACK));
|
2024-04-27 05:18:18 +02:00
|
|
|
} else if ((col % 3 == 0) && (col != 0)){
|
2024-05-04 14:25:52 +02:00
|
|
|
case_editable[ligne][col].setBorder(BorderFactory.createMatteBorder(2,5,2,2,Color.BLACK));
|
2024-04-27 13:34:13 +02:00
|
|
|
} else if ((ligne % 3 == 0) && (ligne != 0)){
|
2024-05-04 14:25:52 +02:00
|
|
|
case_editable[ligne][col].setBorder(BorderFactory.createMatteBorder(5,2,2,2,Color.BLACK));
|
2024-04-27 05:18:18 +02:00
|
|
|
}else {
|
2024-05-04 14:25:52 +02:00
|
|
|
case_editable[ligne][col].setBorder(BorderFactory.createMatteBorder(2,2,2,2,Color.BLACK));
|
2024-04-27 05:18:18 +02:00
|
|
|
}
|
2024-05-04 14:25:52 +02:00
|
|
|
place_grille.add(case_editable[ligne][col]);
|
2024-04-14 23:59:14 +02:00
|
|
|
} else {
|
2024-04-27 05:18:18 +02:00
|
|
|
case_depart[ligne][col] = new JLabel(String.valueOf(grid_values[ligne][col]));
|
|
|
|
case_depart[ligne][col].setFont(new Font("Arial", Font.PLAIN, 30));
|
|
|
|
case_depart[ligne][col].setHorizontalAlignment(JTextField.CENTER);
|
2024-04-27 13:34:13 +02:00
|
|
|
if ((ligne % 3 == 0) && (ligne != 0) && (col % 3 == 0) && (col != 0)){
|
|
|
|
case_depart[ligne][col].setBorder(BorderFactory.createMatteBorder(5,5,2,2,Color.BLACK));
|
2024-04-27 05:18:18 +02:00
|
|
|
} else if ((col % 3 == 0) && (col != 0)){
|
2024-04-27 12:34:40 +02:00
|
|
|
case_depart[ligne][col].setBorder(BorderFactory.createMatteBorder(2,5,2,2,Color.BLACK));
|
2024-04-27 13:34:13 +02:00
|
|
|
} else if ((ligne % 3 == 0) && (ligne != 0)){
|
|
|
|
case_depart[ligne][col].setBorder(BorderFactory.createMatteBorder(5,2,2,2,Color.BLACK));
|
2024-04-27 05:18:18 +02:00
|
|
|
} else {
|
2024-04-27 12:34:40 +02:00
|
|
|
case_depart[ligne][col].setBorder(BorderFactory.createMatteBorder(2,2,2,2,Color.BLACK));
|
2024-04-27 05:18:18 +02:00
|
|
|
}
|
|
|
|
place_grille.add(case_depart[ligne][col]);
|
2024-04-14 23:59:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-04-26 16:26:26 +02:00
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
//bouton(s) grille(s)
|
2024-04-27 12:50:36 +02:00
|
|
|
JButton verifier = null;
|
|
|
|
JButton exporter = null;
|
2024-04-15 18:46:05 +02:00
|
|
|
JPanel bouton_grille = new JPanel();
|
2024-04-27 12:50:36 +02:00
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
//affichage des boutons en fonction du programme lancé
|
2024-04-27 12:50:36 +02:00
|
|
|
if(editable){
|
2024-04-27 20:51:28 +02:00
|
|
|
bouton_grille.add(etat_exportation);
|
2024-04-27 12:50:36 +02:00
|
|
|
exporter = new JButton("exporter");
|
|
|
|
bouton_grille.add(exporter);
|
|
|
|
place_grille.add(bouton_grille);
|
|
|
|
}else{
|
2024-04-30 12:56:06 +02:00
|
|
|
if(resolutionManuel){
|
|
|
|
verifier = new JButton("verifier");
|
|
|
|
bouton_grille.add(verifier);
|
|
|
|
place_grille.add(bouton_grille);
|
|
|
|
}else {
|
|
|
|
JLabel texteTemps = new JLabel("Le programme a mit "+duree+" nanoSecondes pour resoudre la grille");
|
|
|
|
bouton_grille.add(texteTemps);
|
|
|
|
}
|
2024-04-27 12:50:36 +02:00
|
|
|
}
|
|
|
|
|
2024-04-15 18:46:05 +02:00
|
|
|
fenetre.add(bouton_grille,BorderLayout.SOUTH);
|
2024-04-18 19:29:38 +02:00
|
|
|
fenetre.add(place_grille, BorderLayout.CENTER);
|
2024-04-26 16:26:26 +02:00
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
//affichage fenetre
|
2024-04-02 12:35:30 +02:00
|
|
|
fenetre.setVisible(true);
|
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
//verification si un chiffre peut être placé à un endroit
|
2024-05-04 14:25:52 +02:00
|
|
|
for (int ligne = 0; ligne < 9; ligne++) {
|
|
|
|
for (int col = 0; col < 9; col++) {
|
|
|
|
final int finalLigne = ligne;
|
|
|
|
final int finalCol = col;
|
|
|
|
|
|
|
|
if (case_editable[ligne][col] != null) {
|
|
|
|
JTextField textField = case_editable[ligne][col];
|
|
|
|
textField.addFocusListener(new FocusAdapter() {
|
|
|
|
@Override
|
|
|
|
public void focusLost(FocusEvent e) {
|
|
|
|
VerificationGrilleFini();
|
|
|
|
int[][] currentGrid = GrilleActuelle();
|
|
|
|
String input = textField.getText().trim();
|
|
|
|
if (!input.isEmpty()) {
|
|
|
|
int newValue = Integer.parseInt(input);
|
|
|
|
textField.setText("");
|
|
|
|
currentGrid = GrilleActuelle();
|
|
|
|
if (resolveurGrille.isValid(currentGrid, finalLigne, finalCol, newValue)) {
|
|
|
|
// Mettre à jour la grille actuelle avec le nouveau chiffre
|
|
|
|
currentGrid[finalLigne][finalCol] = newValue;
|
|
|
|
textField.setText(Integer.toString(newValue));
|
|
|
|
} else {
|
|
|
|
// Le chiffre n'est pas valide, réinitialiser le champ
|
|
|
|
textField.setText("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-18 19:29:38 +02:00
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
//événement des boutons
|
|
|
|
if (verifier != null) { // Vérification pour s'assurer que verifier a été initialisé
|
2024-04-27 12:50:36 +02:00
|
|
|
verifier.addActionListener(new ActionListener() {
|
2024-05-04 16:04:24 +02:00
|
|
|
/**
|
|
|
|
* verifie votre solution en appuyant sur le bouton verifier
|
|
|
|
*
|
|
|
|
* @param verifier L'évènement d'action.
|
|
|
|
*/
|
2024-04-27 12:50:36 +02:00
|
|
|
public void actionPerformed(ActionEvent verifier) {
|
2024-04-29 19:15:12 +02:00
|
|
|
VerificationGrilleFini();
|
2024-04-27 12:50:36 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2024-04-27 13:14:12 +02:00
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
if (exporter != null) { // Vérification pour s'assurer que exporter a été initialisé
|
2024-04-27 13:14:12 +02:00
|
|
|
exporter.addActionListener(new ActionListener() {
|
2024-05-04 16:04:24 +02:00
|
|
|
/**
|
|
|
|
* permet d'exporter votre grille édité.
|
|
|
|
*
|
|
|
|
* @param exporeter
|
|
|
|
*/
|
2024-05-04 14:25:52 +02:00
|
|
|
public void actionPerformed(ActionEvent exporter) {
|
2024-04-29 19:15:12 +02:00
|
|
|
if (!(resolveurGrille.resoudreSudoku(GrilleActuelle()))){
|
2024-04-27 20:51:28 +02:00
|
|
|
etat_exportation.setHorizontalAlignment(SwingConstants.LEFT);
|
|
|
|
etat_exportation.setText("Sudoku Impossible.");
|
|
|
|
etat_exportation.setForeground(Color.RED);
|
|
|
|
} else {
|
2024-04-29 19:15:12 +02:00
|
|
|
ExporterGrille(GrilleActuelle());
|
2024-04-27 20:51:28 +02:00
|
|
|
etat_exportation.setText("");
|
|
|
|
}
|
2024-04-27 13:14:12 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2024-04-02 12:35:30 +02:00
|
|
|
}
|
|
|
|
|
2024-04-14 18:50:05 +02:00
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
/**
|
|
|
|
* Charge une grille à partir d'un fichier.
|
|
|
|
*
|
|
|
|
* @param cheminFichier Le chemin du fichier contenant la grille.
|
|
|
|
* @return Un tableau représentant la grille.
|
|
|
|
*/
|
2024-04-02 12:35:30 +02:00
|
|
|
public static int[][] ChargerGrille(String cheminFichier){
|
|
|
|
try {
|
|
|
|
FileInputStream fs = new FileInputStream(cheminFichier);
|
|
|
|
DataInputStream fichier = new DataInputStream(fs);
|
|
|
|
|
|
|
|
grid_values = new int[9][9];
|
|
|
|
String string_values = "";
|
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
for (int a = 0; a < 9 ; a++ ) {
|
|
|
|
String ligne = String.valueOf(fichier.readInt());
|
|
|
|
while (ligne.length() < 9){
|
|
|
|
ligne = "0" + ligne;
|
|
|
|
}
|
|
|
|
string_values = string_values + ligne;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 9; i++) {
|
|
|
|
for (int j = 0; j < 9; j++) {
|
|
|
|
grid_values[i][j] = Character.getNumericValue(string_values.charAt(index));
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
fs.close();
|
|
|
|
return grid_values;
|
|
|
|
}catch(IOException e){
|
|
|
|
System.err.println("erreur fermeture du fichier");
|
|
|
|
}
|
|
|
|
}catch(IOException e) {
|
|
|
|
System.err.println("erreur ouverture du fichier");
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
2024-04-26 16:26:26 +02:00
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
/**
|
|
|
|
* Exporte une grille vers un fichier.
|
|
|
|
*
|
|
|
|
* @param grille La grille à exporter.
|
|
|
|
*/
|
2024-04-26 16:26:26 +02:00
|
|
|
public static void ExporterGrille(int[][] grille){
|
2024-04-27 18:56:50 +02:00
|
|
|
|
|
|
|
try {
|
|
|
|
JFileChooser filechooser2 = new JFileChooser();
|
|
|
|
filechooser2.setCurrentDirectory(new File("./grille"));
|
|
|
|
int result2 = filechooser2.showOpenDialog(null);
|
|
|
|
if (result2 == JFileChooser.APPROVE_OPTION) {
|
|
|
|
File selectedFile2 = filechooser2.getSelectedFile();
|
|
|
|
FileOutputStream fs2 = new FileOutputStream(selectedFile2.getAbsolutePath());
|
|
|
|
DataOutputStream fichier2 = new DataOutputStream(fs2);
|
|
|
|
|
|
|
|
String ligne_a_ecrire = "";
|
|
|
|
int entier_a_ecrire = 0;
|
|
|
|
for (int i = 0; i < 9; i++) {
|
|
|
|
for (int j = 0; j < 9; j++){
|
|
|
|
ligne_a_ecrire = ligne_a_ecrire+String.valueOf(grille[i][j]);
|
|
|
|
}
|
|
|
|
entier_a_ecrire = Integer.parseInt(ligne_a_ecrire);
|
|
|
|
fichier2.writeInt(entier_a_ecrire);
|
|
|
|
ligne_a_ecrire = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
fs2.close();
|
|
|
|
}catch(IOException e){
|
|
|
|
System.err.println("erreur fermeture du fichier");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}catch(IOException e) {
|
|
|
|
System.err.println("Erreur ouverture du fichier");
|
|
|
|
}
|
2024-04-27 13:14:12 +02:00
|
|
|
}
|
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
/**
|
|
|
|
* Récupère les valeurs actuelles de la grille et les place dans un tableau.
|
|
|
|
*
|
|
|
|
* @return Un tableau représentant la grille actuelle.
|
|
|
|
*/
|
2024-04-29 19:15:12 +02:00
|
|
|
public static int[][] GrilleActuelle(){
|
2024-04-27 13:14:12 +02:00
|
|
|
int[][] grilleActuelle = new int[9][9];
|
|
|
|
|
|
|
|
for (Component comp : place_grille.getComponents()) {
|
|
|
|
if (comp instanceof JTextField) {
|
|
|
|
JTextField textField = (JTextField) comp;
|
|
|
|
String text = textField.getText().trim();
|
|
|
|
int value = text.isEmpty() ? 0 : Integer.parseInt(text);
|
|
|
|
grilleActuelle[place_grille.getComponentZOrder(comp) / 9][place_grille.getComponentZOrder(comp) % 9] = value;
|
|
|
|
} else if (comp instanceof JLabel) {
|
|
|
|
JLabel label = (JLabel) comp;
|
|
|
|
String text = label.getText().trim();
|
|
|
|
int value = Integer.parseInt(text);
|
|
|
|
grilleActuelle[place_grille.getComponentZOrder(comp) / 9][place_grille.getComponentZOrder(comp) % 9] = value;
|
|
|
|
}
|
|
|
|
}
|
2024-04-26 16:26:26 +02:00
|
|
|
|
2024-04-27 13:14:12 +02:00
|
|
|
return grilleActuelle;
|
2024-04-26 16:26:26 +02:00
|
|
|
}
|
2024-04-29 19:15:12 +02:00
|
|
|
|
2024-05-04 16:04:24 +02:00
|
|
|
/**
|
|
|
|
* Vérifie si la grille actuelle correspond à la grille résolue.
|
|
|
|
*
|
|
|
|
* @return true si la grille est résolue correctement, sinon false.
|
|
|
|
*/
|
2024-04-30 14:51:04 +02:00
|
|
|
public static boolean VerificationGrilleFini(){
|
2024-04-29 19:15:12 +02:00
|
|
|
int[][] soluce_de_la_grille = new int[9][9];
|
|
|
|
soluce_de_la_grille = resolveurGrille.resoudreGrille(grid_values);
|
2024-04-30 14:51:04 +02:00
|
|
|
int[][] gActuelle = GrilleActuelle();
|
|
|
|
for ( int ligne = 0; ligne<9; ligne ++){
|
|
|
|
for (int col = 0; col <9; col++){
|
|
|
|
if(soluce_de_la_grille[ligne][col] != gActuelle[ligne][col]){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-05-04 14:25:52 +02:00
|
|
|
JeuFini.JeuFini();
|
|
|
|
fenetre.dispose();
|
2024-04-30 14:51:04 +02:00
|
|
|
return true;
|
2024-04-29 19:15:12 +02:00
|
|
|
}
|
2024-04-02 12:35:30 +02:00
|
|
|
}
|