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

  1. #1
    Membre actif
    Gestion de la récupération des mauvaises lettres déjà saisies par l'utilisateur
    Bonjour,
    J'ai conçu un jeu demandant à un joueur de deviner le titre d'un film (une sorte de jeu du pendu).
    Par contre je voudrais que lorsque le joueur a déjà saisi une mauvaise lettre que celle-ci s'affiche pour qu'il sache l'erreur qu'il a faite.
    Je pensais utiliser un tableau de type char, ou un StringBuilder mais je ne vois pas comment implémenter la solution.

    Merci par avance.
    Transact.

  2. #2
    Membre confirmé


    Le peu d'information sur ton projet ne nous aide pas beaucoup.
    Par contre, si tu nous demande comment stocker les tentatives de ton joueur, je ne te conseille pas de passer par un tableau puisqu'il s'agit d'une structure immuable.
    Un StringBuilder ne sert pas à ça donc à éviter.
    Il vaut mieux passer par une Collection de type List (ex. ArrayList<char>) (si l'ordre des tentatives est importante) ou Set (ex. HashSet<char>) (si tu souhaites conserver les lettres tentées sans conserver d'ordre particulier).
    Merci d'ajouter un sur les tags qui vous ont aidé

  3. #3
    Modérateur

    Salut,

    Il te suffit de stocker les lettres proposées mais pas dans le mot à trouver, puis de tester si une nouvelle lettre proposée en fait partie.

    Par exemple, si tu as une variable String pour le mot à trouver, et une variable char[] pour les lettres trouvées, donc quelque chose comme ça :

    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
    String mot = randomMot(); // détermination du mot à trouver par une méthode faite pour ça
    char[] trouvees = new char[mot.length()]; // un tableau pour stocker les lettres trouvees
    Arrays.fill(trouvees, '_'); // on remplit de _
    String mottrouve = new String(trouvees);
    do {
       System.out.println("Jeu du pendu : " + mottrouve );
       System.out.println("Proposez une lettre : ");
       char proposition = demandeNouvelleProposition(); // lecture d'une lettre au clavier 
       for(int i=0; i<mot.length(); i++) {
            if ( mot.charAt(i)==proposition ) { // la lettre proposée est dans le mot
                 trouvees[i]=proposition;
                 trouve = true; // on dit qu'on a trouvé la lettre dans le mot
            }
       }
       if ( trouve ) { // la lettre proposée est dans le mot
            System.out.println("Bravo ! Vous avez trouvé une lettre qui est dans le mot !");
       }
       else {
            System.out.println("Dommage ! La lettre proposée n'est pas dans le mot.");
       }
       mottrouve = new String(trouvees);
    } while( !mottrouve.equals(mot) ); // on joue tant que le mot n'est pas trouvé
    System.out.println("Bravo ! Vous avez trouvé le mot : " + mottrouve);


    Il te suffit d'ajouter une structure qui stocke les lettres déjà proposées, mais pas dans le mot :

    1. un tableau char[] (le problème c'est sa taille, cela dépend des caractères que tu permets de cherche, la casse... 26, 52, plus ?), on utilise un index qu'on incrémente pour ajouter la lettre (mauvaiseslettres[index++]=proposition)) et on parcourt pour tester si la lettre y est déjà
    2. un Set<Character>, on utilise Set.add() pour ajouter et on utilise Set.contains() pour tester si la lettre est déjà dedans
    3. un StringBuilder, on utilise StringBuilder.append() pour ajouter et StringBuilder.indexOf() pour chercher si la lettre est déjà dednas
    4. ...



    Par exemple, avec un Set :

    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
    String mot = randomMot(); // détermination du mot à trouver par une méthode faite pour ça
    char[] trouvees = new char[mot.length()]; // un tableau pour stocker les lettres trouvees
    Arrays.fill(trouvees, '_'); // on remplit de _
    Set<Character> setlettresmauvaises = new HashSet<>();
    String mottrouve = new String(trouvees);
    do {
       System.out.println("Jeu du pendu : " + mottrouve );
       System.out.println("Proposez une lettre : ");
       char proposition = demandeNouvelleProposition(); // lecture d'une lettre au clavier
       boolean trouve = false; // va nous servir à savoir que la lettre proposée n'est pas dans le mot
       for(int i=0; i<mot.length(); i++) {
            if ( mot.charAt(i)==proposition ) { // la lettre proposée est dans le mot
                 trouvees[i]=proposition;
                 trouve = true; // on dit qu'on a trouvé la lettre dans le mot
            }
       }
       if ( trouve ) { // la lettre proposée est dans le mot
            System.out.println("Bravo ! Vous avez trouvé une lettre qui est dans le mot !");
       }
       else { // la lettre proposée n'est pas dans le mot
           if ( setlettresmauvaises.contains( proposition ) ) { // la lettre avait déjà été proposée
               System.out.println("Vous avez déjà proposé cette lettre et elle n'est toujours pas dans le mot !");
           }
           else {
               System.out.println("Dommage ! La lettre proposée n'est pas dans le mot.");
               setlettresmauvaises.add( proposition ) ; // on stocke la lettre
           }
       }
       mottrouve = new String(trouvees);
    } while( !mottrouve.equals(mot) ); // on joue tant que le mot n'est pas trouvé
    System.out.println("Bravo ! Vous avez trouvé le mot : " + mottrouve);
    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.

  4. #4
    Membre actif
    Merci pour vos réponses, en même temps je codais une solution avec StringBuilder.
    Tant que la lettre saisie par le joueur n'est pas présente dans le titre du film alors je l'ajoute à mon StringBuilder et je l'affiche.
    Effectivement un Set<Character> me convient plus car StringBuilder étant une classe mutable, je préfère éviter les surprises ... même s'il ne s'agit que d'un jeu comme je le précise.

  5. #5
    Modérateur

    Citation Envoyé par Kazh Du Voir le message
    Par contre, si tu nous demande comment stocker les tentatives de ton joueur, je ne te conseille pas de passer par un tableau puisqu'il s'agit d'une structure immuable.
    Un tableau est de taille fixe, mais pas immuable. Il suffit de le créer à la taille la plus grande possible (bien sûr çà consomme un max de mémoire), et de gérer un index de la prochaine cellule à remplir. C'est ce que fait une ArrayList en interne (sauf que le tableau est créée "petit" au début, et de temps en temps, quand l'index atteint la borne supérieur, on créé un nouveau tableau et on copie le premier dedans...

    Citation Envoyé par Kazh Du Voir le message

    Un StringBuilder ne sert pas à ça donc à éviter.
    Ce n'est pas fait pour ça, mais ça fait le job, et en interne au final ça fait exactement ce qu'un ArrayList<Character> ferait.

    Citation Envoyé par Kazh Du Voir le message

    Il vaut mieux passer par une Collection de type List (ex. ArrayList<char>) (si l'ordre des tentatives est importante) ou Set (ex. HashSet<char>) (si tu souhaites conserver les lettres tentées sans conserver d'ordre particulier).
    <Character> et non <char>

    Il y a d'autres solutions. Par exemple, un tableau avec les 26 lettres (ou 52).
    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.

  6. #6
    Modérateur

    Citation Envoyé par transact Voir le message

    Effectivement un Set<Character> me convient plus car StringBuilder étant une classe mutable, je préfère éviter les surprises ... même s'il ne s'agit que d'un jeu comme je le précise.
    les instances dans les deux cas sont mutables (sinon on ne pourrait pas en modifier la valeur = le contenu). Et quelle surprise (mauvaise je suppose) penses-tu avoir ?
    L'avantage du Set, ce sont les performances à la recherche, mais il sera moins performant à l'ajout.
    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.

  7. #7
    Membre actif
    Merci pour toutes vos réponses, je vais utiliser un LinkedHashSet<>() car comme mentionné dans l'API Java :
    This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order).
    Je souhaite que l'ordre de saisie des mauvaises lettres soit conservé.

    Merci encore, et je n'oublie pas le pouce bleu car vous avez répondu exactement à ma question tous les deux.

  8. #8
    Membre actif
    Et quelle surprise (mauvaise je suppose) penses-tu avoir ?
    Mauvaise surprise en effet, je ne voudrais qu'une méthode récupère le résultat du StringBuilder et la modifie puis l'utilise plus bas dans le code ... par exemple vu que mon StringBuilder ne sera pas en final.

  9. #9
    Modérateur

    D'ailleurs, à noter, que par rapport un HashSet, ou un LinkedHashSet, une ArrayList a un autre avantage : si on veut conserver le fait qu'une mauvaise lettre a été saisie plusieurs fois... Un set ne conservera toujours qu'une seule occurence de chaque caractère.
    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.

  10. #10
    Modérateur

    Citation Envoyé par transact Voir le message
    Mauvaise surprise en effet, je ne voudrais qu'une méthode récupère le résultat du StringBuilder et la modifie puis l'utilise plus bas dans le code ... par exemple vu que mon StringBuilder ne sera pas en final.
    Bah, avec un Set, tu auras le même problème : si c'est possible avec une variable de type StringBuilder, c'est possible avec une variable de type Set. C'est le final justement qui va changer éventuellement quelque chose... (ça ne rend pas l'instance imuable, seulement la variable qui stocke la référence, donc ça protège la référence, pas le contenu de l'instance).

    Ensuite, la première protection pour empêcher une méthode de venir bidouiller ton StringBuilder ou ton Set, c'est que la variable soit locale à la méthode. Limiter la portée donc. Cela empêche déjà d'autres méthodes de venir changer la référence stockée dans la variable. De toute manière, il n'y a aucune raison objective de stocker ça dans un attribut, surtout, que, ça rendrait l'instance englobante stateful.
    Pour l'éviter la modification au sein de la méthode (à supposer que quelqu'un le fasse de manière irréfléchie, parce qu'il n'y a aucune raison de le faire), il suffit de la déclarer final. Pour le contenu, tu ne peux rien faire, ou alors il te faut faire une classe dédiée, qui permet l'ajout, mais aucune suppression (un wrapper de Set, ou de StringBuilder). Mais bon ça ne sert à rien... je vois pas qui irait modifier ton code pour réutiliser la liste des lettres déjà saisies, et en faire des choses...
    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.