IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Exception in thread "main" java.util.NoSuchElementException


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    ENSEIRB
    Inscrit en
    Janvier 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : ENSEIRB
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Janvier 2016
    Messages : 11
    Par défaut Exception in thread "main" java.util.NoSuchElementException
    Bonjour à tous.

    J'ai pour projet de créer une bataille navale en java. J'ai créé une classe Action qui a pour but de demander au joueur ce qu'il souhaite faire : "fire" pour tirer ou "view" pour afficher la grille de jeux. Voici ma classe Action :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    package fr.enseirb.battleship;
     
    import java.util.Scanner;
     
    public class Action {
     
        private int x;
        private int y;
        private String act;
        public Action(){
            this.act="action";
            this.x=0;
            this.y=0;
        }
     
        public void get(){
             Scanner sc = new Scanner(System.in);
                System.out.println("Select an action (fire or view) :");
                this.act = sc.next();
                System.out.println("You choose : " + this.act);
                if(this.act.equals("fire")){
                    System.out.println("Select the target position X Y");
                    this.x = sc.nextInt();
                     this.y = sc.nextInt();
                    System.out.println("You choose : " + this.x +","+this.y);
                }
     
        }
     
        public String getact(){
            return this.act;
        }
        public int getx(){
            return this.x;
        }
        public int gety(){
            return this.y;
        }
     
     
    }
    Lorsque je la teste dans une classe Test elle fonctionne sans problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    package fr.enseirb.battleship;
     
    import fr.enseirb.battleship.ship.*;
     
    import java.util.Scanner;
     
    import fr.enseirb.battleship.grid.*;
    public class Test {
     
        public static void main(String[] args){
     
     
     
        Action action = new Action();
     
     
     
                action.get();
                System.out.println(action.getact());
     
                if(action.getact().equals("fire")){
     
     
                    System.out.println("on est dans fire");
                }
                else if(action.getact().equals("view")){
     
                    System.out.println("on est dans view");
                }
     
                else if(action.getact().equals("debug")){
     
                    System.out.println("on est dans debug");
                }
     
     
            }
     
     
     
        }
    Mais quand je l'utile dans ma classe Game cela ne fonctionne plus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    package fr.enseirb.battleship;
     
    import fr.enseirb.battleship.ship.*;
    import fr.enseirb.battleship.shot.*;
    import fr.enseirb.battleship.draw.*;
     
    import java.util.Scanner;
     
    import fr.enseirb.battleship.grid.*;
     
    public class Game {
     
        private int run;
        private int x;
        private int y;
        private View view = new View();
        private Debug debug = new Debug();
     
    public Game(){
     
    }
     
        public void rungame(ShipList playershiplist, ShipList aishiplist, Grid grid){
     
     
            PlayerShot playershot = new PlayerShot(playershiplist, grid);
            AiShot aishot=new AiShot(aishiplist, grid);
            Action action=new Action();
            action.get();
     
     
            if(action.getact().equals("fire")){
     
     
                playershot.playershot(action.getx(), action.gety());
                aishot.randomshot();
            }
            else if(action.getact().equals("view")){
     
                view.view(grid, aishiplist, playershiplist, aishot.getshotlist(), playershot.getshotlist());
            }
     
            else if(action.getact().equals("debug")){
     
                debug.debug(grid, aishiplist, playershiplist, aishot.getshotlist(), playershot.getshotlist());
            }
     
     
        }
     
    }
    J'obtient le message d'erreur suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Exception in thread "main" java.util.NoSuchElementException
        at java.util.Scanner.throwFor(Scanner.java:862)
        at java.util.Scanner.next(Scanner.java:1371)
        at fr.enseirb.battleship.Action.get(Action.java:19)
        at fr.enseirb.battleship.Game.rungame(Game.java:28)
        at fr.enseirb.battleship.App.main(App.java:36)
    Et je n'arrive pas à comprendre pourquoi ..

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    Ce serait intéressant de voir le code de la classe App. Mais je suppose que le problème vient du fait que la méthode get() de la classe Action est appelée plusieurs fois, ce qui provoque plusieurs créations d'instances de Scanner sur System.in. Le problème vient du fait que la classe Scanner lit les données depuis le tampon (buffer) de System.in, et peut commencer à y lire d'avance certains octets. Si tu crées plusieurs instances de Scanner, une des instances peut donc commencer à lire des caractères qu'une autre instance va chercher à récupérer lors de l'appel de next() ou nextInt(), mais ces octets n'étant plus dans le buffer, l'instance de Scanner ne trouve rien à lire et soulève l'exception.

    POC d'Illustration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class DemoScanner {
     
    	public static void main(String[] args) {
     
                    // on simule la saisie de l'utilisateur, des 26 lettres de a à z, avec appui de la touche entrée entre chaque
    		int nb=0;
    		StringBuilder inputString = new StringBuilder();
    		for(char c='a'; c<='z'; c++, nb++) {
    			inputString.append(c);
    			inputString.append('\n');
    		}
     
    		try(ByteArrayInputStream inputStream = new ByteArrayInputStream(inputString.toString().getBytes())) { // on lit la saisie simulée exactement comme si on la lisait dans System.in
     
    			//Scanner scanner = new Scanner(inputStream); // OK
    			while (nb-->0) {
    				Scanner scanner = new Scanner(inputStream); // KO
    				String s = scanner.next();
    				System.out.print(s);
    				System.out.print(' ');
    			}
    			System.out.println();
     
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
     
    	}
     
    }
    Il ne faut donc créé qu'une seule instance unique de Scanner sur un même InputStream (dans ton cas, une variable static par exemple dans la classe Action). De plus, tu as intérêt à utiliser les méthode du type hasNext(), ou hasNextInt(), pour vérifier que la saisie du joueur est conforme à ce que tu cherches à lire par les appels de next() ou nextInt().
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre habitué
    Homme Profil pro
    ENSEIRB
    Inscrit en
    Janvier 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : ENSEIRB
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Janvier 2016
    Messages : 11
    Par défaut
    Merci de ta réponse rapide .
    Pour avoir un seul est unique scanner je dois donc le créer dans ma classe App (Classe contenant le main) et le faire passer en entrée de toutes mes autres classes ?

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Oui, c'est une solution, en particulier sur tu as besoin de l'utiliser dans plusieurs instances (de même classe ou de différentes classes). Ou la déclarer en public final static, dans App.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public class App {
    public static final Scanner SCANNER = new Scanner(System.in);
     
    /* ... */
     
    }
    Et y accèder là où tu en a besoin par App.SCANNER
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre habitué
    Homme Profil pro
    ENSEIRB
    Inscrit en
    Janvier 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : ENSEIRB
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Janvier 2016
    Messages : 11
    Par défaut
    y acceder par App.SCANNER ?

    Je dois faire un "import App.SCANNER; " , comme pour une classe ?

    (j'ai l'impression que cette question est stupide désolé je débute en java )

  6. #6
    Membre habitué
    Homme Profil pro
    ENSEIRB
    Inscrit en
    Janvier 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : ENSEIRB
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Janvier 2016
    Messages : 11
    Par défaut
    A c'est bon il suffit d'écrire App.SCANNER pour utiliser la variable, en effet question stupide

  7. #7
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Ce n'est pas du tout une question stupide, au contraire. Ce n'est pas utile : il faudra importer la classe App en revanche. Mais, pour éviter d'avoir à indiquer App. systématiquement (et donc à faire l'import de App), tu peux faire un import static.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package fr.enseirb.battleship.machinchose;
     
    import static fr.enseirb.battleship.App.SCANNER;
     
    public class Exemple {
     
       public int lireTruc() {
              System.out.print("Saisir le truc :");
              while( !SCANNER.hasNextInt() ) {
                     SCANNER.next();
                     System.out.print("Le truc doit être un int...\nRecommencez : ");
              }
              return SCANNER.nextInt();
       }
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 02/06/2008, 12h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo