This commit is contained in:
raban 2024-05-03 14:40:22 +02:00
commit 7c89ff9cf0
17 changed files with 108 additions and 259 deletions

Binary file not shown.

View File

@ -1,9 +0,0 @@
000095004
530408702
000700603
900034080
040010070
020570006
409002000
607903021
200650000

View File

@ -1,9 +0,0 @@
062500090
100029000
059008602
047190300
906302104
001087920
604800510
000940007
090001480

View File

@ -1,9 +0,0 @@
062506090
100029000
059008602
047190300
906302104
001087920
604800510
000940007
090001480

View File

@ -1,9 +0,0 @@
010400005
460007000
057020001
000610000
801000509
000035000
300060950
000500048
700004010

Binary file not shown.

View File

@ -0,0 +1 @@
-q<╕╜▒Ь5T^u:0&и°╪вВl^▒)/a ╪)T

View File

@ -1 +0,0 @@
grille 2 et 4 : https://la-conjugaison.nouvelobs.com/sudoku/

View File

@ -1,20 +1,14 @@
## Compilation
Utiliser la commande suivante pour compiler les programmes :
```bash
make
```
## Lancement des programmes ## Lancement des programmes
### Compiler et lancer le programme de Jeu ### Compiler et lancer le programme de Jeu
Utiliser la commande suivante : Utiliser la commande suivante :
```bash ```bash
make run jeu make jeu
``` ```
### Compiler et lancer le programme de Création ### Compiler et lancer le programme de Création
Utiliser la commande suivante : Utiliser la commande suivante :
```bash ```bash
make run creation make creation
``` ```
# Documentation # Documentation

View File

@ -1,7 +1,6 @@
import javax.swing.*; import javax.swing.*;
import java.awt.event.*; import java.awt.event.*;
import java.io.File;
public class AutomatiqueActionListener implements ActionListener { public class AutomatiqueActionListener implements ActionListener {
private JFrame choixFrame; private JFrame choixFrame;
@ -14,19 +13,30 @@ public class AutomatiqueActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
choixFrame.dispose(); choixFrame.dispose();
int[][] grille = GenerateurSudoku.genererGrille(); int[][] grille = new int[9][9]; // Création d'une grille vide
System.out.println("Grille Sudoku générée avec succès.");
long startTime = System.nanoTime(); // Ouverture du sélecteur de fichiers pour que l'utilisateur choisisse un fichier de grille
if (Resolveur.resoudreSudoku(grille)) { JFileChooser fileChooser = new JFileChooser();
long endTime = System.nanoTime(); int returnValue = fileChooser.showOpenDialog(null);
long duration = (endTime - startTime) / 1000000;
FenetrePrincipale fenetrePrincipale = new FenetrePrincipale(); if (returnValue == JFileChooser.APPROVE_OPTION) {
fenetrePrincipale.afficher(true, grille); File selectedFile = fileChooser.getSelectedFile();
JOptionPane.showMessageDialog(null, "Grille résolue avec succès en " + duration + " millisecondes !");
} else { // Lecture de la grille à partir du fichier sélectionné
JOptionPane.showMessageDialog(null, "Impossible de résoudre la grille."); Lecteur.lecture(selectedFile, grille);
// Résolution du Sudoku
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.");
}
} }
} }
} }

View File

