Problème Débutant en Java

AEROTOWER -  
 AEROTOWER -
Bonjour,

Je suis débutante dans la programmation.

Je dois élaborer un programme en Java permettant de remplir n'importe quelle grille de Sudoku définie à partir d'un fichier .txt spécifiant la grille à remplir.

En entrée, le programme lira le fichier texte contenant la grille à compléter. En sortie, le programme affichera la grille complétée.

S'il existe plusieurs solutions pour la grille de départ, le programme devra fournir deux solutions seulement.

J'ai réalisé le programme suivant :

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
 
public class Principale20 {
 
    public static void main(String[] args) throws IOException {
         
        BufferedReader in = new BufferedReader(new FileReader("fichier/monSudoku grille1.txt")); //lieu où ce trouve le fichier .txt
 
        String line = in.readLine(); //on enregistre les lignes lues dans la variable line
 
        while (line!= null) { //tant qu'il y a quelque chose dans line on lit
 
            if( line.startsWith("#")) { //si line commence pas"#"
 
                line = in.readLine();//on passe à la ligne suivante
 
            }else {//sinon
 
                System.out.println(line);//on écrit la ligne dans la console....ou ailleurs ; )
 
                line=in.readLine();//on passe à la ligne suivante
 
            }
 
        }
 
        in.close(); //on ferme le lecteur
         
         
        SudokuTest2 sudo1= new SudokuTest2(args[0]);
        System.out.print(sudo1);
        System.out.println("Is legal ?  ");
        System.out.println("Is OK ?  ");
        sudo1.solver();
        System.out.print(sudo1);
 
    }
}

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
 
 
public class SudokuTest2 {
 
    public static final int N=9;
    int[][] grille;
 
    // Constructeur instancie avec une String
    public SudokuTest2(String nomDeFichier){
    }
     
    // Methode pour lire la grille a partir d'un fichier
    private void readGrilleFromFile(String nomDeFichier) {
        int[][] input=new int [N][N];
        try {
            StringBuffer sbuf = new StringBuffer();
            String str;
            BufferedReader in = new BufferedReader(new FileReader(nomDeFichier));
             
            str = in.readLine();
             
            int i=0;
            while (str != null) {
                for (int j=0;j<str.trim().split(" ").length;j++){
                    input[i][j]=Integer.parseInt(str.trim().split(" ")[j]);
                }
             
                str = in.readLine();
                i++;
            }
            grille=input;
        } catch (IOException e) {
            System.err.println(e);
            System.out.println("Fichier " +nomDeFichier+" inexistant...");
        }
      
    }
     
    private int[][] grille1;
    public static final int VIDE = 0; // cellule vide
    public static final int TAILLE = 9; // taille de la grille
 
    public SudokuTest2(int[][] tableau) {
        this.grille = new int[TAILLE][TAILLE];
 
        for (int i = 0; i < TAILLE; i++) {
            for (int j = 0; j < TAILLE; j++) {
                this.grille[i][j] = tableau[i][j];
            }
        }
    }
 
    // Nombre de possibilité dans une rangée
    private boolean ligne(int r, int n) {
        for (int i = 0; i < TAILLE; i++)
            if (grille1[r][i] == n)
                return true;
 
        return false;
    }
 
    // Nombre de possibilité dans une collone
    private boolean colonne(int c, int n) {
        for (int i = 0; i < TAILLE; i++)
            if (grille1[i][c] == n)
                return true;
 
        return false;
    }
 
    // Nombre de possibilité dans une sous-grille
    private boolean sousGrille(int r, int c, int n) {
        int ligne = r - r % 3;
        int colonne = c - c % 3;
 
        for (int i = ligne; i < ligne + 3; i++)
            for (int j = colonne; j < colonne + 3; j++)
                if (grille1[i][j] == n)
                    return true;
 
        return false;
    }
 
    // On vérifie que le nombre est présent sur une ligne et une colonne et dans une
    // sous-grille
    private boolean x(int r, int c, int n) {
        return !ligne(r, n) && !colonne(c, n) && !sousGrille(r, c, n);
    }
 
    // Méthode de résolution
 
    public boolean solver() {
        for (int ligne = 0; ligne < TAILLE; ligne++) {
            for (int colonne = 0; colonne < TAILLE; colonne++) {
                 
                 
                if (grille1[ligne][colonne] == VIDE) {
                     
                    for (int n = 1; n <= TAILLE; n++) {
                        if (x(ligne, colonne, n)) {
                             
                            grille1[ligne][colonne] = n;
 
                            if (solver()) {
                                return true;
                            } else {
                                grille1[ligne][colonne] = VIDE;
                            }
                        }
                    }
 
                    return false;
                }
            }
        }
 
        return true;
    }
 
