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 :

Problème avec mon héritage


Sujet :

C++

  1. #1
    Membre confirmé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Points : 604
    Points
    604
    Par défaut Problème avec mon héritage
    Bonjour a toutes et tous, je reviens vers vous encore une fois (et normalement c'est la dernière, promis ).

    Je suis un train de développer un mini RPG pour appliquer ce que j'ai appris sur le c++ et j'ai un petit souci qui mélange polymorphisme et héritage. En gros mon idée de RPG est un duel de mage, on choisi le nom de son mage et son type (feu, glace, eau, etc ...) et puis on se lance dans la bataille (chaque mage à des sorts spécifiques à son type).

    Pour l'instant j'en suis à: une classe mère nommé Mage qui me sert de base pour tous les mages, me permettant ainsi d'initialiser des points de vie, les points de mana, le traitement des dégâts, les gain ou perte de points de vie et de mana, etc ...

    Voici les fichiers .h et .cpp pour vous donner l'idée
    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
     
    #ifndef MAGE_H_INCLUDED
    #define MAGE_H_INCLUDED
     
    #include <iostream>
    #include <vector>
    #include <string>
     
    class Mage
    {
        public:
            //Constructeur
            Mage(std::string nom);
     
            //Destructeur
            virtual ~Mage();
     
            //Methodes
            virtual void recevoirDegats(int degats);
            virtual void perteMana(Mage &cible, int pmana);
            virtual void gainMana();
            virtual void boirePotion();
            virtual void attaqueBase(Mage &cible) const;
            virtual void sePresenter () const;
            virtual void afficherEtat() const;
            virtual int etatVie();
     
        protected:
            //Attributs
            int m_vie;
            int m_mana;
            std::string m_nom;
    };
     
    #endif // PERSONNAGE_H_INCLUDED
    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
     
    #include "Mage.h"
     
    using namespace std;
     
     
    //Constructeur
    Mage::Mage(string nom) : m_vie(100), m_mana(100), m_nom(nom)
    {
     
    }
     
    //Destructeur
    Mage::~Mage()
    {
     
    }
     
     
    //Méthode "de base" pour tous les personnes
    void Mage::recevoirDegats(int degats)
    {
        m_vie -= degats;
    }
     
    void Mage::perteMana(Mage &cible, int pmana)
    {
        m_mana -= pmana;
    }
     
    void Mage::boirePotion()
    {
        m_vie += 20;
    }
     
    void Mage::gainMana()
    {
        m_mana += 5;
    }
     
    void Mage::attaqueBase(Mage &cible) const
    {
        cible.recevoirDegats(10);
    }
     
    void Mage::sePresenter() const
    {
        cout << "Bonjour, je m'appelle " << m_nom << "." << endl;
        cout << "J'ai encore " << m_vie << " points de vie et " << m_mana << " points de mana." << endl << endl;
    }
     
     
    void Mage::afficherEtat() const
    {
        cout << "Etat de " << m_nom << endl;
        cout << "Vie : " << m_vie << endl;
        cout << "Mana : " << m_mana << endl << endl;
    }
     
    int Mage::etatVie()
    {
        return(m_vie);
    }
    Puis (pour l'instant), j'ai créé un mage de type feu qui hérite de ma classe mère Mage nommé MageFeu dont voici les fichiers .h et .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
     
    #ifndef MAGEFEU_H_INCLUDED
    #define MAGEFEU_H_INCLUDED
     
    #include <iostream>
    #include <string>
    #include "Mage.h"
     
    class MageFeu : public Mage
    {
        public:
            //Constructeurs
            MageFeu(std::string nom);
     
            //Destructeur
            virtual ~MageFeu();
     
            //Methodes
            virtual void sePresenter () const;
            virtual void bouleDeFeu(Mage &cible) const;
     
        protected:
            //Attributs spécifiques a la classe Magicien
     
    };
     
    #endif // MAGEFEU_H_INCLUDED
    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
     
    #include "Mage.h"
    #include "MageFeu.h"
     
    using namespace std;
     
    //Constructeurs
    MageFeu::MageFeu(string nom) : Mage(nom)
    {
     
    }
     
    //Destructeur
    MageFeu::~MageFeu()
    {
     
    }
     
     
    //Méthodes spécifiques à la classe Mage de feu
    void MageFeu::sePresenter() const
    {
        cout << "Bonjour, je m'appelle " << m_nom << ". Je suis un Mage de feu" << endl;
        cout << "J'ai encore " << m_vie << " points de vie et " << m_mana << " points de mana." << endl << endl;
    }
     
     
    void MageFeu::bouleDeFeu(Mage &cible) const
    {
        cible.recevoirDegats(35);
    }
    Dans mon main maintenant, je gère la création de mes deux personnages mais ne sachant pas de quel type ils sont (vu que c'est au joueur de choisir) j'utilise le polymorphisme avec le code suivant:

    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
     
    string nomMage1;
        string nomMage2;
        int choixType1(0);
        int choixType2(0);
     
        //Creation du premier mage
        Mage* pMage1 = NULL;
    	cout << "Rentrez le nom du premier mage svp:" << endl;
    	getline(cin, nomMage1);
    	cout << "Choisissez le type de mage:" << endl;
    	cin >> choixType1;
    	if(choixType1 == 1)
    	{
    		pMage1 = new Mage(nomMage1);
    	}
    	else if(choixType1 ==2)
    	{
    		pMage1 = new MageFeu(nomMage1);
    	}
        pMage1->sePresenter();
        std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
     
        //Creation du deuxième mage
        Mage* pMage2 = NULL;
    	cout << "Rentrez le nom du deuxieme mage svp:" << endl;
    	getline(cin, nomMage2);
    	cout << "Choisissez le type de mage:" << endl;
    	cin >> choixType2;
    	if(choixType2 == 1)
    	{
    		pMage2 = new Mage(nomMage2);
    	}
    	else if(choixType2 ==2)
    	{
    		pMage2 = new MageFeu(nomMage2);
    	}
        pMage2->sePresenter();
    Jusqu'ici, je ne rencontre aucun problème, la création de mes personnes se fait bien et ils sont bien du type choisi (vérification faite avec la méthode sePresenter()).

    C'est après que j'ai un problème dans ma boucle de comabt (pour l'instant la boucle n'est pas implémentée) dont voici le code:

    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
     
    int choixAction1(0);
        //int choixAction2(0);
        int choixAttaque1(0);
        //int choixAttaque2(0);
        int compteurTour(1);
     
        //int etatVie1(0);
        //int etatVie2(0);
     
        cout << "TOUR " << compteurTour << endl << endl;
        cout << nomMage1 << ", choisissez l'action a effectuer" << endl;
        cin >> choixAction1;
        switch(choixType1)
        {
            case 1:
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl << "1 - Attaque de base" << endl;
                        cin >> choixAttaque1;
                    break;
                    default:
     
                    break;
                }
            break;
            case 2:
                   switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl << "1 - Attaque de base" << endl << "2 - Boule de Feu" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMage1->bouleDeFeu(*pMage2);
                                pMage1->perteMana(*pMage1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    default:
     
                    break;
                }
        }
    Alors, déjà, oui je sais que c'est un peu une usine à gaz (comme on dit par chez moi) mais pour l'instant je n'ai pas d'autre idée de syntaxe donc veuillez me pardonner.

    Mon problème viens de la ligne de code suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pMage1->bouleDeFeu(*pMage2);
    qui me génère comme erreur
    "error: 'class Mage' has no member named 'bouleDeFeu' "

    Alors l'erreur je l'a comprend, ma classe Mage (donc ma classe mère ne connait pas la méthode bouleDeFeu, cette erreur doit très probablement venir du fait que lorsque je crée un personnage j'ai cette ligne de code
    (on utilise le constructeur de la classe mère)

    Donc ma question est: est-ce que je dois la faire version méga-bourrin (enfin je pense) où je déclare toutes les méthodes de sorts (quelque soit le type) dans la classe mère et après j'adapte dans mes switchs en fonction du type choisi par le joueurs ou alors est-ce qu'il y a un moyen de garder les méthodes dans les classes filles ?

    Dans l'attente de vos réponses,
    Cordialement,
    Clairetj
    Si vous voulez suivre les différents championnats de football américain en France, en Europe et dans le Monde (en tout 32 pays différents), c'est sur www.fandefootus.fr

  2. #2
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Points : 311
    Points
    311
    Par défaut
    Comme tu as déclaré un pointeur sur la classe mère, il est normal que tu ne puisses accéder à une méthode de la classe fille qui est inexistante dans la classe mère.
    Cependant comme tu sais de quel type est ton mage puisque tu appels une méthode spécifique d'une classe fille, il te suffit dans ton switch de faire un cast dynamique de ton pMage vers le type de mage que tu as implémenté.
    Dés lors, la méthode sera connue.

  3. #3
    Membre confirmé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Points : 604
    Points
    604
    Par défaut
    Donc si je comprend bien ce que tu m'explique, dans mon switch où j'appelle la méthode bouleDeFeu qui appartient à une classe fille je doit mettre avant la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pMage1 = dynamic_cast<MageFeu*>(pMage1);
    donc cela donnerait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    pMage1 = dynamic_cast<MageFeu*>(pMage1);
    pMage1->bouleDeFeu(*pMage2);                       
    pMage1->perteMana(*pMage1, 5);
    Si vous voulez suivre les différents championnats de football américain en France, en Europe et dans le Monde (en tout 32 pays différents), c'est sur www.fandefootus.fr

  4. #4
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Points : 311
    Points
    311
    Par défaut
    Non, pas tout à fait. pMage et de type Mage* est ça tu ne peux pas le changer tu dois faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    dynamic_cast<MageFeu*>(pMage1)->BouleDefeu( *pMage2);
    ou bien tu déclare un nouveau pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MageFeu *pMageFeu = dynamic_cast<MageFeu*>(pMage1);
    et après tu utilises pMageFeu dans ton switch.

  5. #5
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Points : 311
    Points
    311
    Par défaut
    Si tu veux éviter ce type de manipulation, tu peux aussi déclarer dans ta classe mère une méthode virtuelle pure "attaque" qui prend un paramètre de type entier, et c'est cette méthode que tu surcharges dans les classes filles dès lors tu n'as plus à t’embêter avec les histoires de cast.

  6. #6
    Membre confirmé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Points : 604
    Points
    604
    Par défaut
    Merci AF_2.8

    J'ai choisi d'utiliser la méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MageFeu *pMageFeu = dynamic_cast<MageFeu*>(pMage1);
    et donc utiliser pMageFeu dans le reste du switch et cela marche tel que je le souhaitais,

    Encore merci pour ton aide
    Si vous voulez suivre les différents championnats de football américain en France, en Europe et dans le Monde (en tout 32 pays différents), c'est sur www.fandefootus.fr

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par AF_2.8 Voir le message
    Comme tu as déclaré un pointeur sur la classe mère, il est normal que tu ne puisses accéder à une méthode de la classe fille qui est inexistante dans la classe mère.
    Cependant comme tu sais de quel type est ton mage puisque tu appels une méthode spécifique d'une classe fille, il te suffit dans ton switch de faire un cast dynamique de ton pMage vers le type de mage que tu as implémenté.
    Dés lors, la méthode sera connue.
    Sauf que c'est une très mauvaise méthode à éviter à tout prix

    Je m'explique tout de suite
    Citation Envoyé par clairetj Voir le message
    Merci AF_2.8

    J'ai choisi d'utiliser la méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MageFeu *pMageFeu = dynamic_cast<MageFeu*>(pMage1);
    et donc utiliser pMageFeu dans le reste du switch et cela marche tel que je le souhaitais,

    Encore merci pour ton aide
    Je te conseillerais donc de virer cette horreur de ton code le plus vite possible

    Le fait est que cela fonctionne, c'est indéniable.

    Sauf que, sur le long terme, tu devras de plus en plus faire la distinction entre ton mage de feu et ton mage de glace.

    Les switch et les dynamic_cast vont donc se multiplier comme des petits pains dans les mains de quelqu'un de bien connu

    Et quand tu voudras ajouter ton mage de l'air ou ton mage de l'eau ou ton mage de l'esprit, tu devras parcourir tout ton code à la recherche de tous tes switchs pour rajouter le cas du mage que tu veux rajouter

    Et si tu en oublies un, tu t'étonneras que ton mage ne fait simplement rien alors qu'il aurait du faire une action particulière.

    A priori, si tu connais ton mage comme étant un mage (sans précision), tu n'as pas à essayer de savoir s'il s'agit d'un mage de feu, de glace, d'air d'eau ou de feu!!!

    Chaque mage sait exactement de quel type il est et c'est déjà très largement suffisant!

    La solution passe par ce que l'on appelle le double dispatch:

    Lorsque tu veux entreprendre une action, tu demande au mage (que tu ne connais qu'en tant que tel) d'appeler une fonction en se passant lui même comme paramètre.

    De cette manière, le mage de feu passera en paramètre un MageFeu/*const*/& et un mage de glace passera en paramètre un MageGlace/* const */ &.

    Tu pourras donc surcharger cette fonction pour les différents types de mage qui existent, en utilisant les fonctions membres qui leur sont spécifiques.

    Le problème est à ce point récurrent qu'il existe même un patron de conception qui prend cet aspect en charge (mais qui n'est qu'une manière d'utiliser le double dispatch) : le patron de conception visiteur.

    L'idée est d'avoir au niveau de la fonction un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Visiteur v;
    leMage->accept(v);
    Au niveau du mage, d'avoir quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Mage{
        public:
            // on ne sait pas préciser le comportement pour la classe de base
            virtual void accept(Visiteur &) = 0; 
    }:
    MageGlace : public Mage{
        public:
            virtual void accept(Visiteur &v){v.visit(*this);}
    };
     
    MageFeu : public Mage{
        public:
            virtual void accept(Visiteur &v){v.visit(*this);}
    };
    et, au niveau de Visiteur quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Visiteur{
        public:
            void visit(MageFeu /* const */ & ){
                /* comportement spécifique pour le mage du feu */
            }
            void visit(MageGlace /* const*/ & ){
                /* comportement spécifique pour le mage de glace */
            }
    };
    Notes enfin que tu peux avoir toute une hiérarchie de visiteur, qui prennent différents aspects en charge.

    Les fonctions visit seraient alors virtuelles évidemment
    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

  8. #8
    Membre confirmé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Points : 604
    Points
    604
    Par défaut
    Merci pour ton intervention koala01

    En revanche, et tu risque d'être déçu, mais n'ayant vu que ton message que maintenant, j'ai déjà mis en oeuvre la solution de AF_2.8 que j'avais choisi.

    Outre le fait, et cela je te l'accorde, que ça crée une usine a gaz avec le rajout dans les switchs à chaque fois que je crois un nouveau type de mage (bon ça à la limite je peux encore m'en débrouiller vu que le nombre de mage différents reste limité, je veux dire par la max 8), je me retrouve avec une flopée d'erreurs nommées: "error: crosses initialisation of ..... " (...... représente soit MageFeu, soit MageFoudre, etc ... selon le type de mage).

    Lorsque j'utilise la méthode choisi et que je n'ai qu'un type de mage (par exemple MageFeu), je n'ai aucun problème, le programme fonctionne et mais deux personnages (deux mageFeu) combattent comme souhaiter. Mais lorsque j'ajoute un nouveau type de mage dans ma boucle de combat, là j'ai mon erreur de crosses initialisation et au plus je rajoute un nouveau type de mage au plus j'ai de nouvelles erreurs de crosses initialisation (voici une partie du code que j'ai créé pour le combat, oui c'est usine à gaz alors désolé):

    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
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
     
    cout << nomMage1 << ", choisissez l'action a effectuer:" << endl << "1 - Attaquer" << endl << "2 - Boire une potion de guerison" << endl;
        cin >> choixAction1;
        switch(choixType1)
        {
            case 1:
                MageFeu *pMageFeu1 = dynamic_cast<MageFeu*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl << "1 - Attaque de base" << endl << "2 - Boule de Feu" << endl << "3 - Tempête de Feu" << endl << "4 - Souffle ardent" << endl << "5 - Poing de Feu" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                if(etatMana1 > 10)
                                {
                                    pMageFeu1->bouleDeFeu(*pMage2);
                                    pMageFeu1->perteMana(*pMageFeu1, 10);
                                }
     
                            break;
                            case 3:
                                if(etatMana1 > 20)
                                {
                                    pMageFeu1->tempeteDeFeu(*pMage2);
                                    pMageFeu1->perteMana(*pMageFeu1, 20);
                                }
     
                            break;
                            case 4:
                                if(etatMana1 > 15)
                                {
                                    pMageFeu1->souffleArdent(*pMage2);
                                    pMageFeu1->perteMana(*pMageFeu1, 15);
                                }
     
                            break;
                            case 5:
                                if(etatMana1 > 5)
                                {
                                    pMageFeu1->poingDeFeu(*pMage2);
                                    pMageFeu1->perteMana(*pMageFeu1, 5);
                                }
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
     
            case 2:
                MageFoudre *pMageFoudre1 = dynamic_cast<MageFoudre*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl << "1 - Attaque de base" << endl << "2 - Charge Electrique" << endl << "3 - Grondement de la Foudre" << endl << "4 - Eclair Destructeur" << endl << "5 - Poing de Foudre" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageFoudre1->chargeElectrique(*pMage2);
                                pMageFoudre1->perteMana(*pMageFoudre1, 10);
                            break;
                            case 3:
                                pMageFoudre1->grondementDeLaFoudre(*pMage2);
                                pMageFoudre1->perteMana(*pMageFoudre1, 20);
                            break;
                            case 4:
                                pMageFoudre1->eclairDestructeur(*pMage2);
                                pMageFoudre1->perteMana(*pMageFoudre1, 15);
                            break;
                            case 5:
                                pMageFoudre1->poingDeFoudre(*pMage2);
                                pMageFoudre1->perteMana(*pMageFoudre1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
            case 3:
                MageEau *pMageEau1 = dynamic_cast<MageEau*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl << "1 - Attaque de base" << endl << "2 - Prison Aqueuse" << endl << "3 - Raz-de-maree" << endl << "4 - Vague Deferlente" << endl << "5 - Fouet Aqueux" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageEau1->prisonAqueuse(*pMage2);
                                pMageEau1->perteMana(*pMageEau1, 10);
                            break;
                            case 3:
                                pMageEau1->razDeMaree(*pMage2);
                                pMageEau1->perteMana(*pMageEau1, 20);
                            break;
                            case 4:
                                pMageEau1->vagueDerferlente(*pMage2);
                                pMageEau1->perteMana(*pMageEau1, 15);
                            break;
                            case 5:
                                pMageEau1->fouetAqueux(*pMage2);
                                pMageEau1->perteMana(*pMageEau1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
            case 4:
                MageTerre *pMageTerre1 = dynamic_cast<MageTerre*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl << "1 - Attaque de base" << endl << "2 - Dagues de Pierre" << endl << "3 - Tremblement de Terre" << endl << "4 - Eboulement" << endl << "5 - Poing de Pierre" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageTerre1->daguesDePierre(*pMage2);
                                pMageTerre1->perteMana(*pMageTerre1, 10);
                            break;
                            case 3:
                                pMageTerre1->tremblementDeTerre(*pMage2);
                                pMageTerre1->perteMana(*pMageTerre1, 20);
                            break;
                            case 4:
                                pMageTerre1->eboulement(*pMage2);
                                pMageTerre1->perteMana(*pMageTerre1, 15);
                            break;
                            case 5:
                                pMageTerre1->poingDePierre(*pMage2);
                                pMageTerre1->perteMana(*pMageTerre1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
            case 5:
                MageAir *pMageAir1 = dynamic_cast<MageAir*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl << "1 - Attaque de base" << endl << "2 - Danse du Vent" << endl << "3 - Souffle Devastateur" << endl << "4 - Lame du Vent" << endl << "5 - Sphere du Vent" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageAir1->danseDuVent(*pMage2);
                                pMageAir1->perteMana(*pMageAir1, 10);
                            break;
                            case 3:
                                pMageAir1->souffleDevastateur(*pMage2);
                                pMageAir1->perteMana(*pMageAir1, 20);
                            break;
                            case 4:
                                pMageAir1->lameDuVent(*pMage2);
                                pMageAir1->perteMana(*pMageAir1, 15);
                            break;
                            case 5:
                                pMageAir1->spheresDuVent(*pMage2);
                                pMageAir1->perteMana(*pMageAir1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
            case 6:
                MageGlace *pMageGlace1 = dynamic_cast<MageGlace*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl << "1 - Attaque de base" << endl << "2 - Marteau de Glace" << endl << "3 - Avalanche" << endl << "4 - Hache de Glace" << endl << "5 - Poing de Glace" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageGlace1->marteauDeGlace(*pMage2);
                                pMageGlace1->perteMana(*pMageGlace1, 10);
                            break;
                            case 3:
                                pMageGlace1->avalanche(*pMage2);
                                pMageGlace1->perteMana(*pMageGlace1, 20);
                            break;
                            case 4:
                                pMageGlace1->hacheDeGlace(*pMage2);
                                pMageGlace1->perteMana(*pMageGlace1, 15);
                            break;
                            case 5:
                                pMageGlace1->poingDeGlace(*pMage2);
                                pMageGlace1->perteMana(*pMageGlace1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
        }
    du coup, je devrais changer de méthode et faire comme celle que tu m'as indiquer, mais juste par curiosité, si je souhaite garder mon usine à gaz, comment faire pour régler mes problèmes de crosses initialisations ???
    Si vous voulez suivre les différents championnats de football américain en France, en Europe et dans le Monde (en tout 32 pays différents), c'est sur www.fandefootus.fr

  9. #9
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par clairetj Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if(etatMana1 > 10)
    {
        pMageFeu1->bouleDeFeu(*pMage2);
        pMageFeu1->perteMana(*pMageFeu1, 10);
    }
    Tu devrais factoriser ce code. Si tu oublis une vérification (comme dans le cas du mage foudre par exemple), ou d'appeler perteMana tu te retrouvera avec un comportement bizarre.

  10. #10
    Membre confirmé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Points : 604
    Points
    604
    Par défaut
    Pour les structures en if de contrôle de la quantité de mana, oui je pourrait factoriser pour alléger de le code (et l'oubli généralisé, pas seulement sur MageFoudre, est un oubli de ma part).

    En revanche j'ai toujours mes problèmes de crosses initialisation (qui je pense n'est pas dût à l'oubli de ces if), donc pour l'instant c'est surtout ces problèmes que j'essaie de résoudre en priorité et je n'ai actuellement aucune solution
    Si vous voulez suivre les différents championnats de football américain en France, en Europe et dans le Monde (en tout 32 pays différents), c'est sur www.fandefootus.fr

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    En fait, la "mise en page" de ton code ne te permet pas de te rendre bien compte.

    Nous allons donc te donner une première règle : tu dois limiter chaque ligne de code à (environ) 80 caractères.

    Cette limite "arbitraire" vient de la préhistoire des ordinateur, lorsque les écrans ne pouvaient afficher que 25 lignes de 80 colonnes, et on peut donc envisager de l'assouplir quelque peut en admettant qu'il y en ait "quelques uns" (mettons une dizaine maximum) de plus, mais cela rendra déjà le code beaucoup plus facile à lire.

    Surtout si nous y adjoignons une autre règle : une instruction par ligne.

    Ce n'est ici que de la mise en page, mais, si tu considère que <<endl correspond à une fin d'instruction (ce qui est vrai dans le sens où cela force l'affichage à aller à la ligne, même si ce n'est pas vraiment le symbole de fin d'instruction ), ton code pourrait ressembler à
    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
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    cout << nomMage1 << ", choisissez l'action a effectuer:" << endl 
         << "1 - Attaquer" << endl 
         << "2 - Boire une potion de guerison" << endl;
        cin >> choixAction1;
        switch(choixType1)
        {
            case 1:
                MageFeu *pMageFeu1 = dynamic_cast<MageFeu*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl 
                             << "1 - Attaque de base" << endl 
                             << "2 - Boule de Feu" << endl 
                             << "3 - Tempête de Feu" << endl 
                             << "4 - Souffle ardent" << endl 
                             << "5 - Poing de Feu" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                if(etatMana1 > 10)
                                {
                                    pMageFeu1->bouleDeFeu(*pMage2);
                                    pMageFeu1->perteMana(*pMageFeu1, 10);
                                }
     
                            break;
                            case 3:
                                if(etatMana1 > 20)
                                {
                                    pMageFeu1->tempeteDeFeu(*pMage2);
                                    pMageFeu1->perteMana(*pMageFeu1, 20);
                                }
     
                            break;
                            case 4:
                                if(etatMana1 > 15)
                                {
                                    pMageFeu1->souffleArdent(*pMage2);
                                    pMageFeu1->perteMana(*pMageFeu1, 15);
                                }
     
                            break;
                            case 5:
                                if(etatMana1 > 5)
                                {
                                    pMageFeu1->poingDeFeu(*pMage2);
                                    pMageFeu1->perteMana(*pMageFeu1, 5);
                                }
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
     
            case 2:
                MageFoudre *pMageFoudre1 = dynamic_cast<MageFoudre*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" 
                             << endl << "1 - Attaque de base" << endl 
                             << "2 - Charge Electrique" << endl 
                             << "3 - Grondement de la Foudre" << endl 
                             << "4 - Eclair Destructeur" << endl 
                             << "5 - Poing de Foudre" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageFoudre1->chargeElectrique(*pMage2);
                                pMageFoudre1->perteMana(*pMageFoudre1, 10);
                            break;
                            case 3:
                                pMageFoudre1->grondementDeLaFoudre(*pMage2);
                                pMageFoudre1->perteMana(*pMageFoudre1, 20);
                            break;
                            case 4:
                                pMageFoudre1->eclairDestructeur(*pMage2);
                                pMageFoudre1->perteMana(*pMageFoudre1, 15);
                            break;
                            case 5:
                                pMageFoudre1->poingDeFoudre(*pMage2);
                                pMageFoudre1->perteMana(*pMageFoudre1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
            case 3:
                MageEau *pMageEau1 = dynamic_cast<MageEau*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl 
                               << "1 - Attaque de base" << endl 
                               << "2 - Prison Aqueuse" << endl 
                               << "3 - Raz-de-maree" << endl 
                               << "4 - Vague Deferlente" << endl 
                               << "5 - Fouet Aqueux" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageEau1->prisonAqueuse(*pMage2);
                                pMageEau1->perteMana(*pMageEau1, 10);
                            break;
                            case 3:
                                pMageEau1->razDeMaree(*pMage2);
                                pMageEau1->perteMana(*pMageEau1, 20);
                            break;
                            case 4:
                                pMageEau1->vagueDerferlente(*pMage2);
                                pMageEau1->perteMana(*pMageEau1, 15);
                            break;
                            case 5:
                                pMageEau1->fouetAqueux(*pMage2);
                                pMageEau1->perteMana(*pMageEau1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
            case 4:
                MageTerre *pMageTerre1 = dynamic_cast<MageTerre*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl 
                             << "1 - Attaque de base" << endl 
                             << "2 - Dagues de Pierre" << endl 
                             << "3 - Tremblement de Terre" << endl 
                             << "4 - Eboulement" << endl 
                             << "5 - Poing de Pierre" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageTerre1->daguesDePierre(*pMage2);
                                pMageTerre1->perteMana(*pMageTerre1, 10);
                            break;
                            case 3:
                                pMageTerre1->tremblementDeTerre(*pMage2);
                                pMageTerre1->perteMana(*pMageTerre1, 20);
                            break;
                            case 4:
                                pMageTerre1->eboulement(*pMage2);
                                pMageTerre1->perteMana(*pMageTerre1, 15);
                            break;
                            case 5:
                                pMageTerre1->poingDePierre(*pMage2);
                                pMageTerre1->perteMana(*pMageTerre1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
            case 5:
                MageAir *pMageAir1 = dynamic_cast<MageAir*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl 
                            << "1 - Attaque de base" << endl 
                            << "2 - Danse du Vent" << endl 
                            << "3 - Souffle Devastateur" << endl 
                            << "4 - Lame du Vent" << endl 
                            << "5 - Sphere du Vent" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageAir1->danseDuVent(*pMage2);
                                pMageAir1->perteMana(*pMageAir1, 10);
                            break;
                            case 3:
                                pMageAir1->souffleDevastateur(*pMage2);
                                pMageAir1->perteMana(*pMageAir1, 20);
                            break;
                            case 4:
                                pMageAir1->lameDuVent(*pMage2);
                                pMageAir1->perteMana(*pMageAir1, 15);
                            break;
                            case 5:
                                pMageAir1->spheresDuVent(*pMage2);
                                pMageAir1->perteMana(*pMageAir1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
            case 6:
                MageGlace *pMageGlace1 = dynamic_cast<MageGlace*>(pMage1);
                switch(choixAction1)
                {
                    case 1:
                        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl 
                             << "1 - Attaque de base" << endl 
                             << "2 - Marteau de Glace" << endl 
                             << "3 - Avalanche" << endl 
                             << "4 - Hache de Glace" << endl 
                             << "5 - Poing de Glace" << endl;
                        cin >> choixAttaque1;
                        switch(choixAttaque1)
                        {
                            case 1:
                                pMage1->attaqueBase(*pMage2);
                            break;
                            case 2:
                                pMageGlace1->marteauDeGlace(*pMage2);
                                pMageGlace1->perteMana(*pMageGlace1, 10);
                            break;
                            case 3:
                                pMageGlace1->avalanche(*pMage2);
                                pMageGlace1->perteMana(*pMageGlace1, 20);
                            break;
                            case 4:
                                pMageGlace1->hacheDeGlace(*pMage2);
                                pMageGlace1->perteMana(*pMageGlace1, 15);
                            break;
                            case 5:
                                pMageGlace1->poingDeGlace(*pMage2);
                                pMageGlace1->perteMana(*pMageGlace1, 5);
                            break;
                            default:
     
                            break;
                        }
                    break;
                    case 2:
                        pMage1->boirePotion();
                    break;
                    default:
                        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
                    break;
                }
            break;
        }
    On se rend alors compte que, quel que soit le type de mage, tu copie, à quelques point de variation près, à chaque fois le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl 
         << "1 - Attaque de base" << endl 
         << "2 - <attaque type 2>" << endl 
         << "3 - <attaque type 3>" << endl 
         << "4 - <attaque type 4>" << endl 
         << "5 - <attaque type 5>" << endl;
    cin >> choixAttaque1;
    et que la logique est toujours la même (à quelque variation près) car elle prend la forme 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
    switch(choixAttaque1)
    {
        case 1:
            leMage->attaqueBase(*pMage2);
            break;
        case 2:
            leMage-><attaque type 2>(*pMage2);
            leMage->perteMana(<pMage1>, <cout attaque type2>);
            break;
        case 3:
            leMage-><attaque type 3>(*pMage2);
            leMage->perteMana(*leMage,  <cout attaque type3>);
            break;
        case 4:
            leMage-><attaque type 4>(*pMage2);
            leMage->perteMana(*leMage,  <cout attaque type4>);
            break;
        case 5:
            leMage-><attaque type 5>(*pMage2);
            leMage->perteMana(*leMage,  <cout attaque type5>);
            break;
        default:
            break;
    }
    Je n'ai modifié le code qu'afin de "généraliser" les comportements.

    Mais cette généralisation met un aspect en évidence : une attaque est une attaque, quel que soit le type de l'attaque ou la spécialité qu'elle nécessite.

    On peut donc mettre un nouveau "concept" au point qui représente "n'importe quelle attaque" par une classe de base proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Attaque{
        public:
            Attaque(std::string const & nom, int cout):nom_(nom),cout_(cout){}
            std::string const & nom() const{return nom_;}
           int cout() const{return cout_;}
    };
    Cela nous permet, étant donné qu'il y a d'office cinq attaque pour chaque type de mage, de créer un tableau d'attaque proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::vector<Attque> attaquesMageDeau;
    attaquesMageDeau.push_back(Attaque("attaque de base", 0));
    attaquesMageDeau.push_back(Attaque("Prison Aqueuse", 10));
    attaquesMageDeau.push_back(Attaque("Raz-de-maree", 20));
    attaquesMageDeau.push_back(Attaque("Vague Deferlente", 15));
    attaquesMageDeau.push_back(Attaque("Fouet Aqueux", 5));
    et de faire de même pour n'importe quel type de mage (en adaptant simplement le nom des attaques et le nom du tableau).

    Ce nouveau concept permettra en outre de n'avoir plus qu'un comportement, commun à chaque mage, qui est d'attaquer (le mage à attaquer, avec l'attaque choisie par l'utilisateur).

    Plutôt que d'avoir cinq comportements (qui portent des noms différents pour chaque type de mage), tu peux donc généraliser l'ensemble en un seul comportement, qui peut apparaitre dans la classe de base:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Mage{
        public:
            void attaque(Mage * leMage, Attaque const & lattaque){
                leMage->subitAttaque(lattaque);
            }
    };
    et tu peux créer une fonction proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int choixAttaque(std::vector<Attaque> const & tab){
        cout << nomMage1 << ", a vous d'attaquer. Veuillez choisir une attaque entre:" << endl 
        for(int i = 0; i< tab.size();++i){
            cout<< i<<" - "<<tab[i].nom<<std::endl;
        }
        int choix;
        cin >> choix;
        return choix
    }
    L'avantage, c'est que si tu décide qu'un type de mage connait plus d'attaques qu'un autre, cela continuera à fonctionner

    Mais, surtout, cela te permet de généraliser le comportement de l'attaque elle-même sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int attaque1 =  choixAttaque(attaquesMageDeau);
    if(attaque1 < attaquesMageDeau.size()){
        leMage->attaque(pMage2, attaquesMageDeau[i]);
        leMage->perteMana(*leMage,attaquesMageDeau[i].cout() );
    }
    et, comme c'est un code identique quel que soit le type de mage, nous pourrions créer une fonction une fonction proche de
    void attaque(Mage * attaquant, Mage * lattaque, std::vector<Attaque>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const & tab){
        if(choixAttaque(tab)< attaquesMageDeau.size()){
            leMage->attaque(pMage2, attaquesMageDeau[tab]);
            leMage->perteMana(*leMage,attaquesMageDeau[tab].cout() );
        }
        else{
            cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
        }
    }
    Au final, tu n'as même plus besoin de l'usine à gaz car ton code peut devenir aussi simple que
    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
    cout << nomMage1 << ", choisissez l'action a effectuer:" << endl 
         << "1 - Attaquer" << endl 
         << "2 - Boire une potion de guerison" << endl;
    cin >> choixAction1;
    if(choixAction1==1){
        switch(choixType1)
        {
                case 1:
                    attaquer(pMage1, pMage2, attaquesMageDeFeu);
                    break;
                case 2:
                    attaquer(pMage1, pMage2, attaquesMageDeau);
                    break;
                case 3:
                    attaquer(pMage1, pMage2, attaquesMageDeGlace);
                    break;
                case 4:
                    attaquer(pMage1, pMage2, attaquesMageDePierre);
                    break;
        }
    } 
    else if(choixAction1 == 2)
    {
        pMage1->boirePotion();
    }else{
        cout << "Vous n'avez pas choisi d'action a effectuer, vous passez votre tour !" << endl << endl;
    }
    En plus, tu remarqueras que tu n'as même plus besoin de récupérer le type réel de tes mages
    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

  12. #12
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par koala01 Voir le message
    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
        switch(choixType1)
        {
                case 1:
                    attaquer(pMage1, pMage2, attaquesMageDeFeu);
                    break;
                case 2:
                    attaquer(pMage1, pMage2, attaquesMageDeau);
                    break;
                case 3:
                    attaquer(pMage1, pMage2, attaquesMageDeGlace);
                    break;
                case 4:
                    attaquer(pMage1, pMage2, attaquesMageDePierre);
                    break;
        }
    En plus, tu remarqueras que tu n'as même plus besoin de récupérer le type réel de tes mages
    Bah, il y a bien un switch sur le type du mage là. (qui peut disparaître en mettant le tableau d'attaques dans la classe Mage )

    On en à déjà un peu discuté, mais dans ce cas, le fait d'avoir une classe par type de Mage me plait pas. Le code risque d'être de la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Mage { /* ... */ };
     
    class MageFeu: public Mage { }; // aucun nouvel attribut ni fonctions à surcharger ou à ajouter
    Seule la fonction recevoirDegat pourrait être surchargée pour modifier les dégâts en fonctions des types des mages, mais on peut très bien s'en sortir avec une std::map<Type, float> dmgMultiplier;Ou gérer ça dans la fonction attaquer

  13. #13
    Membre confirmé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Points : 604
    Points
    604
    Par défaut
    merci pour la réponse koala01, mais je ne pourrait la programmer que ce soir soir je ne peux pas te dire quels résultats cela va donner (mais je puis supposer que cela va marcher)

    En revanche un petit point me turlupine, j'ai vu dans la partie "traitement des attaques" la gestion de la perte de mana par contre concernant l'utilisation des sorts (l'attaque quoi) je vois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class Attaque{
        public:
            Attaque(std::string const & nom, int cout):nom_(nom),cout_(cout){}
            std::string const & nom() const{return nom_;}
           int cout() const{return cout_;}
    };
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::vector<Attque> attaquesMageDeau;
    attaquesMageDeau.push_back(Attaque("attaque de base", 0));
    attaquesMageDeau.push_back(Attaque("Prison Aqueuse", 10));
    attaquesMageDeau.push_back(Attaque("Raz-de-maree", 20));
    attaquesMageDeau.push_back(Attaque("Vague Deferlente", 15));
    attaquesMageDeau.push_back(Attaque("Fouet Aqueux", 5));
    Est-ce que cela veut dire que les méthodes des sorts devront porter exactement le même mot que le paramètre ? Parce qu'actuellement, si on prend un exemple, le nom de la méthode créée pour "Vague Derferlente" se nomme void vagueDeferlente(). dois-je donc changer les noms de mes méthodes ?
    Si vous voulez suivre les différents championnats de football américain en France, en Europe et dans le Monde (en tout 32 pays différents), c'est sur www.fandefootus.fr

  14. #14
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Apparemment, tu n'as pas compris ce que j'expliquais.

    Pour l'instant, tu as quelque chose qui prend la forme 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
    class Mage{
       /* ..*/
    };
    class MageFeu : public Mage{
        public:
            void attaqueBase(Mage *);
            void bouleDeFeu(Mage *);
            void tempeteDeFeu(Mage *);
            void souffleArdent(Mage *);
            void poingDeFeu(Mage *);
    }
     
    class MageFoudre: public Mage{
        public:
            void attaqueBase(Mage *);
            void chargeElectrique(Mage *);
            void grondementDeLaFoudre(Mage *);
            void eclairDestructeur(Mage *);
            void poingDeFoudre(Mage *);
    }
    /*pareil pour tous les types de mages */
    soit 5 comportements d'attaque par type de mage, ce qui fait que tu as pour l'intant 5*4 = 20 fonctions d'attaque différentes et que, pour chaque type de mage que tu rajouteras, tu auras 5 nouvelles fonctions supplémentaires.

    Je te propose de modifier tes classes sous la forme beaucoup plus simple 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
    class Mage{
        public:
            /*virtual */ void attaquer(Mage * , Attaque const &);
       /* ..*/
    };
    class MageFeu : public Mage{
        public:
           /* supprimer les cinq attaques */
    }
     
    class MageFoudre: public Mage{
        public:
           /* supprimer les cinq attaques */
    }
    /*pareil pour tous les types de mages */
    en se basant sur le fait que l'attaque sait exactement :
    1. le nom qui la représente
    2. le nombre de points de mana qu'il faut pour l'utiliser
    3. le nombre de points de dégats qu'elle occasionne
    4. (éventuellement, le type d'attaque (feu / glace / air / terre/ eau) qui la représente)
    En agissant de la sorte, tu ne dois même plus savoir quel mage peut lancer quel sort : c'est le sort lui-même qui indique à tous les objets qui le manipulent ce qu'ils doivent savoir à son sujet.

    Par exemple, tu pourrais dire qu'un mage de glace a 50% de chances de rater un sort qui ne soit pas un sort de glace, qu'un mage de feu subit la moitié des dégats occasionnés par les sort de feu, mais le double de dégats occasionnés par un sort de terre, ou que sais-je : les possibilités n'ont pour seule limite que ton imagination

    Mais ce qui importe, c'est que tu n'as plus cette relation absurde de 1 sort qui peut être lancé est égal à une fonction au niveau du mage:

    Une attaque, quelle qu'elle soit, est considérée comme étant une attaque, et le seul comportement dont tu as besoin au niveau du mage est... de pouvoir lancer une attaque (qu'il s'agisse d'un sort ou d'une attaque normale)

    @iradille : en fait, je ne voulais pas trop m'écarter du code d'origine... Mais tu remarqueras que, si je fais un switch sur le type de mage, je n'ai en tout cas aucun besoin de transtyper le mage dans son type réel

    L'idéal serait, en effet, que chaque mage dispose de la liste des attaques qu'il est susceptible de lancer, et de faire en sorte de travailler avec cette liste à chaque fois.

    Mais bon, chaque chose en son temps, ce qu'il faut ici, c'est que clairetj comprenne qu'il est important de séparer les différents concepts : un mage est un concept donné, l'attaque (qui peut etre un sort) est un concept différent
    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

  15. #15
    Membre confirmé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Points : 604
    Points
    604
    Par défaut
    Ok merci koala01, je ferai les modifications se oir, en revanche une petite précision qui, je pense ne nuira pas à ce que tu viens de m'expliquer mais sait-on jamais.

    La méthode attaque de base appartient à la classe mère Mage donc avec le dernier code que tu m'as donné, à savoir
    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
     
    class Mage{
       /* ..*/
    };
    class MageFeu : public Mage{
        public:
            void attaqueBase(Mage *);
            void bouleDeFeu(Mage *);
            void tempeteDeFeu(Mage *);
            void souffleArdent(Mage *);
            void poingDeFeu(Mage *);
    }
     
    class MageFoudre: public Mage{
        public:
            void attaqueBase(Mage *);
            void chargeElectrique(Mage *);
            void grondementDeLaFoudre(Mage *);
            void eclairDestructeur(Mage *);
            void poingDeFoudre(Mage *);
    }
    /*pareil pour tous les types de mages */
    Il vaudrait mieux que je laisse la méthode attaque de base dans la classe mere ou est-ce qu'il est préférable de la mettre dans toutes les classes filles ???
    Si vous voulez suivre les différents championnats de football américain en France, en Europe et dans le Monde (en tout 32 pays différents), c'est sur www.fandefootus.fr

  16. #16
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par clairetj Voir le message
    Il vaudrait mieux que je laisse la méthode attaque de base dans la classe mere ou est-ce qu'il est préférable de la mettre dans toutes les classes filles ???
    Nul part.
    Relis les deux derniers posts de koala01, il t'expliques comment transformer ton code actuel qui contient une fonction par attaque (attaque de base comprise) en quelque chose de plus modulaire : plus de fonction pour les attaques, mais simplement une entrée dans un tableau d'attaques.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par clairetj Voir le message
    Ok merci koala01, je ferai les modifications se oir, en revanche une petite précision qui, je pense ne nuira pas à ce que tu viens de m'expliquer mais sait-on jamais.

    La méthode attaque de base appartient à la classe mère Mage donc avec le dernier code que tu m'as donné, à savoir
    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
     
    class Mage{
       /* ..*/
    };
    class MageFeu : public Mage{
        public:
            void attaqueBase(Mage *);
            void bouleDeFeu(Mage *);
            void tempeteDeFeu(Mage *);
            void souffleArdent(Mage *);
            void poingDeFeu(Mage *);
    }
     
    class MageFoudre: public Mage{
        public:
            void attaqueBase(Mage *);
            void chargeElectrique(Mage *);
            void grondementDeLaFoudre(Mage *);
            void eclairDestructeur(Mage *);
            void poingDeFoudre(Mage *);
    }
    /*pareil pour tous les types de mages */
    Il vaudrait mieux que je laisse la méthode attaque de base dans la classe mere ou est-ce qu'il est préférable de la mettre dans toutes les classes filles ???
    Ce code, c'est le code tel qu'il se présente pour l'instant chez toi.

    Ce que tu dois avoir, en utilisant une attaque, ressemble à
    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
    class Mage{
        public:
            /*virtual */ void attaquer(Mage * , Attaque const &);
       /* ..*/
    };
    class MageFeu : public Mage{
        public:
           /* supprimer les cinq attaques */
    }
     
    class MageFoudre: public Mage{
        public:
           /* supprimer les cinq attaques */
    }
    /*pareil pour tous les types de mages */
    les fonctions attaqueBase, bouleDeFeu, tempeteDeFeu, souffleArdent et poingDeFeu de ta classe MageFeu doivent être supprimées car elles ne servent plus à rien, de même que les fonction équivalentes pour les autres classes dérivées de Mage.

    Toutes ces fonctions sont remplacée par une seule, qui se trouve directement dans la classe de base Mage : attaquer(Mage * le_mage_attaque, Attaque const & l_attaque_choisie).

    Tu peux fournir un comportement par défaut directement dans la classe de base Mage qui ressemblerait à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void attaquer(Mage * le_mage_attaque, Attaque const & l_attaque_choisie){
        le_mage_attaque.subireAttaque(l_attaque_choisie);
    }
    mais, comme je te l'ai expliqué, tu peux aussi (bien que ce ne soit pas obligatoire ! ) décider de redéfinir ce comportement dans les classes dérivées (comprends :dans MageFeu, MageFoudre ou MageCeQueTuVeuxCommeSpecialisation ) pour faire en sorte qu'il ai un certain quota de chances de réussir (ou de rater) l'attaque si le sort n'appartient pas à sa spécialisation, ou pour faire en sorte que, étant "hyper spécialisé" ou d'un niveau si élevé, le mage fasse une attaque qui fera trois fois plus de dégats que si elle était lancée par "quelqu'un d'autre".

    Comme je te l'ai dit, les adaptations possibles n'ont qu'une seule limite : celles de ton imagination
    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

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

Discussions similaires

  1. [VC++] Problème avec un héritage
    Par Freakazoid dans le forum Visual C++
    Réponses: 7
    Dernier message: 28/11/2005, 08h35
  2. [DEBUTANT] Probléme avec l'héritage
    Par BRAUKRIS dans le forum Langage
    Réponses: 7
    Dernier message: 16/09/2005, 20h22
  3. Problème avec mon service mysql et PhpMyAdmin
    Par Fixazo dans le forum Outils
    Réponses: 1
    Dernier message: 28/08/2005, 18h02
  4. problème avec mon lecteur CD
    Par leo13 dans le forum Périphériques
    Réponses: 3
    Dernier message: 16/08/2005, 11h21
  5. Problème avec mon firewall ...
    Par Wis dans le forum Tomcat et TomEE
    Réponses: 15
    Dernier message: 06/04/2004, 08h46

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