@ -31,6 +31,9 @@ public class CaseMouseListener extends MouseAdapter {
if (panel.validerChiffre(panel.getLigneSelectionnee(), panel.getColonneSelectionnee(), valeur)) { if (panel.validerChiffre(panel.getLigneSelectionnee(), panel.getColonneSelectionnee(), valeur)) {
panel.getGrille()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] = valeur; panel.getGrille()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] = valeur;
panel.repaint(); panel.repaint();
if (panel.grilleComplete()) {
panel.afficherBravo();
}
} else { } else {
JOptionPane.showMessageDialog(null, "Ce chiffre ne respecte pas les contraintes du Sudoku. Veuillez choisir un autre chiffre."); JOptionPane.showMessageDialog(null, "Ce chiffre ne respecte pas les contraintes du Sudoku. Veuillez choisir un autre chiffre.");
} }
@ -54,17 +57,32 @@ public class CaseMouseListener extends MouseAdapter {
if (incertainOption == JOptionPane.OK_OPTION) { if (incertainOption == JOptionPane.OK_OPTION) {
// Vérifier que les valeurs obligatoires sont remplies // Vérifier que les valeurs obligatoires sont remplies
if (!incertainFields[0].getText().isEmpty() && !incertainFields[1].getText().isEmpty()) { if (!incertainFields[0].getText().isEmpty() && !incertainFields[1].getText().isEmpty()) {
// Récupérer les valeurs incertaines saisies par le joueur // Vérifier que les valeurs incertaines sont valides
int valeursIncertaines = 0; boolean valeursValides = true;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (!incertainFields[i].getText().isEmpty()) { if (!incertainFields[i].getText().isEmpty()) {
int valeur = Integer.parseInt(incertainFields[i].getText()); int valeur = Integer.parseInt(incertainFields[i].getText());
valeursIncertaines |= (valeur << (i * 4)); if (valeur < 1 || valeur > 9) {
valeursValides = false;
break;
}
} }
} }
// Mettre à jour la grille avec les valeurs incertaines if (valeursValides) {
panel.getGrille()[panel.getLigneSelectionnee()][panel.getColonneSelectionnee()] = valeursIncertaines; // Récupérer les valeurs incertaines saisies par le joueur
panel.repaint(); 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 valeurs incertaines doivent être des nombres entre 1 et 9.");
}
} else { } else {
JOptionPane.showMessageDialog(null, "Les deux premières valeurs incertaines sont obligatoires."); JOptionPane.showMessageDialog(null, "Les deux premières valeurs incertaines sont obligatoires.");
} }

View File

@ -19,11 +19,29 @@ public class GrillePainter {
for (int j = 0; j < panel.getTailleGrille() * panel.getTailleRegion(); j++) { for (int j = 0; j < panel.getTailleGrille() * panel.getTailleRegion(); j++) {
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.drawRect(j * panel.getTailleCellule(), i * panel.getTailleCellule(), panel.getTailleCellule(), panel.getTailleCellule()); g.drawRect(j * panel.getTailleCellule(), i * panel.getTailleCellule(), panel.getTailleCellule(), panel.getTailleCellule());
int valeur = panel.getGrille()[i][j]; int valeur = panel.getGrille()[i][j];
if (valeur != 0) { if (valeur != 0) {
g.drawString(String.valueOf(valeur), j * panel.getTailleCellule() + panel.getTailleCellule() / 2, i * panel.getTailleCellule() + panel.getTailleCellule() / 2); if (valeur < 10) {
g.drawString(String.valueOf(valeur), j * panel.getTailleCellule() + panel.getTailleCellule() / 2, i * panel.getTailleCellule() + panel.getTailleCellule() / 2);
} else {
int[] valeurs = decomposerValeurs(valeur);
for (int k = 0; k < valeurs.length; k++) {
int xOffset = (k % 2) * panel.getTailleCellule() / 2;
int yOffset = (k / 2) * panel.getTailleCellule() / 2;
g.drawString(String.valueOf(valeurs[k]), j * panel.getTailleCellule() + xOffset + panel.getTailleCellule() / 4, i * panel.getTailleCellule() + yOffset + panel.getTailleCellule() / 4);
}
}
} }
} }
} }
} }
private static int[] decomposerValeurs(int valeursIncertaines) {
int[] valeurs = new int[4];
for (int i = 0; i < 4; i++) {
valeurs[i] = (valeursIncertaines >> (i * 4)) & 0xF;
}
return valeurs;
}
} }

View File

@ -1,46 +0,0 @@
import javax.swing.*;
import java.awt.*;
public class GrilleSudokuDessin extends JPanel {
private static final int TAILLE_GRILLE = 3;
private static final int TAILLE_REGION = 3;
private static final int TAILLE_CELLULE = 50;
private int[][] grille;
public GrilleSudokuDessin(int[][] grille) {
this.grille = grille;
setPreferredSize(new Dimension(TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// Définir l'épaisseur de la ligne
g2d.setStroke(new BasicStroke(20)); // Épaisseur de ligne de 4 pixels
// Dessiner les lignes de la grille (en gras pour les contours)
for (int i = 0; i <= TAILLE_GRILLE * TAILLE_REGION; i++) {
if (i % TAILLE_REGION == 0) {
g2d.drawRect(0, i * TAILLE_CELLULE - 2, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, 4);
g2d.drawRect(i * TAILLE_CELLULE - 2, 0, 4, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE);
} else {
g2d.drawRect(0, i * TAILLE_CELLULE - 1, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE, 2);
g2d.drawRect(i * TAILLE_CELLULE - 1, 0, 2, TAILLE_GRILLE * TAILLE_REGION * TAILLE_CELLULE);
}
}
// Dessiner les valeurs de la grille
g.setColor(Color.BLACK);
for (int i = 0; i < grille.length; i++) {
for (int j = 0; j < grille[i].length; j++) {
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);
}
}
}
}
}

View File

@ -1,7 +1,6 @@
import javax.swing.*; import javax.swing.*;
import java.awt.event.*; import java.awt.event.*;
import java.io.File;
public class ManuelActionListener implements ActionListener { public class ManuelActionListener implements ActionListener {
private JFrame choixFrame; private JFrame choixFrame;
@ -14,10 +13,21 @@ public class ManuelActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
choixFrame.dispose(); choixFrame.dispose();
int[][] grille = GenerateurSudoku.genererGrille(); int[][] grille = new int[9][9]; // Création d'une grille vide
System.out.println("Grille Sudoku générée avec succès.");
FenetrePrincipale fenetrePrincipale = new FenetrePrincipale(); // Ouverture du sélecteur de fichiers pour que l'utilisateur choisisse un fichier de grille
fenetrePrincipale.afficher(false, grille); JFileChooser fileChooser = new JFileChooser();
int returnValue = fileChooser.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
// Lecture de la grille à partir du fichier sélectionné
Lecteur.lecture(selectedFile, grille);
// Affichage de la grille dans la fenêtre principale en mode manuel
FenetrePrincipale fenetrePrincipale = new FenetrePrincipale();
fenetrePrincipale.afficher(false, grille);
}
} }
} }

View File

@ -1,27 +0,0 @@
import java.io.*;
public class OuvertureFichier {
public static int[][] lireFichier(File fichier) {
int[][] grille = new int[9][9];
try (BufferedReader br = new BufferedReader(new FileReader(fichier))) {
String ligne;
int i = 0;
while ((ligne = br.readLine()) != null && i < 9) {
for (int j = 0; j < Math.min(ligne.length(), 9); j++) {
char caractere = ligne.charAt(j);
if (caractere != ' ') {
// Convertir chaque caractère en valeur numérique
int valeur = Integer.parseInt(String.valueOf(caractere), 16);
grille[i][j] = valeur;
}
}
i++;
}
} catch (IOException e) {
e.printStackTrace();
}
return grille;
}
}

View File

@ -92,6 +92,26 @@ public class SaisieGrille extends JPanel {
} }
} }
// Vérifier les valeurs incertaines dans la cellule
int valeursIncertaines = grille[ligne][colonne];
for (int i = 0; i < 4; i++) {
int valeur = (valeursIncertaines >> (i * 4)) & 0xF;
if (valeur != 0 && valeur == chiffre) {
return false;
}
}
return true;
}
public boolean grilleComplete() {
for (int i = 0; i < grille.length; i++) {
for (int j = 0; j < grille[i].length; j++) {
if (grille[i][j] == 0) {
return false;
}
}
}
return true; return true;
} }
@ -101,5 +121,7 @@ public class SaisieGrille extends JPanel {
GrillePainter.dessinerGrille(g, this); GrillePainter.dessinerGrille(g, this);
} }
public void afficherBravo() {
JOptionPane.showMessageDialog(this, "Bravo ! La grille est complétée avec succès.");
}
} }