    public void affichage() {
        for (int i = 0; i < TAILLE; i++) {
            for (int j = 0; j < TAILLE; j++) {
                System.out.print(" " + grille1[i][j]);
            }
 
            System.out.println();
        }
 
        System.out.println();
    }
     
}


Dans la console j'ai le résultat suivant :

123456789
.6.....3.
.7.....4.
789123456
.........
.........
456789123
.........
.........
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Principale20.main(Principale20.java:33)

Pouvez-vous m'aider s'il vous plait, je m'arrive pas à m'en sortir avec ce script.

7 réponses

  1. KX Messages postés 19031 Statut Modérateur 3 020
     
    Bonjour,

    Le message d'erreur est assez explicite, faut il encore savoir le lire.
    java.lang.ArrayIndexOutOfBoundsException: 0
    at Principale20.main(Principale20.java:33)

    ArrayIndexOutOfBoundsException est un type d'exception concernant l'accès à une valeur de tableau en dehors des indices possibles. Le 0 qui suit correspond à l'indice incorrect.

    Principale20.main correspond aux noms de la classe et de la méthode où s'est produite l'erreur à l'exécution et Principale20.java:33 au fichier de code et au numéro de ligne correspondante.

    Il suffit donc d'aller chercher la ligne 33 de Principale20.java, c'est
    SudokuTest2 sudo1= new SudokuTest2(args[0]);
    qui est effectivement dans la méthode main.

    Le problème de tableau à l'indice 0 est donc lié à la valeur
    args[0]
    qui n'existe pas, ce qui signifie que le tableau
    args
    est vide alors qu'on devrait avoir une valeur.

    Vu le constructeur de SudokuTest2, c'est un nom de fichier qui est attendu, celui que le programme est censé lire.
    Au début de ton programme tu as écrit en dur la valeur
    "fichier/monSudoku grille1.txt"
    pour ce nom de fichier. Je pense que c'est cette valeur là qu'il faudrait remettre aussi en paramètre de ce constructeur.

    La ligne 33 à remplacer serait donc :
    SudokuTest2 sudo1= new SudokuTest2("fichier/monSudoku grille1.txt");
    1
  2. AEROTOWER
     
    Après avoir fait la modification que tu m'as donné, j'ai eu le message suivant dans la console :

    123456789
    .6.....3.
    .7.....4.
    789123456
    .........
    .........
    456789123
    .........
    .........
    SudokuTest2@15db9742Is legal ?
    Is OK ?
    Exception in thread "main" java.lang.NullPointerException
    at SudokuTest2.solver(SudokuTest2.java:100)
    at Principale20.main(Principale20.java:37)
    0
    1. KX Messages postés 19031 Statut Modérateur 3 020
       
      À la ligne 100 de SudokuTest2.java tu as
      if (grille1[ligne][colonne] == VIDE)
      , le NullPointerException signifie que tu as une valeur null dans un contexte qui l'interdit.
      En l'occurrence ici tu dois avoir grille1[ligne] qui vaut null (au moins pour une valeur de ligne), donc null[colonne] plante...

      Il serait intéressant que tu affiches grille1 pour voir son contenu exact, cela te permettra de trouver où est le null qui pose problème.
      System.out.println(java.util.Arrays.deepToString(grille1))
      ;
      0
  3. AEROTOWER
     
    Bonjour,

    J'ai essayé ce que tu n'as dit, et ça ne fonctionne pas.
    Le problème que j'ai c'est que j'aimerais prendre les valeurs dans mon fichier .txt pour ensuite les intégrer dans mon programme. Et c'est là que ça coince.
    Je ne sais pas comment faire.
    Si tu as une idée, elle serait la bienvenue
    0
    1. KX Messages postés 19031 Statut Modérateur 3 020
       
      Quel est l'affichage obtenu pour la grille complète (avec le deepToString) au début de la méthode solver ?

          // Méthode de résolution
       
          public boolean solver() {
              System.out.println(java.util.Arrays.deepToString(grille1));
              for (int ligne = 0; ligne < TAILLE; ligne++) {
                  for (int colonne = 0; colonne < TAILLE; colonne++) {
      0
  4. AEROTOWER
     
    J'ai fait quelques modifications sur la méthode main

    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Principale20 {
    
     public static void main(String[] args) throws IOException {
      
      BufferedReader in = new BufferedReader(new FileReader("fichier/monSudoku grille1.txt")); //lieu où ce trouve le fichier .txt
    
      String line = in.readLine(); //on enregistre les lignes lues dans la variable line
    
      while (line!= null) { //tant qu'il y a quelque chose dans line on lit
    
       if( line.startsWith("#")) { //si line commence pas"#" 
    
        line = in.readLine();//on passe à la ligne suivante
    
       }else {//sinon
    
        System.out.println(line);//on écrit la ligne dans la console....ou ailleurs ; )
    
        line=in.readLine();//on passe à la ligne suivante
    
       }
    
      }
    
      in.close(); //on ferme le lecteur
      
      SudokuTest2 sudoku = new SudokuTest2("fichier/monSudoku grille1.txt");
      System.out.println("Grille à résoudre");
      sudoku.affichage();
    
      // we try resolution
      if (sudoku.solver()) {
       System.out.println("Solution du Sudoku");
       sudoku.affichage();
      } else {
       System.out.println("Pas de solution pour cette grille");
      
    } 
    
    }
    }

    et avec avec le deepToString au début de la méthode solver, j'obtiens dans la console le résultat suivant :
    123456789
    .6.....3. 
    .7.....4. 
    789123456 
    ......... 
    ......... 
    456789123 
    ......... 
    .........
    Grille à résoudre
    Exception in thread "main" java.lang.NullPointerException
     at SudokuTest2.affichage(SudokuTest2.java:127)
     at Principale20.main(Principale20.java:34)
    0
    1. KX Messages postés 19031 Statut Modérateur 3 020
       
      "avec le deepToString au début de la méthode solver, j'obtiens dans la console le résultat suivant"
      Il n'y a pas d'affichage de deepToString dans ce que tu as mis, parce qu'avec ton nouveau main() ton programme plante plus tôt, à cause de la méthode affichage().

      Le mieux serait peut-être de mettre le deepToString également au début de la méthode affichage, mais cela renforce bien l'idée que ta grille contient des null...
      0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. AEROTOWER
     
    Ma grille de début est la suivante :

    # -----------------------
    # Fichier grille1.txt 
    # -- Exemple de fichier de definition d'une grille
    # -----------------------
    123456789
    .6.....3. 
    .7.....4. 
    789123456 
    ......... 
    ......... 
    456789123 
    ......... 
    ......... 
    #    -------------------------
    #    | 1 2 3 | 4 5 6 | 7 8 9 |
    #    | . 6 . | . . . | . 3 . |
    #    | . 7 . | . . . | . 4 . |
    #    -------------------------
    #    | 7 8 9 | 1 2 3 | 4 5 6 |
    #    | . . . | . . . | . . . |
    #    | . . . | . . . | . . . |
    #    -------------------------
    #    | 4 5 6 | 7 8 9 | 1 2 3 |
    #    | . . . | . . . | . . . |
    #    | . . . | . . . | . . . |
    #    ------------------------- 
    


    Je ne sais vraiment plus quoi faire, rien ne fonctionne dans mon programme
    0
    1. KX Messages postés 19031 Statut Modérateur 3 020
       
      Vu l'état de ton programme, le mieux est peut-être de tout recommencer avec de meilleures bases

      Un début de code, qui permet la lecture du fichier et l'affichage de la grille :

      import java.io.IOException;
      import java.nio.file.*;
      import java.util.Arrays;
      
      public class Sudoku {
          private static final int SIZE = 9;
          private static final String COMMENT_PREFIX = "#";
          private static final int EMPTY = 0;
      
          private final int[][] values;
      
          public Sudoku(Path filePath) throws IOException {
              values = Files.lines(filePath).map(String::trim).filter(Sudoku::isLineCorrect).map(Sudoku::readLine).toArray(int[][]::new);
              if (values.length != SIZE)
                  throw new IllegalArgumentException(values.length + " lines found, " + SIZE + " expected " + this);
          }
      
          private static boolean isLineCorrect(final String trimLine) {
              return trimLine.length() == SIZE && !trimLine.startsWith(COMMENT_PREFIX);
          }
      
          private static int[] readLine(final String trimLine) {
              return trimLine.chars().map(Sudoku::readValue).toArray();
          }
      
          private static int readValue(int character) {
              return (character >= '1' && character <= '9') ? (character - '0') : EMPTY;
          }
      
          @Override
          public String toString() {
              return Arrays.deepToString(values);
          }
      
          public static void main(String[] args) throws IOException {
              System.out.println(new Sudoku(Paths.get("E:/grille1.txt")));
          }
      }
      0
  7. AEROTOWER
     
    Merci beaucoup KX, je vais essayer de continuer mon programme avec le début que tu m'as donné.
    J'ai bien pour le moment l'affichage de la grille de sudoku.
    0
  8. AEROTOWER
     
    Ca y est ! ça a fonctionné !! merci KX !

    voici le code :

    import java.io.IOException;
    import java.nio.file.*;
    import java.util.Arrays;
    
    public class SudokuTest3 {
        private static final int SIZE = 9;
        private static final String COMMENT_PREFIX = "#";
        private static final int EMPTY = 0;
        public static final int TAILLE = 9;
    
        private final int[][] values;
        public SudokuTest3(int[][] tableau) {
      this.values = new int[TAILLE][TAILLE];
      for (int i = 0; i < TAILLE; i++) {
       for (int j = 0; j < TAILLE; j++) {
        this.values[i][j] = tableau[i][j];
       
        }
     }
        }
        
        
        public SudokuTest3(Path filePath) throws IOException {
            values = Files.lines(filePath).map(String::trim).filter(SudokuTest3::isLineCorrect).map(SudokuTest3::readLine).toArray(int[][]::new);
            if (values.length != SIZE)
                throw new IllegalArgumentException(values.length + " lines found, " + SIZE + " expected " + this);
        }
    
        private static boolean isLineCorrect(final String trimLine) {
            return trimLine.length() == SIZE && !trimLine.startsWith(COMMENT_PREFIX);
        }
    
        private static int[] readLine(final String trimLine) {
            return trimLine.chars().map(SudokuTest3::readValue).toArray();
        }
    
        private static int readValue(int character) {
            return (character >= '1' && character <= '9') ? (character - '0') : EMPTY;
        }
    
        @Override
        public String toString() {
            return Arrays.deepToString(values);
        }
    
     // Nombre de possibilité dans une rangée
      private boolean ligne(int r, int n) {
       for (int i = 0; i < TAILLE; i++)
        if (values[r][i] == n)
         return true;
    
       return false;
      }
    
      // Nombre de possibilité dans une collone
      private boolean colonne(int c, int n) {
       for (int i = 0; i < TAILLE; i++)
        if (values[i][c] == n)
         return true;
    
       return false;
      }
    
      // Nombre de possibilité dans une sous-grille
      private boolean sousGrille(int r, int c, int n) {
       int ligne = r - r % 3;
       int colonne = c - c % 3;
    
       for (int i = ligne; i < ligne + 3; i++)
        for (int j = colonne; j < colonne + 3; j++)
         if (values[i][j] == n)
          return true;
    
       return false;
      }
    
      // On vérifie que le nombre est présent sur une ligne et une colonne et dans une
      // sous-grille
      private boolean x(int r, int c, int n) {
       return !ligne(r, n) && !colonne(c, n) && !sousGrille(r, c, n);
      }
        
     // Méthode de résolution
    
      public boolean solver() {
       for (int ligne = 0; ligne < TAILLE; ligne++) {
        for (int colonne = 0; colonne < TAILLE; colonne++) {
         
         
         if (values[ligne][colonne] == EMPTY) {
          
          for (int n = 1; n <= TAILLE; n++) {
           if (x(ligne, colonne, n)) {
            
            values[ligne][colonne] = n;
    
            if (solver()) { 
             return true;
            } else { 
             values[ligne][colonne] = EMPTY;
            }
           }
          }
    
          return false; 
         }
        }
       }
    
       return true; 
      }
    
      public void affichage() {
       for (int i = 0; i < TAILLE; i++) {
        for (int j = 0; j < TAILLE; j++) {
         System.out.print(" " + values[i][j]);
        }
    
        System.out.println();
       }
    
       System.out.println();
      }
        
        public static void main(String[] args) throws IOException {
     
            SudokuTest3 sudoku = new SudokuTest3(Paths.get("fichier/monSudoku grille1.txt"));
      System.out.println("Grille à résoudre");
      sudoku.affichage();
      
      // we try resolution
      if (sudoku.solver()) {
       System.out.println("Solution du Sudoku");
       sudoku.affichage();
      } else {
       System.out.println("Pas de solution pour cette grille");
        }
     }
    }


    et j'ai dans la console le résultat suivant :

    Grille à résoudre
     1 2 3 4 5 6 7 8 9
     0 6 0 0 0 0 0 3 0
     0 7 0 0 0 0 0 4 0
     7 8 9 1 2 3 4 5 6
     0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0
     4 5 6 7 8 9 1 2 3
     0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0
    
    Solution du Sudoku
     1 2 3 4 5 6 7 8 9
     5 6 4 8 9 7 2 3 1
     9 7 8 2 3 1 6 4 5
     7 8 9 1 2 3 4 5 6
     2 3 1 5 6 4 8 9 7
     6 4 5 9 7 8 3 1 2
     4 5 6 7 8 9 1 2 3
     3 1 2 6 4 5 9 7 8
     8 9 7 3 1 2 5 6 4
    0