TP 3.2 2324v1

Avant de commencer ce TP,  le TP 3.1 doit être entièrement terminé, avec tous nos tests et vos tests réussis.

Si ce n'est pas le cas, demandez de l'aide à l'intervenant dès le début du TP.

I. Suite de la classe Game

  1. Ajouter une procédure privée printWelcome sans aucun paramètre (qui sera appelée au début du jeu, dans la partie III.) pour afficher le message suivant (notez que les 2 dernières lignes changeraient si le lieu initial n'était pas 'main entrance') :
    Welcome to the World of Zuul!
    World of Zuul is a new, incredibly boring adventure game.
    Type 'help' if you need help.
     
    You are outside the main entrance of the university
    Exits: east south west
    Remarquez qu'on affiche juste les directions possibles, pas les lieux.

  2. Ajouter 2 méthodes privées printHelp et quit (qui seront exécutées lorsqu'on tapera respectivement les commandes "help" et "quit") :
    a) La première est une procédure (sans aucun paramètre) qui affiche :
    You are lost. You are alone.
    You wander around at the university.

    Your command words are:
      go quit help
    Lorsque vous n'avez plus d'erreur de compilation, clic-droit sur la classe GameTest et exécuter testprint_6().
    Si vous voyez apparaître tout en bas la mention 'testprint_6 succeeded', vous pouvez passer à la suite. Sinon, vous devez voir apparaître une fenêtre 'BlueJ: Test Results'. Cliquer sur la ligne 'v1.GameTest.testprint_6' pour voir le message d'erreur sous la barre rouge.
    b) La seconde est une fonction booléenne qui prend une Command en paramètre. S'il y a un second mot, elle retourne faux après avoir affiché "Quit what ?". Sinon, elle se contente de retourner vrai. (indice au VI.1)
    Lorsque vous n'avez plus d'erreur de compilation, clic-droit sur la classe GameTest et exécuter testquit_7().
    Si vous voyez apparaître tout en bas la mention 'testquit_7 succeeded', vous pouvez passer à la suite. Sinon, cliquez sur la ligne 'v1.GameTest.testquit_7' pour voir le message d'erreur sous la barre rouge.

  3. Ajouter maintenant une fonction booléenne privée processCommand qui prend une Command en paramètre. Son rôle est d'appeler la bonne méthode en fonction de la commande passée en paramètre.
    a) Si la commande est inconnue  , elle retournera faux après avoir affiché le message "I don't know what you mean...".
    b) Sinon, après avoir appelé la méthode correspondant à la commande, elle retournera :
    - soit le résultat (booléen) de quit() (dans le cas de la commande "quit"),
    - soit systématiquement faux  (pour les autres commandes).
    c) Si aucun mot de commande n'a été reconnu, afficher "Erreur du programmeur : commande non reconnue !", car cela aurait dû être détecté par isUnknown().
    (indice au VI.2)
    Lorsque vous n'avez plus d'erreur de compilation, clic-droit sur la classe GameTest et exécuter testprocessCommand_8().
    Si vous voyez apparaître tout en bas la mention 'testprocessCommand_8 succeeded', vous pouvez passer à la suite. Sinon, cliquez sur la ligne 'v1.GameTest.testprocessCommand_8' pour voir le message d'erreur sous la barre rouge.

  4. Vérifier interactivement le bon fonctionnement de cette deuxième version de la classe Game. Vous pouvez rendre publiques les méthodes que vous voulez tester, puis les remettre privées puisqu'elles n'auront pas vocation à être appelées en dehors de cette classe.

