Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de référence

Sur l'exercice de M@teo21 que j'ai poussé un peu plus loin

Sujet résolu
    17 mars 2008 à 14:33:48

    Bonjour à tous cher zéros !

    Alors voilà, je débute en C++, et je suis en train de faire l'exercice du RPG. J'ai fait tout ce que proposait M@teo21, et quand j'ai compilé tout marchait très bien :D

    Maintenant, j'ai voulu rendre le programme plus intéressant, en permettant à l'utilisateur de pouvoir intéragir avec le programme via cin, jusqu'à ce que l'un des 2 combattants n'ait plus de points de vie. Et me voilà avec un gros problème... voilà tout d'abord le code en question :

    main.cpp


    1. int numAttaquant = 1, numDefenseur = 2;
    2.     while (personnage1.estVivant() && personnage2.estVivant())
    3.     {
    4.         Personnage &attaquant = ("personnage" + numAttaquant);
    5.         Personnage &defenseur = ("personnage" + numDefenseur);
    6.         cout << attaquant.getName() << ", A toi de commencer !" << endl;
    7.         string typeAttaque;
    8.         cout << "Que veux-tu faire comme attaque ? (choix : magique - tranchante)" << endl;
    9.         cin >> typeAttaque;
    10.         attaquant.attaquer(defenseur, typeAttaque);
    11.         cout << "Vlam ! " << attaquant.getName() << " a porté une attaque " << typeAttaque;
    12.         cout << " mortelle, et " << defenseur.getName() << " se voit infliger des dégats." << endl << endl;
    13.         defenseur.afficherEtat();
    14.         cout << endl << endl;
    15.         if (numAttaquant == 1)
    16.         {
    17.                 numAttaquant = 2;
    18.                 numDefenseur = 1;
    19.         }
    20.         else
    21.         {
    22.                 numAttaquant = 1;
    23.                 numDefenseur = 2;
    24.         }
    25.     }



    Le problème vient des lignes 4 et 5 .. Effectivement, chaque tour, l'attaquant change de personnage.. donc je dois faire une référence ou un pointeur vers le personnage qui attaque, de même pour le personnage qui défend.
    La référence attaquant pointera à tour de rôle sur personnage1 et personnage2 à chaque passage dans la boucle while..

    J'imagine que c'est vraiment simple, mais le noob que je suis n'arrive pas à saisir la subtilité :-°

    Si vous pouviez me corriger, en m'expliquant rapidement le pourquoi du comment, je vous en serais extrèmement reconnaissant :)

    Merci à l'avance !!!
    • Partager sur Facebook
    • Partager sur Twitter
      17 mars 2008 à 15:22:38

      Non les références ne peuvent pas être utilisées ainsi... ce que tu pourrais faire c'est une fonction qui prendre en paramètres par référence l'attaquant et l'attaqué et faire les action de "l'attaque"... Avec un simble booléen ou un modulo sur le nombre de tour tu décide quel personnage attaquera.


      en passant :
      1. MaClasse & ref_obj = ( "blabla" + num );

      C'est supposé faire quoi? On est pas en PHP ou en JavaScript!
      • Partager sur Facebook
      • Partager sur Twitter
        17 mars 2008 à 15:28:27

        effectivement, j'ai souvent tendance à essayer des méthodes que je connais d'autres langages pour parvenir à mes fins X_X

        Merci pour l'explication, je devrais m'en sortir :)

        • Partager sur Facebook
        • Partager sur Twitter
          17 mars 2008 à 16:39:40

          Et pourquoi pas coupler les deux techniques ? Ca pourrait faire joli :)
          1. unsigned tour = 0;
          2. while ( ... ) {
          3.     Personnage & attaquant = (tour % 2 ? perso1 : perso2);
          4.     Personnage & defenseur = (tour % 2 ? perso2 : perso1);
          5.     //... Action !
          6.     tour++;
          7. }

          Je reconnais que c'est peut-être pas très performant, mais ça minimise les changements de code !
          Ou alors, autrement plus brutal
          1. Personnage & attaquant = perso1;
          2. Personnage & defenseur = perso2;
          3. while ( ... ) {
          4.     // ... Action !
          5.     Personnage & ancien_attaquant = attaquant;
          6.     attaquant = defenseur;
          7.     defenseur = ancien_attaquant;
          8. }


          J'avoue que c'est vraiment juste histoire de dire quoi :)
          • Partager sur Facebook
          • Partager sur Twitter
            17 mars 2008 à 16:57:09

            Citation : groscask

            Et pourquoi pas coupler les deux techniques ? Ca pourrait faire joli :)

            1. unsigned tour = 0;
            2. while ( ... ) {
            3.     Personnage & attaquant = (tour % 2 ? perso1 : perso2);
            4.     Personnage & defenseur = (tour % 2 ? perso2 : perso1);
            5.     //... Action !
            6.     tour++;
            7. }


            Je reconnais que c'est peut-être pas très performant, mais ça minimise les changements de code !
            Ou alors, autrement plus brutal

            1. Personnage & attaquant = perso1;
            2. Personnage & defenseur = perso2;
            3. while ( ... ) {
            4.     // ... Action !
            5.     Personnage & ancien_attaquant = attaquant;
            6.     attaquant = defenseur;
            7.     defenseur = ancien_attaquant;
            8. }





            La deuxième technique nécessite un tas de copie de données inutiles et en plus attaquant et defenseur seront 100% égaux après le premier tour de boucles.

            la première technique donne la même chose qu'avec une fonction mais sans fonction, code non modularisé.


            Exemple d'une ébauche de code modularisé... (Les saisies n'étant pas validées)
            1. // interaction_attaque
            2. // Gère les actions d'un tour de combat (une attaque).
            3. // l'Utilisateur peut décider les action du personnage attaquant.
            4. // Informe l'utilisateur sur l'issue du combat.
            5. void interaction_attaque( Personnage & attaquant, Personnage & defenseur )
            6. {
            7.     string typeAttaque;
            8.     cout << attaquant.getName() << ", A toi de commencer !" << endl;
            9.     cout << "Que veux-tu faire comme attaque ? (choix : magique - tranchante)" << endl;
            10.     cin >> typeAttaque;
            11.     attaquant.attaquer(defenseur, typeAttaque);
            12.     cout << "Vlam ! " << attaquant.getName() << " a porté une attaque " << typeAttaque;
            13.     cout << " mortelle, et " << defenseur.getName() << " se voit infliger des dégats." << endl << endl;
            14.     defenseur.afficherEtat();
            15.     cout << endl << endl;
            16. }
            17. // combat
            18. // Gère l'ordre d'action de deux Personnages lors d'un combat.
            19. // Seul la mort d'un Personnage peut arrêter un combat
            20. void combat( Personnage & p1, Personnage & p2 )
            21. {
            22.     bool drapeau_tour = false;
            23.     while( p1.estVivant() && p2.estVivant() )
            24.     {
            25.         if( drapeau_tour )
            26.             interaction_attaque( p1, p2 );
            27.         else
            28.             interaction_attaque( p2, p1 );
            29.         drapeau_tour = !drapeau_tour;
            30.     }
            31. }
            • Partager sur Facebook
            • Partager sur Twitter
              17 mars 2008 à 17:16:43

              Copie de données inutiles ? Alors que je ne fais que copier des références ? C'est un bête swap dans le fond... Donc des références ou des pointeurs, je ne vois pas où sont les copies inutiles...

              Si tu peux m'éclairer, je suis preneur !
              Quoiqu'il en soit : j'ai déjà mentionné que c'était du code "histoire de" ;)
              • Partager sur Facebook
              • Partager sur Twitter
                17 mars 2008 à 18:13:52

                ng", avec des espaces, auquel cas il y a une boucle infinie..

                J'imagine qu'il considère que "Glaive" est le nom, et cherche jusqu'à la fin des temps ce que peux être " long"...
                Comment corriger ce problème ?

                Merci beaucoup de vos interventions :Dss="code2 cpp">
                1. #include <iostream>
                2. #include <string>
                3. #include "Personnage.h"
                4. using namespace std;
                5. void tourDeJeu(Personnage &attaquant, Personnage &defenseur);
                6. int main()
                7. {
                8.     cout << "##########################################" << endl;
                9.     cout << "# Bienvenue dans l'arène des gladiateurs #" << endl;
                10.     cout << "##########################################" << endl << endl;
                11.     string nomPersonnage1, nomPersonnage2;
                12.     cout << "Premier combattant :"<< endl << "Quel est le nom de votre personnage ? ";
                13.     cin >> nomPersonnage1;
                14.     cout << "Deuxième combattant :"<< endl << "Quel est le nom de votre personnage ? ";
                15.     cin >> nomPersonnage2;
                16.     cout << endl << endl;
                17.     Personnage personnage1(nomPersonnage1), personnage2(nomPersonnage2,"Epée aiguisée",20);
                18.     int nombreDeTours = 0;
                19.     while (personnage1.estVivant() && personnage2.estVivant())
                20.     {
                21.         if (nombreDeTours % 2 == 0)
                22.         {
                23.                 tourDeJeu(personnage1, personnage2);
                24.         }
                25.         else
                26.         {
                27.                 tourDeJeu(personnage2, personnage1);
                28.         }
                29.         nombreDeTours++;
                30.     }
                31.     if (personnage1.estVivant())
                32.     {
                33.         cout << personnage1.getNom() << " est le vainqueur du duel !!!!!!";
                34.         cout << " Félicitations à toi, noble guerrier !" << endl << endl;
                35.     }
                36.     else if (personnage2.estVivant())
                37.     {
                38.         cout << personnage2.getNom() << " est le vainqueur du duel !!!!!!";
                39.         cout << " Félicitations à toi, noble guerrier !" << endl << endl;
                40.     }
                41.     cout << "Etat final des 2 combattants :" << endl;
                42.     cout << "------------------------------" << endl << endl;
                43.     personnage1.afficherEtat();
                44.     personnage2.afficherEtat();
                45.     cout << endl;
                46.     return 0;
                47. }
                48. void tourDeJeu(Personnage &attaquant, Personnage &defenseur)
                49. {
                50.         attaquant.regenererMana();
                51.         cout << attaquant.getNom() << ", A toi de jouer !" << endl;
                52.         cout << "Voilà ton profil :" << endl;
                53.         cout << "------------------" << endl;
                54.         attaquant.afficherEtat();
                55.         bool erreur;
                56.         do
                57.         {
                58.                 cout << "Que veux-tu faire ? (choix : attaquer - boirePotionDeVie - changerArme)" << endl;
                59.                 string choixTour;
                60.                 cin >> choixTour;
                61.                 if (choixTour == "attaquer")
                62.                 {
                63.                         string typeAttaque;
                64.                         cout << "Que veux-tu faire comme attaque ? (choix : magique - tranchante)" << endl;
                65.                         cin >> typeAttaque;
                66.                         attaquant.attaquer(defenseur, typeAttaque);
                67.                         cout << "Vlam ! " << attaquant.getNom() << " a porté une attaque " << typeAttaque;
                68.                         cout << " mortelle, et " << defenseur.getNom() << " se voit infliger des dégats.";
                69.                         cout << endl << endl;
                70.                         defenseur.afficherEtat();
                71.                         erreur = false;
                72.                 }
                73.                 else if (choixTour == "boirePotionDeVie")
                74.                 {
                75.                         attaquant.boirePotionDeVie(20);
                76.                         attaquant.afficherEtat();
                77.                         erreur = false;
                78.                 }
                79.                 else if (choixTour == "changerArme")
                80.                 {
                81.                         cout << "Quelle arme voulez-vous prendre ? ";
                82.                         string nomArme;
                83.                         cin >> nomArme;
                84.                         cout << endl << "Combien de dégats infligés par l'arme ? ";
                85.                         int nbDegats;
                86.                         cin >> nbDegats;
                87.                         attaquant.changerArme(nomArme,nbDegats);
                88.                         attaquant.afficherEtat();
                89.                         erreur = false;
                90.                 }
                91.                 else
                92.                 {
                93.                         cout << "Vous avez rentré un mauvais choix, reessayez !" << endl << endl;
                94.                         erreur = true;
                95.                 }
                96.                 cout << endl << endl;
                97.         } while (erreur);
                98. }


                Mais effectivement, suite à vos interventions, je me rend compte que je pourrais faire une autre fonction avec la boucle while pour rendre le code plus lisible (d'ailleurs j'ai 0 commentaires, faudra que j'en fasse quelques uns histoire de :lol: )

                Merci beaucoup en tout cas :)


                PAR CONTRE :

                J'ai un autre problème, et ne sais pas vraiment comment corriger cela...
                Lorsque je veux changer d'arme, le programme me demande le nom de la nouvelle arme. Ce nom est récupéré avec cin, et placé dans la variable nomArme. Le problème surgit lorsque j'écris un nom tel que "Glaive lo
                • Partager sur Facebook
                • Partager sur Twitter
                  17 mars 2008 à 18:38:06

                  Citation : groscask

                  Copie de données inutiles ? Alors que je ne fais que copier des références ? C'est un bête swap dans le fond... Donc des références ou des pointeurs, je ne vois pas où sont les copies inutiles...

                  Si tu peux m'éclairer, je suis preneur !
                  Quoiqu'il en soit : j'ai déjà mentionné que c'était du code "histoire de" ;)



                  Les références sont initialisé lors de leur déclaration et ne peuvent pas "référer" un autre zone mémoire lors du déroulement... Ce que tu fais ici c'est appeler l'opérateur d'affectation de la classe.

                  Exemple :
                  1. int main()
                  2. {
                  3.     int a = 0;
                  4.     int b = 10;
                  5.     // Déclaration de références pour que l'exemple ressemble au code proposé
                  6.     int & ra = a;
                  7.     int & rb = b;
                  8.     // "référence de swap" (comme proposé)
                  9.     int & rt = rb;
                  10.     rb = ra;
                  11.     ra = rt;
                  12.     std::cout << "a : " << a << "\nb : " << b << std::endl;
                  13.     return 0;
                  14. }


                  sortie :
                  a : 0
                  b : 0



                  Pourtant, selon toi, a devrait valoir 10. En fait à la ligne 12 rb qui réfère à b copie la valeur de ra (référence de a, soit 0). À ligne suivante rt toujours référé à rb qui réfère toujours à b qui vaut maintenant 0 et a affecte cette valeur. a et b ont la même valeur et celle que contenait b est perdue.


                  Citation : Fandekasp

                  J'ai un autre problème, et ne sais pas vraiment comment corriger cela...
                  Lorsque je veux changer d'arme, le programme me demande le nom de la nouvelle arme. Ce nom est récupéré avec cin, et placé dans la variable nomArme. Le problème surgit lorsque j'écris un nom tel que "Glaive long", avec des espaces, auquel cas il y a une boucle infinie..

                  J'imagine qu'il considère que "Glaive" est le nom, et cherche jusqu'à la fin des temps ce que peux être " long"...
                  Comment corriger ce problème ?



                  Je viens d'en parler dans un autre sujet... utilise getline()!

                  1. void changerArme( Personnage & perso )
                  2. {
                  3.     std::string nomArme;
                  4.     std::cout << "Nom de la nouvelle arme?" << std::endl;
                  5.     getline( cin, nomArme );
                  6.     perso.setNomArme( nomArme );
                  7.     std::cout << "la nouvelle arme de " << perso.getName() << " est un(e) " << nomArme << std::endl;
                  8. }


                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 mars 2008 à 18:46:25

                    Pour les espaces j'ai trouvé dans la doc ça :

                    Tu fais un getline(cin, variableString) et c'est tout ! ;)

                    Pour récupérer un nombre et que vous ne voulez pas que quelqu'un, au lieu de mettre un nombre entier, met quelque chose d'autre qui causera une boucle inconditionelle, tu fais :

                    1. using namespace std;
                    2. /* ... */
                    3. int entier = 0;
                    4. string nbEntier;
                    5. /* ... */
                    6. getline(cin, nbEntier);
                    7. stringstream(nbEntier) >> entier; /* Transforme tous les nombres dans la chaîne en entiers et les  met dans ta variable ! */


                    Ainsi, tu n'auras plus de boucle interminable ! ^^

                    A plus !
                    • Partager sur Facebook
                    • Partager sur Twitter
                      17 mars 2008 à 19:15:34

                      Ah super !!!

                      Merci beaucoup :)

                      Va falloir que j'apprenne à chercher plus efficacement dans la doc lol


                      A bientôt :D
                      • Partager sur Facebook
                      • Partager sur Twitter
                        17 mars 2008 à 20:30:58

                        J'ai oublié de te dire ça : il faut inclure <sstream> pour que ça marche !
                        @+
                        • Partager sur Facebook
                        • Partager sur Twitter
                          17 mars 2008 à 20:52:42

                          oué j'avais une erreur, mais j'ai vite trouvé le problème ^^


                          Parcontre, j'ai un problème étrange concernant le getline().

                          Je l'ai fait 2 fois :
                          - 1 fois pour demander le nom de l'arme
                          - 1 fois pour demander le nombre de dégats infligés par l'arme (j'y ajoute un stringstream après pour convertir en int)

                          Le problème est qu'il ne s'arrête pas pour me demander le nom de l'arme, mais me demande le nombre de dégats o_O


                          changerArme
                          Quelle arme voulez-vous prendre ? 
                          Combien de dégats infligés par l'arme ? 40


                          Voilà le code :

                          1. cout << "Quelle arme voulez-vous prendre ? ";
                          2. string nomArme;
                          3. getline (cin, nomArme);
                          4. cout << endl << "Combien de dégats infligés par l'arme ? ";
                          5. int nbDegats;
                          6. string nombre;
                          7. getline (cin, nombre);
                          8. stringstream(nombre) >> nbDegats;
                          9. attaquant.changerArme(nomArme,nbDegats);



                          Qu'en pense-tu ? n'est-ce pas vraiment étrange ?
                          • Partager sur Facebook
                          • Partager sur Twitter
                            17 mars 2008 à 21:01:48

                            Merci beaucoup MatteX pour tes précisions...
                            Dans ma tête, les références n'étaient que des pointeurs améliorés, là pour la syntaxe... Je prendrai garde à l'avenir de ne pas les considérer comme tel ;)
                            • Partager sur Facebook
                            • Partager sur Twitter
                              17 mars 2008 à 21:07:45

                              Est-ce que tu fais d'autres saisies avec cin avant le getline. Car si ton buffer contient un '\n' c'est normal qu'il ne demande pas le nom de l'arme
                              • Partager sur Facebook
                              • Partager sur Twitter
                                17 mars 2008 à 23:02:23

                                Ah effectivement c'est le cas, je fais plusieurs cin avant... mais comment faire pour vider le buffer alors ?


                                edit:
                                Bon j'ai remplacé tous les cin pour des getline(), donc je n'ai plus de problèmes.. mais si vous avez d'autres suggestions pour "vider" le buffer, je suis preneur :)
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  18 mars 2008 à 15:09:33

                                  réponse @ FAQ C++ de developpez.com
                                  (Lien dans ma signature)
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Problème de référence

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown