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

 C++ Discussion :

Pti dev, aide pour finalisation


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 66
    Par défaut Pti dev, aide pour finalisation
    Bonjour

    Etudiant en bts, je vais bientôt passer mes PTI, et voulait savoir si quelques bonnes âmes pouvaient jeter un œil sur mon "programme" en c++.

    Déjà, voila un .rar avec tout ce qu'il faut dedans.
    http://garrethvfou.free.fr/Meujeu/PT...ymorphisme.rar

    Alors, ce qui m'intéresse, c'est de savoir :
    - Si je respecte bien l'encapsulation,
    - Si il y a du code inutile et redondant
    - Si je pourrais mettre + de commentaires (là il y en a quasiment pas, mais je vois pas trop où en mettre, le programme restant relativement simple)
    - Me rappeler pourquoi les classes Magiciens et Guerrier sont en virtual, mais pas la classe Personnage qui pourtant, le devrait aussi, non ? Ou alors, pourquoi ne peut on pas mettre Magicien et Guerrier en normal aussi ?
    - Si vous voyez tout autre chose qui pourrait m'aider ...


    Voila, merci beaucoup d'avance ! Je reste à votre disposition pour toutes questions

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 188
    Par défaut
    Citation Envoyé par Xenofexs Voir le message
    - Me rappeler pourquoi les classes Magiciens et Guerrier sont en virtual, mais pas la classe Personnage qui pourtant, le devrait aussi, non ? Ou alors, pourquoi ne peut on pas mettre Magicien et Guerrier en normal aussi ?
    Heu si tu les as mis en virtual tu doit bien avoir une raison, non ?

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 66
    Par défaut
    Biensur, mais c'était il y a quelque temps. C'est pour pouvoir utiliser la fonction monChoix, qui transmet deux paramètres qui sont des objets.
    Sans le polymorphisme, je ne pouvais pas.
    Mais si comme vous devez le remarquer, si on me pose la question directement à l'examen, mon explication sera un peu soft ... un petit rappel me serait bien utile .
    Surtout comme je l'ai marqué, pourquoi Personnage n'a pas besoin d'être virtualisé ? Et ce que j'ai fait, du coup, ça respecte toujours l'encapsulation ?
    Si vous pouviez DL le source pour jeter un oeil, ça serait sympa

    Merci d'avance

  4. #4
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Citation Envoyé par Xenofexs Voir le message
    - Me rappeler pourquoi les classes Magiciens et Guerrier sont en virtual, mais pas la classe Personnage qui pourtant, le devrait aussi, non ? Ou alors, pourquoi ne peut on pas mettre Magicien et Guerrier en normal aussi ?
    Je ne sais pas trop ce que tu entends pas "classe virtuelle", mais je suppose que tu fais allusion au mot clé "virtual" qui l'on voit ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Guerrier : virtual public Personnage
    {
        ...
    };
    Ce mot clé s'applique ici non pas à la classe Guerrier, mais à la classe Personnage.
    Tu indique au compilateur que tu veux faire un héritage virtuel (un peu d'anglais, ça fait pas de mal, pas trouvé dans la FAQ C++ de Developpez).
    Dans le cadre de ton programme, c'est nécessaire pour que la classe Joueur puisse fonctionner correctement. En effet, son diagramme d'héritage a la forme d'un losange (ou d'un diamant, c'est comme on veut), et ça créé des ambiguïté pour le compilateur.
    Si tu lis l'anglais, c'est bien mieux expliqué dans le lien ci dessus.

    Mais je ne suis pas sûr qu'il soit nécessaire de ré-écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Joueur : virtual public Personnage, public Guerrier, public Magicien
    {
        ...
    };
    Ceci devrait suffire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Joueur : public Guerrier, public Magicien
    {
        ...
    };
    Par contre, la classe Personnage dont tu hérite dans Guerrier et Magicien n'a pas de destructeur virtuel (en français cette fois), et ça c'est assez grave.

    Maintenant place au pinaillage :

    D'abord, l'indentation n'est pas toujours top. En lisant main.cpp, j'ai d'abord cru que tu avais écris un while() en dehors de toute fonction, avant de me rendre compte que c'était juste une erreur d'indentation. Ca ne tue pas, mais c'est quand même gênant pour qui ne connais pas le code.

    Ensuite, quand une méthode retourne un std::string membre de la classe (ou tout autre type d'objet lourd à copier), on préfère le retourner par référence constante plutôt que par valeur. Ca évite des copies inutile est c'est totalement transparent pour l'utilisateur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Personnage
    {
            ...
            const std::string& getType();
            const std::string& getNom();
            ...
    };
    On peut aller plus loin, et déclarer ces fonctions comme constantes, car elles ne modifient pas l'objet Personnage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Personnage
    {
            ...
            void coupDePoing(Personnage &cible) const;
            bool estVivant() const;
            const std::string& getType() const;
            const std::string& getNom() const;
            ...
    };
    Pareil pour :
    • Joueur::afficherEtat()
    • Guerrier::grosCoupDepee()
    • Magicien::bouleDeFeu()


    Autre détail : les variables globales. Dans ton cas les deux variables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int i=1;
    bool boucle=true;
    ... n'ont strictement rien à faire dans la portée globale.
    Tu ne les utilises nulle part ailleurs que dans la fonction main(), donc autant les déclarer là bas, c'est plus sûr :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        int i=1;
        bool boucle=true;
     
        ...
    }
    Enfin, vraiment un détail :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while ((Edward.estVivant()==true) && (Andristin.estVivant()==true) && boucle==true) {
        ...
    }
    ... ça se simplifie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while (Edward.estVivant() && Andristin.estVivant() && boucle) {
       ...
    }

  5. #5
    Membre expérimenté
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 188
    Par défaut
    Pour l'héritage virtuel la FAQ l'explique très bien.

    Au niveau de la conception déjà la classe joueur me fais un peu peur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    class Joueur : virtual public Personnage, public Guerrier, public Magicien
    Premièrement Guerrier et Magicien hérite déjà de Personnage donc pourquoi l'hérité une troisième fois ? (de plus si tu lis la FAQ tu verras que Guerrier et Magicien devrai être, eux, hérité en virtual).

    Mais surtout ton héritage signifie que joueur est à la fois un Guerrier et un Magicien (ce qui n'est pas le cas).

    la déclaration de tes joueur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Joueur Andristin ("Andristin", "Guerrier", 50);
    Joueur Edward ("Edward", "Magicien", 50);
    Devrai ressemblé plutôt à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Personnage *Andristin  = new Guerrier("Andristin", 50);
    Personnage *Edward = new Magicien("Edward ", 50);
    Dans ton code tu n'utilise pas du tout le polymorphisme alors qu'il te serai très utile dans ton cas.

    Pour cela il faut que tu n'aies plus a utiliser getType() (sauf éventuellement pour afficher des info).

    EDIT: grillé. reste qu'il y a (d'après moi) un problème de conception.

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut, et bienvenue sur le forum.

    1- Le constructeur de personnage ne prenant pas d'argument est, au mieux inutile, au pire, dangereux...:

    Comme il n'y a aucun moyen de modifier le nom du personnage (ce qui est quelque part logique ), tu ne devrais pas permettre de... créer un personnage qui n'a pas au minimum un nom

    (il en va de même pour les classes magicien et guerrier )

    2- Si je suis d'accord avec le fait qu'un magicien ou qu'un guerrier est un personnage, je ne suis pas particulièrement d'accord avec l'idée de faire hériter joueur de ces deux classes: un joueur n'est pas un magicien ou un guerrier, mais un joueur est représenté par un personnage qui peut être soit un magicien soit un guerrier (si c'est le prof qui a indiqué qu'un joueur devait hériter de l'un ou de l'autre, tu peux lui dire que sa conception est foireuse de ma part )

    Comme le joueur peut, à peu près à tout moment, décider d'abandonner un personnage afin d'en créer un autre, et que l'on ne peut pas savoir à la base quel type il décidera de créer, il faudrait avoir dans la classe joueur:
    • une chaine de caractère (std::string) représentant le pseudo du joueur, et
    • une méthode permettant de le récupérer (c'est la seule information qui sera nécessaire pour la création du joueur)
    • un pointeur sur "personnage", et deux fonctions permettant de les gérer: creerPersonnage(std::string const & nom, type) et detruirePersonnage(), la première ne pouvant agir que... si le joueur n'a pas encore (ou plus) de personnage


    Si tu pars sur cette base (beaucoup plus saine), il n'y a plus aucun intérêt à faire en sorte d'avoir un héritage virtuel

    3- De prime abord, je n'utiliserais pas une chaine de caractères pour représenter le type de personnage, mais plutôt une énumération, par exemple, et je ne vois, pour être honnête, pas l'intérêt de la fonction permettant de récupérer le type...

    Les raisons pour laquelle j'éviterais la chaine de caractère sont:
    • que tu va permettre la création d'un nombre finis de types différents (pour l'instant, tu n'as que "guerrier" et "magicien", mais, si tu décide de permettre d'autres type ("voleur","paladin",...), tu voudra veiller à... ce que seuls ces types soient utilisés )
    • la comparaison de chaines de caractères est sans doute ce qui prend le plus de temps: il faut comparer chaque caractère avec celui se trouvant à la même place dans la deuxième chaine, jusqu'à trouver une différence
    • les tests à choix multiple (switch... case) ne fonctionnent qu'avec... des valeurs numériques entières. Pour l'instant, un if... else suffit, mais, si tu rajoute des types de personnage, le switch case sera bien plus lisible et sans doute plus efficace sur un grand nombre de types différents

    La raison pour laquelle je ne suis pas persuadé de l'intérêt d'une fonction permettant de récupérer le type de personnage est, simplement, que pour la plus grande partie du jeu, tu va considérer tes magiciens et tes guerriers comme... des personnages, et ils seront (principalement) utilisé comme tels: que ce soit un magicien ou un guerrier, il pourra attaquer et subir des dégâts (et, qu'il s'agisse d'un guerrier ou d'un magicien, s'il n'a pas d'arme, il risque encore bien d'utiliser... le coup de poing )

    Par contre, il serait sans doute intéressant d'avoir une fonction "attaquer" dans la classe de base.

    Cette fonction serait virtuelle et redéfinie de manière à appeler le gros coup de poing du guerrier ou la boule de feu du magicien, en fonction du perso

    Il est vrai que, dans certains cas, tu devras peut être effectivement disposer du type réel du personnage.

    Dans le cas où le seul polymorphisme est insuffisant (tu peux avoir une fonction virtuelle "équiper" qui est redéfinie pour le guerrier et pour le magicien de manière à vérifier que tu n'essaye pas d'équiper un objet destiné à "l'autre type" de personnage ), le pattern "visiteur" te viendra sans doute bien à point
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 66
    Par défaut
    Déjà, merci beaucoup pour vos réponses, j'ai commencé les changement et me suis replongé dans vos liens FAQ C++.

    Pour le site, oui et non. J'ai repris uniquement la base (soit le fait d'avoir une classe Personnage, Magicien et Guerrier) mais c'est tout.
    Sur le site, pas de polymorphisme, pas de classe joueur donc, pas de "round" ni de choix pour le déroulement du combat. etc.

    Pour ce qui est de la conception du programme ... je sais pas, je n'ai pas eu de cours, je pensais que c'était pas trop mal. Hélas je n'ai pas le temps de tout refaire, là. Mais merci pour l'info, je m'y replongerai aussi pour faire quelque chose de correct après l'épreuve (pour ma propre connaissance, quoi )

    Pour le destructeur, il est bien nécessaire ? Car, comme le souligne atttchoum, je n'utilise pas de " new " pour créer mes objets.

    Pour les std::string, quel intérêt de les passer par constantes et références? Qu'est ce que ça fait concrètement ? Et aussi, comment l'écrire dans le .cpp ?


    Encore merci en tout cas, j'ai corrigé les petits trucs, genre indentation, simplification des " == true " etc

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Xenofexs Voir le message
    Pour le destructeur, il est bien nécessaire ? Car, comme le souligne atttchoum, je n'utilise pas de " new " pour créer mes objets.
    Un constructeur est nécessaire dés le moment où... tu veux construire un objet, que ce soit en utilisant l'allocation dynamique de la mémoire ou non

    car, même si tu écris un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    joueur j1("arthur","magicien");
    tu ... appelle un constructeur
    Pour les std::string, quel intérêt de les passer par constantes et références? Qu'est ce que ça fait concrètement ? Et aussi, comment l'écrire dans le .cpp ?
    Il est préférable de passer les types définis par l'utilisateur (std::string est un type défini par l'utilisateur, même s'il est fourni par le standard ) par référence afin d'éviter les copies inutiles qui peuvent demander beaucoup de temps ou de ressources.

    Il est préférable de passer un objet constant chaque fois qu'il ne doit pas être modifié pour assurer la "const correctness".

    De plus, l'utilisation de référence constante permet d'utiliser des "variables anonyme temporaire" (le code que je donne en exemple crée une variable de type std::string anonyme contenant "arthur" qui n'existe que... pour la durée de l'exécution du constructeur )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 66
    Par défaut
    je viens de voir les réponses de koala01.

    Déjà, merci à toi aussi pour ta réponse
    La conception ne vient pas d'un prof (quoi que mon prof de Php m'y a aidé un peu) car je n'ai pas eu de prof objet (java, C++), tout simplement.

    Le but du programme n'est pas de pouvoir créer dynamiquement (ni de supprimer) des personnages, donc pas besoin de récupérer la saisi de l'utilisateur ou autre.

    Citation Envoyé par koala01 Voir le message
    Un constructeur est nécessaire dés le moment où... tu veux construire un objet, que ce soit en utilisant l'allocation dynamique de la mémoire ou non

    car, même si tu écris un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    joueur j1("arthur","magicien");
    tu ... appelle un constructeur
    Je parlais du destructeur. Il n'est pas nécessaire uniquement lorsqu'on utilise un new ?

    Pour le getType, le fait est que je ne sais pas comment "comparer" des objets.
    Je ne sais pas comment faire, en gros : if cet objet est de la classe Magicien, faire ...

    En tout cas, tu m'as convaincu pour l'utilisation de valeurs numériques. En effet, si le jeu devait se développer, et qu'il y avait 50 classes, ce serait beaucoup plus pratique.


    Pour voir si mon esprit est tordu, dans ma tête, je vais vous dire pourquoi j'ai fait mon code comme ça : pour que tous les Personnages aient certains attributs identiques, comme des points de vie, des points de capacité, un nom.
    Que ces personnages puissent être guerrier ou magicien
    Et pour utiliser ma fonction monChoix (nomClasse &objet, nomClasse, &objet) il fallait que je fasse la virtualisation de Personnage puis guerrier et magicien.

    Comme ça, je passe dans monChoix que des joueurs. (Joueur &etre, Joueur, &cible)

    C'est pas défendable ?

  10. #10
    Membre expérimenté
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 188
    Par défaut
    Citation Envoyé par Xenofexs Voir le message
    Je parlais du destructeur. Il n'est pas nécessaire uniquement lorsqu'on utilise un new ?
    non, que l'objet sois créé dynamiquement (avec new) ou non il sera toujours à un moment ou à un autre détruit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void f(){
        maClasse o(arg1, arg2);//appel au constructeur
        /*
         des instruction
         ...
         */
    }//arrivé a la fin de la fonction l'objet o est détruit => on appel son destructeur
    Citation Envoyé par Xenofexs Voir le message
    Pour le getType, le fait est que je ne sais pas comment "comparer" des objets.
    Je ne sais pas comment faire, en gros : if cet objet est de la classe Magicien, faire ...
    Tu n'as justement pas à différentier le magicien et le guerrier chacun est un personnage qui possède les même actions (une attaque au poing ou spéciale)
    cependant selon le type "réel" du personnage l'action effectuée sera différente.

    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
     
     
    class Personnage
    {
        public:
        //...
            void coupDePoing(Personnage &cible);
            virtual void attaqueSpeciale(Personnage &cible) = 0; //je sais que mes personnages auront un coup speciale mais je ne le connais pas
        //...
    };
     
    class Guerrier : public Personnage
    {
        //...
            void attaqueSpeciale(Personnage &cible){
                //je sais que je suis un guerrier => j'envois un coup d'épée
            }
        //...
     
        protected:
     
    };
     
    class Magicien : public Personnage
    {
    //...
            void attaqueSpeciale(Personnage &cible){
                //je sais que je suis un Magicien => j'envois une boule De Feu
            }
    //...
     
    };
     
    int main(){
    //...
    Personnage *Andristin  = new Guerrier("Andristin", 50);
    Personnage *Edward = new Magicien("Edward ", 50);
     
    Andristin->attaqueSpeciale(*Edward );//appelle attaqueSpeciale de la classe Guerrier
    Edward ->attaqueSpeciale(*Andristin  );//appelle attaqueSpeciale de la classe Magicien
    Bien que Andristin et Edward soit tout deux des personnages (enfin des pointeurs vers un personnage) grâce au polymorphisme ils ont effectué des actions différentes avec la même fonction appelée.

    ps : si tu ne comprend pas la signature

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    virtual void attaqueSpeciale(Personnage &cible) = 0;
    alors renseigne toi sur les fonction virtuelles et virtuelles pures.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 66
    Par défaut
    Ok, donc j'oublie totalement la classe Joueur alors.
    Je vais voir pour changer ça, ça revient à presque tout revoir mais tant mieux, je me rends compte que mon prog était bien loin d'un vrai codage objet.

    J'ai encore du mal, avec l'objet...

    Merci en tout cas, et merci pour les cours de C+++ ! Si vous avez d'autres remarques, n'hésitez pas, j'éditerai ou répondrai après avoir fait les modifs

  12. #12
    Membre expérimenté
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 188
    Par défaut
    Citation Envoyé par Xenofexs Voir le message
    Ok, donc j'oublie totalement la classe Joueur alors.
    En tout cas de la façons dont tu l'as faite.

    Cependant faire une classe Joueur qui représenterai un joueur physique qui puisse choisir un personnage, en changer, ect... comme koala01 l'a proposé te permettra de pouvoir gérer ta partie plus clairement. (et cette fois Joueur contiendra un personnage mais n'héritera pas de la classe Personnage).

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 66
    Par défaut
    Arg, je tombe sur une erreur de linkage. J'ai regardé sur les fofo, mais n'ai pas très bien compris. Il faudrait que je change de biblio, ou quelque chose comme ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Magicien.obj||error LNK2019: symbole externe non résolu "public: __thiscall Personnage::Personnage(void)" (??0Personnage@@QAE@XZ) référencé dans la fonction "public: __thiscall Magicien::Magicien(void)" (??0Magicien@@QAE@XZ)|
    Guerrier.obj||error LNK2001: symbole externe non résolu "public: __thiscall Personnage::Personnage(void)" (??0Personnage@@QAE@XZ)|
    main.obj||error LNK2019: symbole externe non résolu "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Personnage::getType(void)" (?getType@Personnage@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) référencé dans la fonction "void __cdecl monChoix(class Personnage &,class Personnage &)" (?monChoix@@YAXAAVPersonnage@@0@Z)|
    bin\Debug\JdrSdzPourPolymorphisme.exe||fatal error LNK1120: 2 externes non résolus|
    ||=== Build finished: 4 errors, 0 warnings ===|

    S'il faut, je peux vous refiler l'intégralité du nouveau code .

    EDIT : pour plus de clarté, je pense que "citer" mon main.cpp aiderai. Je pense que les erreurs doivent venir de là, car je maitrise encore relativement mal les *, & etc.

    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    void monChoix(Personnage &etre, Personnage &cible) {
        int choix=1;
     
        while (choix==1 && cible.estVivant()) {
            cin >> choix;
            switch (choix) {
     
            case 1 :    etre.afficherEtat();
                        cout << "Retapez un choix "<<endl;
            break;
     
            case 2 :    if (etre.getType()=="Magicien") {
                            cout << "Les paumes du mage s'embrasent alors qu'il les tournes vers le guerrier, dechainant son brasier.\n " << endl;
                            etre.attaqueSpeciale(cible);
                            }
                        else {
                            cout << "Le guerrier leve son arme et la rabat avec violence et fracas. \n " << endl;
                            etre.attaqueSpeciale(cible);
                             }
            break;
     
            case 3 :    cout << etre.getNom() << " assene un coup de poing a son adversaire ! " << endl; etre.coupDePoing(cible);
     
            break;
     
            case 4 : boucle=false;
     
            break;
     
            }
        }
    }
     
    int main()
    {
        int nbRound=1;
     
        // Initialise deux Personnages
        Personnage *Andristin = new Guerrier ("Andristin", 50);
        Personnage *Edward = new Magicien ("Edward", 50);
     
     
        Andristin->afficherEtat();
        cout << endl;
        Edward->afficherEtat();
        cout << endl;
     
        cout    << "\nBienvenue dans notre arene. Vous etes un fier marionetiste qui veut voir \nlaquelle de ses deux creation est la plus forte ! \n" << endl
                << "1 pour afficher l'etat de votre personnage. \n2 pour utiliser la capacite speciale de votre personnage. \n3 pour donner un simple coup de poing.\n4 pour cesser le combat.\n " << endl;
     
        while ((Edward->estVivant()) && (Andristin->estVivant()) && (boucle)) {
            cout << "Round: " << nbRound << endl;
            cout << "Tour du Magicien: " << endl;
     
            monChoix(*Edward, *Andristin);
     
            cout << "Tour du Guerrier: " << endl;
     
            if (Andristin->estVivant()) {
            monChoix(*Andristin, *Edward);
            }
     
            nbRound++;
        }
     
        return 0;
    }

  14. #14
    Membre expérimenté
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 188
    Par défaut
    tu utilises encore if (etre.getType()=="Magicien")
    alors que tu appelles la même fonction derrière !
    Si c'est juste pour afficher du texte, place cet affichage dans la fonction attaqueSpeciale.

    Sinon pour l'erreur de linkage, il va nous falloir le code des classes pour savoir d'où ça vient.

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 66
    Par défaut
    Oui oui, le code n'est pas encore forcément très "propre", j'ai juste tenté quelques modifs...

    Enfin voila la total recompressé.
    http://garrethvfou.free.fr/Meujeu/PT...rphismeNew.rar

    Merci encore

  16. #16
    Membre expérimenté
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 188
    Par défaut
    pour l'erreur de linkage elle vient du fais que tu déclares un constructeur vide pour personnage (Personnage();) dan le .h mais que tu ne l'implémente pas dans le .cpp. Ton destructeur non plus n'est pas implémenté.

    sinon encore quelque petite chose:

    -le destructeur de personnage doit être virtuel (et implémenter !).

    -ta liste d'initialisation dans la classe Personnage n'est pas dans le bonne ordre ce qui doit faire grogner ton compilateur.

    - comme te l'a dis koala01 tes constructeurs (ou du moins celui de Personnage) vides sont inutiles.

  17. #17
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Allez, je suis trop bon (je sais), mais je vais te donner un code qui devrait fonctionner
    personnage.hpp
    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
    #ifndef PERSONNAGE_HPP
    #define PERSONNAGE_HPP
    #include <string>
    class Personnage
    {
        public:
            Personnage(std::string const & n, int pv):name_(n),pv_(pv){}
            virtual ~Personnage();
            bool estVivant() const{return pv_>0;}
            int pointDeVie() const{return pv_>0?  pv_: 0 ;}
            std::string const & name() const{return name_;}
            void coupDePoing(Personnage & p) const;
            virtual void attaqueSpeciale(Personnage & p) const = 0;
            void subitDegats(int d){pv_-=d;}
            virtual const std::string type() const = 0;
        private:
           /* les personnages ne sont ni copiables ni assignables...
            * en attendant C++11, nous nous en assurons en déclarant
            * SANS LES DEFINIR le constructeur par copie et l'opérateur 
            * d'affectation dans la visibilité privée
            */
           Personnage(Personnage const &);
           Personnage & operator=(Personnage const &);
           std::string name_;
           int pv_;
    };
    #endif
    personnage.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <personnage.hpp>
    #include <iostream>
    Personnage::~Personnage(){}
    void Personnage::coupDePoing(Personnage & p) const
    {
        std::cout<<name()<<" lance un coup de point a "<<p.name()
                 <<" et lui inflige 10 points de degats"<<std::endl;
        p.subitDegats(10);
    }
    magicien.hpp
    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
    #ifndef MAGICIN_HPP
    #define MAGICIEN_HPP
    #include <personnage.hpp>
    class Magicien : public Personnage
    {
        public:
            /* j'ai décidé de donner 150 points de vie au magicien ;) */
            Magicien(std::string const & n):Personnage(n,150){}
            virtual ~Magicien();
            virtual void attaqueSpeciale(Personnage & p) const ;
            virtual const std::string type() const;
        private:
            void bouleDeFeu(Personnage & p) const;
    };
    #endif
    Magicien.cpp
    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
    #include <magicien.hpp>
    #include <iostream>
    Magicien::~Magicien(){}
    void Magicien::attaqueSpeciale(Personnage & p) const 
    {
        bouleDeFeu(p);
    }
    void Magicien::bouleDeFeu(Personnage & p) const
    {
        std::cout<<name()<< "lance une boule de feu sur "<<p.name() <<
                 <<" et lui inflige 15 points de dégats"<<std:endl;
        p.subitDegats(15);
    }
    const std::string Magicien::type() const
    {
        return std::string("magicien");
    }
    guerrier.hpp
    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
    #ifndef GUERRIER_HPP
    #define GUERRIER_HPP
    #include <personnage.hpp>
    class Guerrier : public Personnage
    {
        public:
        /* le guerrier a seulement 125 points de vie :P */
            Guerrier(std::string const & n):Personnage(n,150){}
            virtual ~Guerrier();
            virtual void attaqueSpeciale(Personnage &) const;
            virtual const std::string type() const;
        private:
            void grosCoupDePoing(Personnage & ) const;
    };
    #endif
    guerrier.cpp
    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
    #include <guerrier.hpp>
    #include <iostream>
    Guerrier::~Guerrier(){}
    void Guerrier::attaqueSpeciale(Personnage & p ) const
    {
        grosCoupDePoing(p);
    }
    void Guerrier::grosCoupDePoing(Personnage & p) const
    {
        std::cout<<name()<<" lance un gros coup de point a "<<p.name();
                 <<" et lui inflige 20 points de degats"<<std::endl;
        p.subitDegats(20);
    }
     
    const std::string Guerrier::type() const
    {
        return std::string("guerrier");
    }
    Le joueur: c'est la personne physique qui se trouve devant le clavier
    joueur.hpp
    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
    #ifndef JOUEUR_HPP
    #define JOUEUR_HPP
    #include<string>
    /* ca, c'est une "déclaration anticipée" :D */
    class Personnage;
    class Joueur
    {
        public:
            Joueur(std::string const & ps, int s=0):pseudo_(ps),score_(s), 
                                    perso_(NULL){}
            std::string const & pseudo() const{return pseudo_;}
            int score () const{return score_;}
            Personnage & perso();
            Personnage const & perso() const;
        private:
            friend class Duel;
            void creerPersonnage();
            std::string pseudo;
            int score;
            Personnage * perso_;
    };
    bool operator< (Joueur const & j1, joueur cost & j2)
    {
        return j1.score()>j2.score();
    }
    #endif
    joueur.cpp
    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
    #include <joueur.hpp>
    #include <guerrier.hpp>
    #include <magicien.hpp>
    #include <iostream>
    #include <limits>
    void Joueur::creerPersonnage()
    {
        delete perso_;
        std::string nom;
        std::cout<<pseudo_
                 <<" veuillez introduire le nom de votre personnage :"
        std::cin>>nom;
        bool ok=false;
        int choix;
        while(!ok)
        {
            std::cout<< pseudo_
                     <<" veuillez choisir la classe de votre personnage "<<std::endl
                     <<"    1- Guerrier"<<std::endl
                     <<"    2- Magicien"<<std::endl
                     <<" Votre choix :";
            if(!(cin>>choix))
            {
                std::cout<<"Veuillez choisir entre 1 et 2 uniquement"<<std::endl;
                std::cin.clear(); 
                std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
     
            }
            else
            {
                if(choix==1)
                    perso_=new Guerrier(nom);
                else
                    perso_=new Magicien(nom);
                ok=true;
            }
        }
    }
     
    Personnage & perso(){return *perso_;}
    Personnage const & perso() const{return *perso_;}
    la classe duel: Deux joueurs s'affrontent... dans un duel
    duel.hpp
    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
    #ifndef DUEL_HPP
    #define DUEL_HPP
    class Joueur;
    class Duel
    {
        public:
            Duel(Joueur j1 , Joueur  j2);
            Joueur const & combattre();
        private:
            void presentation() const;
            Joueur joueurs_[2];
            int actif_;
            int defensif_;
            int vainqueur_;
    };
    #endif
    duel.cpp
    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    #include <duel.hpp>
    #include <joueur.hpp>
    #include <iostream>
    Duel::Duel(Joueur const & j1, Joueur const &j2):
          actif_(0),defensif_(1),vainqueur_(3)
    {
        joueurs_[0]=j1;
        joueurs_[1]=j2;
    }
    void Duel::presentation() const
    {
        std::cout<<" Le combat opposera "
                 << joueurs_[0].perso().name()<<", le "
                 << joueurs_[0].perso().type()<<" de "
                 << joueurs_[0].pseudo() <<" ( "<<joueurs_[0].score()<<" points)
                 <<std::endl
                 <<"aaaaa..."<<std::endl
                 << joueurs_[1].perso().name()<<", le "
                 << joueurs_[1].perso().type()<<" de "
                 << joueurs_[1].pseudo() <<" ( "<<joueurs_[0].score()<<" points)
                 <<std::endl<<std::endl
    }
    Joueur const & Duel::combattre()
    {
     
        joueurs_[0].creerPersonnage();
        joueurs_[1].creerPersonnage();
        presentation()
        std::cout<<" Et c'est parti..."<<std::endl
        while(vainqueur_==3)
        {
            bool ok=false;
            int choix;
            while(!ok)
            {
                std::cout<<joueurs_[actif_].pseudo()
                         <<" veuillez choisir l'attaque a porter :"<<std::endl
                         <<"    1- attaque normale"<<std::endl
                         <<"    2- attaque speciale"<<std::endl
                         <<"votre choix ";
            if(!(cin>>choix))
            {
                std::cout<<"Veuillez choisir entre 1 et 2 uniquement"<<std::endl;
                std::cin.clear(); 
                std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
     
            }
            else
            {
                if(choix==1)
                    joueurs_[actif_].perso().coupDePoing(joueurs_[passif_].perso());
                else
                    joueurs_[actif_].perso()
                                    .attaqueSpeciale(joueurs_[passif_].perso());
                ok=true;
            }
            if(!joueurs_[defensif_].perso().estVivant())
            {
                vainqueur_==actif_;
                std::cout<<joueurs_[defensif_].perso().name()
                         <<" est hors combat"<<std::endl;
            }
            else
            {
                std::cout<<"il reste "<<joueurs_[defensif_].perso().pointDeVie()
                         <<" point de vie a "<<joueurs_[defensif_].perso().name()
                         <<std::endl;
                actif_= actif_==0? 1 : 0;
                defensif_=defensif_==0? 1:0;
            }
        }
        std::cout<<"Et le vainqueur est... "<<std::endl
                 << joueurs_[vainqueur_].perso().name()<<", le "
                 << joueurs_[vainqueur_].perso().type()<<" de "
                 << joueurs_[vainqueur_].pseudo()<<std::endl;
        joueurs_[vainqueur_].score_++;
        return joueurs_[vainqueur_];
    }
    Enfin, il serait pas mal d'avoir une classe qui permet d'afficher le score des différents joueurs...

    Elle aurait plusieurs responsabilités:
    1- gérer les joueurs qui ont déjà participés
    2- permettre de sauvegarder le score des joueurs
    3- permettre de récupérer le score des joueurs
    4- afficher le score des joueurs dans l'ordre décroissant

    Nous appellerions cette classe HallOfFame, par exemple
    halloffame.hpp
    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
    #ifndef HALLOFFAME_HPP
    #define HALLOFFAME_HPP
    #include <joueur.hpp>
    #include <duel.hpp>
    #include <map.h>
    class HallOfFame
    {
        public:
            HallOfFame(){}
            bool charger();
            bool sauver() const;
            void scores() const;
            int menu() const;
            mettreAJour(Joueur const &);
            Duel creerDuel();
        private:
            Joueur obtenirJoueur( int);
            std::map<std::string, Joueur> joueurs_;
    };
    #endif
    halloffame.cpp
    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    #include <halloffame.hpp>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #include <fstream>
    /* quelques fonctions qui seront nécessaires pour la facilité */
    std::ostream & operator<<(std::ostream & ofs, Joueur const & j)
    {
        ofs<<j.name()<<"................... "<<j.score()<<std::endl;
        return ofs;
    }
    std::ofstream & operator<<(std::ofstream & ofs, Joueur const & j)
    {
        ofs<<j.name()<<" "<<j.score()<<std::endl;
        return ofs;
    }
    bool HallOfFame::charger()
    {
        std::cout<<"Indiquez le nom du fichier a charger :";
        std::string filename;
        cin>>filename;
        std::ifstream ifs(filename);
        if(!ifs)
        {
            std::cout<<"impossible de charger le fichier "<<filename<<std::endl; 
            return false;
        }
        int score;
        std::string name;
        while(ifs>>name>>score)
        {
            Joueur j(name, score);
            joueurs_.insert(std::make_pair(name,j));
        }
        return true;
    }
    void HallOfFame::sauver() const
    {
        std::cout<<"Indiquez le nom du fichier pour l'enregistrement :";
        std::string filename;
        cin>>filename;
        std::ofstream ofs(filename);
        if(!ofs)
        {
            std::cout<<"impossible de charger le fichier "<<filename<<std::endl; 
            return false;
        }   
        for(std::map<std::string, Joueur>::const_iterator it=joueurs_.begin();
            it!=joueurs_.end(); ++it)
            ofs<<(*it).second;
        return true;
    }
    void HallOfFame::scores() const
    {
        std::vector<Joueurs> tab;
        /* il y aurait surement d'autres solutions ;) */  
        for(std::map<std::string, Joueur>::const_iterator it=joueurs_.begin();
            it!=joueurs_.end(); ++it)
            tab.push_back((*it).second);
        std::sort(tab.begin(), tab.end());
        std::cout<<"Meilleurs scores"<<std::endl
                 <<"================"<<std::endl;
        for(std::vector<Joueur>::const_iterator it=tab.begin();it!=tab.end();++it)
            cout<<(*it);
    }
    int HallOfFame::menu() const
    {
        bool ok=false;
        int choix;
        whle(!ok)
        {
            std::cout<<"Que souhaitez vous faire :"<<std::endl
                     <<"    1- charger un fichier de joueurs"<<std::endl
                     <<"    2- sauvegarder les joueurs"<<std::endl
                     <<"    3- afficher les scores"<<std::endl
                     <<"    4- Lancer un duel"<<std::endl<<std::endl
                     <<"    0- quitter"<<std::endl 
                     <<"Votre choix"
            if(!(cin>>choix))
            {
                std::cout<<"Veuillez choisir entre 1, 2, 3, 4 et 0 uniquement"<<std::endl;
                std::cin.clear(); 
                std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
            }
            if(choix==1 || choix==2 || choix==3 || choix==4 || choix==0)
                ok=true;
        }
        return choix;
    }
    Duel HallOfFame::creerDuel()
    {
        Joueur j1=obtenirJoueur(1);
        Joueur j2=obtenirJoueur(2);
        return Duel(j1,j2);
    }
    Joueur HallOfFame::obtenirJoueur(int i)
    {
        std::cout<<"Veuillez introduire le nom du "
                 <<(i==1 ? "premier " :"deuxieme ")<<" dueliste :";
        std::string nom;
        cin>>nom;
        std::map<std::string, Joueur>::iterator it = joueurs_.find(nom);
        if(it != joueurs_.end())
            return (*it).second;
        Joueur j(nom);
        joueurs_.insert(std::make_pair(nom,j));
        return j;
    void HallOfFame::mettreAJour(Joueur const & j)
    {
        std::map<std::string, Joueur>::iterator it = joueurs_.find(nom);
        (*it).second=j;
    }
    Et le tout serait utilisé sous une forme fort proche de
    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
    #include <halloffame.hpp>
    int main()
    {
        bool encore = true;
        HallOfFame hof;
        while(encore)
        {
            int choix=hof.menu();
            switch (choix)
            {
                case 1:
                    hof.charger();
                    break;
                 case 2:
                    hof.sauver();
                    break;
                 case 3: 
                    hof.scores();
                    break
                 case 4 :
                    Duel d=hof.creerDuel();
                    joueur j=d.combattre();
                    hof.mettreAJour(j);
                    break;
                 case 0: 
                     encore = false;
                     break;
                 default:
                     std::cout<<" nous n'aurions jamais du arriver ici"<<std::endl;
            }
        }
    }
    PS Tout ce code est écrit "à la volée" et n'a pas été testé, mais il devrait faire ce que l'on attend de lui (en plus de permettre pas mal de choses auxquelles tu n'avais sans doute pas pensé )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  18. #18
    Invité
    Invité(e)
    Par défaut
    Petite erreur de frappe dans joueur.h: perso_ devrait être un pointeur.

  19. #19
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Joe Dralliam Voir le message
    Petite erreur de frappe dans joueur.h: perso_ devrait être un pointeur.
    Effectivement, l'étoile a du rester dans mon clavier (j'avais dit que ce code était écrit "à la volée" et non testé... En voila la preuve: la première tentative de compilation m'aurait jeté et je me serais rendu compte de l'erreur )

    Je corrige de suite
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  20. #20
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 66
    Par défaut
    Super, merci beaucoup pour votre aide
    J'ai bien amélioré mon code grace à vous . Je reviendrais surement dans les prochains jours si j'ai des questions précises, histoire de préparer clairement ce que je répondrais face, par exemple, aux : "pourquoi t'as mis une étoile là"?

Discussions similaires

  1. [XL-2002] Besoin d'aide pour finaliser Macro mise en forme + bordure
    Par warrio67 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 12/03/2010, 05h23
  2. [XL-2007] Aide pour finaliser un code
    Par eliot.raymond dans le forum Macros et VBA Excel
    Réponses: 15
    Dernier message: 21/05/2009, 13h56
  3. Aide pour finaliser une macro
    Par NEC14 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 07/08/2008, 08h02
  4. une toute petits aide pour finaliser tout sa
    Par yoan_111 dans le forum ASP
    Réponses: 6
    Dernier message: 16/12/2005, 16h04

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