II. Créer les deux dernières classes

  1. Créer une classe CommandWords qui contiendra les mots de commande acceptés par le jeu. Pour cela :
    1. Déclarez comme unique attribut un tableau de chaînes de caractères, constant (==> non modifiable : quel mot java permet ça ?) que nous appellerons aValidCommands et que nous initialiserons avec les 3 seules commandes reconnues par le jeu pour l'instant.
      (voir les rappels de syntaxe sur les tableaux ci-dessous)
    2. Comme cette classe ne contient qu'un attribut constant, pas besoin de constructeur.
      (pour information, Java crée automatiquement un constructeur par défaut avec un corps vide)
    3. Compilez. Quand il n'y a plus d'erreurs, clic-droit sur la classe et Créer classe Test. Écrasez tout le code par celui contenu dans le fichier CommandWordsTest.java tout en bas de cet énoncé. Compilez. Exécutez la méthode testconstructeur_3(). Tout est vert ?
    4. Écrivez maintenant une fonction booléenne isCommand qui pourra dire si oui ou non le mot qu'on lui passe en paramètre fait partie des commandes reconnues.
      Pour cela, elle parcourera simplement le tableau des commandes reconnues et retournera sa réponse dès qu'elle l'aura trouvée.
    5. Lorsque vous n'avez plus d'erreur de compilation, clic-droit sur la classe CommandWordsTest et exécuter testisCommand_4().

    Ce qu'il faut retenir sur les tableaux   

    Ce qu'il faut retenir sur la boucle for   

    C'est une boucle souvent utilisée avec les tableaux. Même si elle est rigoureusement équivalente à une boucle while (comme on pourra le constater ci-dessous), il est très pratique d'avoir toutes les informations rassemblées en une ligne au lieu d'être potentiellement dispersées dans une méthode.
    On l'utilise à chaque fois que l'on souhaite exprimer une répétition un nombre connu de fois.

    L'ensemble des instructions :

    initialisation ;
    while ( condition_de_continuation ) {
      instructions_à_répéter ;
      incrémentation ;
    } // while

    peut/doit avantageusement être remplacé par :

    for ( initialisation ; condition_de_continuation ; incrémentation ) {
      instructions_à_répéter ;
    } // for

    Ce qu'on appelle initialisation comprend en général la déclaration, par exemple : int i=0;
    Ce qu'on appelle incrémentation est en général de la forme i = i+1, mais rien n'empêche d'écrire i = i-2 et d'adapter l'initialisation et la condition en conséquence !
    Attention !  La condition_de_continuation (comme son nom l'indique) n'est pas une condition d'arrêt !
    Il est important de noter que l'incrémentation a lieu en fin de boucle, après les instructions_à_répéter.
    A noter également : c'est le seul cas en java où un point-virgule (à l'intérieur des parenthèses) ne marque pas la fin de l'instruction for !

    Si ça ne suffit pas, vous pouvez aussi lire ce mini-cours sur la boucle for

  2. Créer une classe Parser qui lira la commande tapée au clavier, vérifiera qu'elle est valide, et qui construira l'objet Command correspondant.
    Comme il y a beaucoup de nouvelles notions importantes dans cette classe, copiez/collez le code de la classe jointe en bas de ce sujet, et nous reviendrons sur ces notions au TP suivant.
    En attendant lire la description ci-dessous :
    - déclaration d'un objet de la classe CommandWords qui gèrera la validité des commandes tapées (L23) et d'un objet Scanner qui ira lire les commandes tapées au clavier (L24)
    - constructeur par défaut qui crée les 2 objets déclarés en attribut (L29-34) (à quoi les attributs sont-ils initialisés ?)
    - une fonction qui retourne un objet Command en fonction de la commande tapée au clavier (L39-47) ; son principe :
       1) s'il y a un mot dans la ligne tapée, le mémoriser dans un 1er mot, puis s'il y a encore un mot, le mémoriser dans le 2nd mot. (L50-57)
       2) Demander à l'objet CommandWords si le premier mot correspond à une commande valide ou pas. (L62)
       3) Si oui, retourner un nouvel objet Command composé des deux mots (le second pouvant éventuellement être null) (L63) ; sinon, retourner un nouvel objet Command contenant 2 fois null (L66).
    Plus de détails sur le Scanner dans l'exercice 7.2.1 (partie V.).

