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 :

structure et class


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de devdeb91
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    246
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2013
    Messages : 246
    Par défaut structure et class
    bonjour

    alors voila j'ai une class personnage mais pour ce personnage on doit retenir plein d'info sur lui par exemple xp, argent, force, etc... donc je me demande ne vaut t'il pas mieux changer la class en structure. seul probleme c'est que j'ai besoin des constructeur que on ne trouve pas dans les structure du coup j'aurai besoin de conseil.

    que feriez vous ?
    quel serais la meilleur solution ?

  2. #2
    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,

    De manière générale, une classe et une structure sont strictement identiques en C++, à une exception près: la visibilité par défaut de ses membres, qui est privée pour les classes et publique pour les structures.

    Ceci dit:

    Le meilleur moyen de définir des valeurs particulières pour une classe passe par son constructeur, en fournissant les arguments "qui vont bien" et, le cas échéant, en fournissant des valeurs par défaut.

    Il n'y a, a priori, aucun lien direct entre les différentes valeurs que tu peux vouloir utiliser pour ton personnage (force, xp, argent, mana, etc), il n'y a donc aucune raison de vouloir les regrouper "ailleurs" que dans ton personnage

    S'il y a des raisons pour placer des accesseurs sur ces valeurs (après tout, on s'attend de la part du personnage à ce qu'il puisse répondre à des questions comme "quelle est ta force / ton niveau / ton expérience / la somme d'argent dont tu disposes"), il n'y a pas lieu de fournir des mutateurs classiques:

    La plupart de ces valeurs seront modifiées dans certaines situations:
    • L'expérience augmente quand le personnage est avisé qu'il a tué son adversaire, dans une proportion dépendant de l'adversaire qu'il a tué (et e son propre niveau, par exemple)
    • Son mana diminue lorsqu'il décide de lancer un sort, en fonction de la quantité de mana pour ce faire et augmente quand le personnage décide de boire une potion, en fonction de la quantité de mana que la dite potion lui octroie, voir, d'une valeur donnée toutes les X secondes.
    • La somme d'argent dont il dispose augmente en fonction de ce qu'il ramasse
    • ...
    Toutes ces situations représentent autant de services que tu es sans doute en droit d'attendre de la part de ton personnage, et c'est de ce point de vue qu'il faut que tu en arrive à les manipuler
    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

  3. #3
    Membre éclairé Avatar de devdeb91
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    246
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2013
    Messages : 246
    Par défaut
    Je suis tout à fait d'accord avec ça mais au niveau des stats après ça fera sans doute beaucoup d'attributs privés non car si on observe bien à part les stats vie magie xp argent il faut retenir la force vitesse agilité résistance physique résistance magique force magique etc... ça fait beaucoup pour une classe non ?

  4. #4
    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
    Visiblement, tu n'as pas compris ce que je voulais expliquer.

    Ton personnage manipule en interne toutes ces données, mais il n'y a pas forcément lieu de créer une classe pour représenter son niveau, une autre pour représenter sa force et une troisième pour représenter la somme d'argent dont il dispose : de "simples" valeurs numériques sont amplement suffisantes

    L'idée est d'avoir une classe "personnage" qui pourrait ressembler à 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    class Personnage
    {
        public:
            Personnage(int level = 0, int gold=0, int strength=1, int mana=60,
                       int live = 60
                       /*, les autres auxquels je ne pense pas */):level_(level);
                       gold_(gold),strength_(strength), mana_(mana),
                       maxMana_(mana), live_(live), maxLive_(live)
                       /* tous les autres */
            {}
            /* on s'attend à pouvoir demander les différentes valeurs */
            int level() const{return level_;}
            int gold() const{return gold_;}
            int strenght () const{return strength_;}
            int mana() const{return mana_;}
            int maxMana() const{return maxMana_;}
            int live() const{return live_;}
            bool alive() const{return live_>0;}
            int maxLive() const{return maxLive_;}
            /* ce que j'ai oublié */
        private:
            int level_;
            int gold_;
            int strenght_;
            int mana_; // nombre de points de mana disponible
            int live_;  // nombre de points de vie disponible
            int maxMana_; // maximum de points de mana
            int maxLive_; // maximum de point de vie
            int experience_; // l'expérience actuelle
            int nextLevelAt_; // expérience requise pour le prochain niveau
            /* tous les autres */
            Inventaire inventory_;
    };
    Quand tu veux afficher les stats, tu n'as donc qu'à demander les différentes valeurs que tu veux afficher

    Ensuite, tu attends une série de services de la part de ton personnage, qui vont régulièrement manipuler l'une ou l'autre de ces données (ou parfois plusieurs!).

    Par exemple, on peut se dire que quand le personnage tue un ennemi, il se passe plusieurs choses simultanées:
    • il gagne un certain nombre de points d'expérience
    • il récupère une certaine somme d'argent sur l'ennemi
    • il peut récupérer certains objets d'inventaire
    • ... plein de choses qui dépendent de ton gameplay
    Certaines de ces choses peuvent d'ailleurs provoquer d'autres changements. Le fait de gagner de l'expérience peut, par exemple, te faire passer de niveau!

    Mais pour tuer un ennemi, il faut l'avoir attaqué, et c'est surtout cela qui va t'intéresser.

    Tu complèteras donc sans doute ton interface Personnage sous une forme 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
    class Personnage
    {
         /* tout ce dont j'ai parlé plus haut */
         public:
             void attack(Personnage & ennemy)
             {
                 ennemy.subitAttaque(/* ... */); 
                 if(! ennemy.alive())
                 {
                     gainXp(ennemy.xpToGain());
                     gainGold(ennemy.xpToGain());
                     pillerInventaire(ennemy.inventaire());
                 }
             }
    };
    ouppss... voila trois fonctions dont je n'ai pas parlé.

    En fait, gainXp, gainGold et pillerInventaire sont des comportements que le personnage peut avoir, mais dont on ne s'attend pas forcément à pouvoir appeler depuis "l'extérieur" (à par gainGold ou pillerInventaire )

    Il est donc bon de faire en sorte que seul les fonctions membres de Personnage puissent y avoir accès en les rendant privées, sous une forme 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
    class Personnage
    {
        /* tout ce dont j'ai parlé plus haut */
        private:
            void gainExperience(int toGain)
            {
                 experience_ += toGain;
                 if(experience_>= nextLevelAt_)
                 {
                     gainedLevel();
                 }
            }
            void gainGold(int toGain)
            {
                gold_ += toGain;
            }
            void pillerInventaire(Inventaire & toTake)
            {
                /* passer tous les objets  qui peuvent l'être de
                 * toTake à inventory_
                 */
            }
    };
    Et, décidément, je viens encore de rajouter une fonction inconnue: gainedLevel, qui prend "simplement" en charge les modifications à apporter lorsque l'on gagne un niveau, et qui pourrait ressembler à 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
    15
    16
    17
    18
    19
    20
    21
    class Personnage
    {
        /* tout ce dont j'ai parlé plus haut */
        private:
            void gainedLevel()
            {
                level_++; 
                /* pour le prochain niveau, il faut moitié plus d'expérience que
                 * pour le niveau actuel
                 */
               nextLevelAt_ = nexLevelAt_ * 1.5;
               /* en gagnant un niveau, on augmnte d'un tiers la mana maximale
                * et la vie maximale
                */
                manaMax_ = manaMax_ *4 / 3;
                liveMax_ = liveMax_ * 4 / 3;
                /* et on se retrouve avec la mana et la vie au maximum */
                live_= liveMax_;
                mana_ = manaMax_;
            }
    };
    Bien sur, ces comportements sont tels que je les imagine moi, avec des valeurs arbitraires choisies par moi, et peuvent parfaitement être adaptés selon ton propre gameplay

    Il n'est d'ailleurs pas exclu que tu veuille pouvoir faire gagner de l'or, de l'expérience ou du matériel autrement qu'en tuant un ennemi (en terminant une quête, en vendant ou en achetant du matériel, et autres possibilités).

    Certaines des fonctions dont je viens de parler ici (comme gainExperience ou gainGold) peuvent donc se retrouver en accessibilité publique et d'autres (gainedLevel), tout en restant privées, peuvent être virtuelles pour profiter du polymorphisme, afin que les stats soient modifiées de manière différentes si le personnage est un guerrier, un archer ou un magicien

    Mais ca, ca dépend de ton gameplay, du jeu que tu veux créer et de plein d'aspects que j'ignore pour l'instant

    Ce qui importe, c'est que tu te rendes compte de plusieurs choses:

    1. Tu peux accéder en lecture à tes différentes statistiques parce que cela correspond à certains services que tu es en droit d'attendre de la part de ton personnage
    2. Toute modification des statistiques passe d'office par l'appel d'un comportement spécifique de ton personnage
    3. Certains comportements de ton personnages peuvent être publics parce que ce sont des services que l'on est en droit d'attendre de sa part, d'autres ne sont que des "comportements internes" dont on n'a pas à s'occuper ailleurs qu'au niveau des différentes fonctions membres de personnage.
    4. Certains services que tu es en droit d'attendre de la part de ton personnage sont susceptibles, dans certaines circonstances, d'appeler d'autres comportements ou d'autres services, voire de modifier les statistiques de ton personnage.
    Tu dois donc penser à ton personnage en termes de services que tu es en droit d'attendre de sa part, et non en termes de données qu'il manipule.

    Les données qu'il manipulent sont, typiquement des "détails d'implémentation" qui permettent au personnage de rendre les services que l'on est en droit d'attendre de sa part

    Ainsi, j'aurais très bien pu regrouper tous les int dans un seul tableau, cela n'aurait rien changé pour l'utilisateur de la classe Personnage (même ca aurait changé le code pour accéder aux différentes stats au niveau des fonctions membres de Personnage )
    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

  5. #5
    Membre éclairé Avatar de devdeb91
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    246
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2013
    Messages : 246
    Par défaut
    Si si je suis très bien et je suis tout à fait d'accord tout ça été prévu c'est juste le fait qu'il y ait autant attribut car j'ai eu l'habitude de faire des classes avec 4-5 attributs privés max et là il y en a une dizaine du coup je ne savais pas si c'était vraiment bien d'en avoir autant en général quand j'en ai autant j'utilise des structures c'est cela qui me perturbait c'est tout après sur le reste ça je suis tout à fait d'accord avec toi.

  6. #6
    Membre éclairé Avatar de devdeb91
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2013
    Messages
    246
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2013
    Messages : 246
    Par défaut
    par ailleurs pour les monstres j'ai fait comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<int, SMonstre> monstre;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct SMonstre {
            SMonstre(std::string nom, int hp, int mp, std::string type, int exp, int gold):
                nom(nom), hp(hp), mp(mp), type(type), exp(exp), gold(gold){}
     
        std::string nom;
        int hp;
        int mp;
        std::string type;
        int exp;
        int gold;
     
    };
    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
    void chargemonstre(SMap & Map, string filename, int index)
    {
        cout << "chargement monstre" << endl;
     
        ifstream ifs(filename);
        int ligne = 0;
        while(!ifs.eof())
        {
            char c = ifs.get();
            if(c == '\n')
            {
                ligne++;
            }
        }
        //cout << "ligne " << ligne << endl;
     
        /*std::tr1::mt19937 gen(time(0));
        std::tr1::uniform_int <int> a(1,ligne);
        int lignechoisi = a(gen);*/
        //srand(time(0));
        int lignechoisi  = 0;
        lignechoisi = (rand() % ligne);
        cout << "ligne choisi " << lignechoisi << endl;
       /* ifs.clear();
        ifs.seekg(0, ios::beg);
        int pos = ifs.tellg();
        cout << "position " << pos << endl;*/
        ifs.close();
        ifs.open(filename);
    //    ifstream ifs(filename);
        //lignechoisi--;
        while(lignechoisi > 0)
        {
            //cout << "entrer 2eme boucle" << endl;
            char c = ifs.get();
            //cout << c << endl;
            if(c == '\n')
            {
                //cout << c << " trouver" << endl;
                lignechoisi--;
                //cout << "ligne " << lignechoisi << endl;
            }
            /*string nom;
            getline(ifs, nom);
            lignechoisi--;
            cout << nom << endl;*/
        }
     
        string nom;
        int hp;
        int mp;
        string type;
        int exp;
        int gold;
        //cout << "remplissage" <<  endl;
        ifs>>nom>>hp>>mp>>type>>exp>>gold;
     
        //cout << nom << " " << hp << " " << mp << " " <<
        //        type << " " << exp << " " << gold << endl;
        //cout << "fin remplissage" << endl;
        //Map.monstre.insert(std::make_pair(Position(joueur.x(), joueur.y()), SMonstre(nom, hp, mp, type, exp, gold)));
        Map.monstre.insert(std::make_pair(int(index), SMonstre(nom, hp, mp, type, exp, gold)));
    }
    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
    else if(Map.tileAt(joueur.x(), joueur.y()) == 'M')
               {
                   Map.monstre.clear();
                   srand(time(NULL));
                   int nbmonstre = 0;
                   while(nbmonstre == 0)
                   {
                       nbmonstre = rand() % 5;
                   }
                   string filename = Map.title + "_monstre" + ".txt";
                   cout << "nombre monstre " << nbmonstre << " " << "nom fichier " << filename << endl;
                   for(int i = 0; i < nbmonstre; i++)
                   {
                       chargemonstre(Map, filename, i);
                   }
     
                   for(int i = 0; i < nbmonstre; i++)
                   {
                       cout << "monstre " << i <<endl;
                      auto it = Map.monstre.find(i);
                   cout << it->second.nom << " " << it->second.hp <<" "<< it->second.mp << " " <<
                           it->second.type << " " << it->second.exp << " " << it->second.gold << endl;
                   }
               }
    est ce bien ? car maintenant que je vois mieux je me demande si c'est pas mieux de passer par une class monstre

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

Discussions similaires

  1. Structure ou classe ?
    Par progfou dans le forum C++
    Réponses: 5
    Dernier message: 01/10/2007, 14h27
  2. Schéma structure des classes
    Par delma dans le forum EDI et Outils pour Java
    Réponses: 8
    Dernier message: 29/11/2006, 16h52
  3. [log4j] structurer par classes
    Par frouge dans le forum Logging
    Réponses: 4
    Dernier message: 25/09/2006, 11h24
  4. Structure de classe dynamique
    Par amel666 dans le forum Langage
    Réponses: 2
    Dernier message: 24/01/2006, 09h13
  5. structure de class?
    Par kiko69 dans le forum C++
    Réponses: 4
    Dernier message: 13/03/2005, 14h30

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