View File

@ -1,114 +0,0 @@
import javax.swing.*;
import java.io.*;
public class SudokuGenerator {
public static int[][] generateGrid() {
// grille par défaut
int[][] grid = {
{0, 0, 0, 9, 0, 5, 0, 0, 4},
{5, 0, 3, 0, 0, 4, 0, 8, 7},
{0, 0, 0, 7, 0, 0, 6, 0, 3},
{9, 0, 0, 0, 3, 4, 0, 8, 0},
{0, 4, 0, 0, 1, 0, 0, 7, 0},
{0, 2, 0, 5, 7, 0, 0, 0, 6},
{4, 0, 9, 0, 0, 2, 0, 0, 0},
{6, 0, 7, 9, 0, 3, 0, 2, 1},
{2, 0, 0, 6, 5, 0, 0, 0, 0}
};
return grid;
}
public static int[][] readGridFromFile() {
int[][] grid = new int[9][9];
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
try (BufferedReader reader = new BufferedReader(new FileReader(selectedFile))) {
for (int i = 0; i < 9; i++) {
String line = reader.readLine();
// Vérifier la longueur de la ligne lue
if (line.length() != 9) {
JOptionPane.showMessageDialog(null, "Invalid file format. Please select a file with correct Sudoku grid format.");
return generateGrid(); // Charger la grille par défaut en cas d'erreur
}
for (int j = 0; j < 9; j++) {
char ch = line.charAt(j);
if (ch >= '1' && ch <= '9') {
grid[i][j] = Character.getNumericValue(ch);
} else {
grid[i][j] = 0;
}
}
}
if (!isGridValid(grid)) {
JOptionPane.showMessageDialog(null, "Invalid Sudoku grid. Loading default grid.");
return generateGrid(); // Charger la grille par défaut en cas de grille invalide
}
} catch (IOException e) {
e.printStackTrace();
}
}
return grid;
}
// Méthode pour vérifier si la grille est valide
private static boolean isGridValid(int[][] grid) {
for (int i = 0; i < 9; i++) {
if (!isRowValid(grid, i) || !isColumnValid(grid, i) || !isRegionValid(grid, i)) {
return false;
}
}
return true;
}
// Méthode pour vérifier s'il n'y a pas de chiffres en double sur une ligne donnée
private static boolean isRowValid(int[][] grid, int row) {
boolean[] seen = new boolean[10]; // Tableau pour suivre les chiffres déjà rencontrés
for (int i = 0; i < 9; i++) {
int num = grid[row][i];
if (num != 0) {
if (seen[num]) {
return false; // Le chiffre est déjà apparu sur cette ligne
}
seen[num] = true;
}
}
return true; // Aucun chiffre en double sur la ligne
}
// Méthode pour vérifier s'il n'y a pas de chiffres en double sur une colonne donnée
private static boolean isColumnValid(int[][] grid, int col) {
boolean[] seen = new boolean[10]; // Tableau pour suivre les chiffres déjà rencontrés
for (int i = 0; i < 9; i++) {
int num = grid[i][col];
if (num != 0) {
if (seen[num]) {
return false; // Le chiffre est déjà apparu sur cette colonne
}
seen[num] = true;
}
}
return true; // Aucun chiffre en double sur la colonne
}
// Méthode pour vérifier s'il n'y a pas de chiffres en double dans une région donnée
private static boolean isRegionValid(int[][] grid, int region) {
int rowOffset = (region / 3) * 3;
int colOffset = (region % 3) * 3;
boolean[] seen = new boolean[10]; // Tableau pour suivre les chiffres déjà rencontrés
for (int i = rowOffset; i < rowOffset + 3; i++) {
for (int j = colOffset; j < colOffset + 3; j++) {
int num = grid[i][j];
if (num != 0) {
if (seen[num]) {
return false; // Le chiffre est déjà apparu dans cette région
}
seen[num] = true;
}
}
}
return true; // Aucun chiffre en double dans la région
}
}