III. Pour obtenir un jeu qui fonctionne

  1. Tous les éléments nécessaires sont désormais réunis, il ne manque plus dans la classe Game qu'un attribut aParser (objet qu'il ne faudra pas oublier de créer dans le constructeur) et une procédure play()sans paramètre qui devra lire répétitivement des commandes au clavier et les exécuter jusqu'à ce qu'on tape "quit".
    Pour cela, elle devra :
  2. Afficher le message de bienvenue.
  3. Initialiser une variable booléenne vFinished à faux pour signifier qu'on ne veut pas quitter le jeu.
  4. TANT QUE cette variable est fausse, faire 2 choses :
    a) Récupérer dans une variable de type Command la commande tapée au clavier.
    b) Mettre dans vFinished le résultat de l'exécution de la commande.
    + Pour exprimer un 'TANT QUE' en java, il suffit de le traduire en anglais : while. La syntaxe est la même que celle d'un if, c'est-à-dire que la condition doit être entre parenthèses et une seule instruction peut la suivre (sauf si on met des accolades, bien entendu).
  5. Afficher un message de fin : "Thank you for playing.  Good bye.".
  6. Vérifier maintenant que le jeu est parfaitement fonctionnel en lançant la méthode play() sur un objet Game ; ensuite, appeler cette méthode (redevenue privée) dans le constructeur.
    Ne pas hésiter à tester tous les cas.

    Ce qu'il faut retenir sur la boucle while   

    La syntaxe est identique à celle d'un if (faire bien attention de ne pas les confondre !) :
    avant...
    while ( condition ) {
      instructions
    } // while
    après...
    La boucle ci-dessus répète les instructions tant que la condition reste vraie.
    Quatre remarques :

    1. Si la condition est fausse avant d'arriver sur le while, les instructions ne seront jamais exécutées
    2. Dans tous les cas, si on se retrouve après le while, c'est que la condition est fausse.
    3. La boucle while s'utilise à chaque fois qu'on ne peut pas prévoir en rentrant dans la boucle combien de fois elle va tourner (puisqu'on ne sait pas quand la condition deviendra fausse).
    4. Dans la condition, ne pas utiliser == ou != avec des nombres, mais plutôt < <= > ou >=.

IV. Compétences à vérifier

Après les TP 3.1 & 3.2,  érifiez que vous avez acquis les compétences ci-dessous, ainsi que celles du TP1 et celles du TP2.

V. Avancement du projet

VI. Indices pour ce TP

1) Indices pour écrire la méthode quit :
- La situation normale est l'absence de second mot. Dans ce cas, se contenter de retourner vrai (pour quitter le jeu).
- Dans le cas contraire, afficher un message et retourner faux (pour ne pas quitter le jeu).

2) Indices pour écrire la méthode processCommand :
- Comprendre la nature de ce qui lui est passé en paramètre.
- Traiter le cas où la commande est inconnue : une fonction écrite dans un exercice précédent nous permet de le savoir, il faut afficher un message et terminer la fonction (en indiquant qu'on ne veut pas quitter le jeu => retourner faux).
- Mémoriser le mot de commande à tester.
- Tester chaque mot de commande pour exécuter la bonne commande en appelant la méthode correspondante, et retourner faux (sauf la commande quit qui doit retourner le résultat booléen de la fonction quit).
- À la fin de ces tests, si vous n'avez détecté aucun mot de commande valide, c'est que vous avez fait une erreur : soit isUnknown() ne fonctionne pas bien, soit ces tests ne sont pas bons.
Choisissez bien l'enchaînement des if ou des if/else, et rappelez-vous que les chaînes de caractères sont des objets !

Si vous n'arrivez toujours pas à terminer ces exercices (notamment en travail personnel), demandez de l'aide sans attendre.
La séance Résa 3.2 est obligatoire pour tous ceux qui n'ont pas terminé les TP 3.1 & 3.2.
 
Fichier java CommandWordsTest.java
Fichier java Parser.java