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 :

[POO] Modifier un attribut depuis le main


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Lycéen
    Inscrit en
    Novembre 2009
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Novembre 2009
    Messages : 67
    Par défaut [POO] Modifier un attribut depuis le main
    Bonjour !

    je suis en train de réaliser une sorte de mini mini mini RPG et j'ai quelque soucis, j'essaye de faire en sorte que ce soit l'utilisateur qui fasse intéragir mes personnages (Bruce et Chuck).
    Seulement voilà:
    • J'ai fait un tuto au début (tres cours), mais a la fin du tuto je souhaite remettre la vie de mon personnage blessé au maximum. Mais je crois que la regle d'encapsulation me l'interdit, j'ai donc fait un getm_vie(), mais ca ne semble pas fonctionner.
    • Y a t-il moyen de rendre les commande moins lourde, car.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      cin << choix;
      if(choix == "bruce boire potion")
      {
            bruce.boirepotion(20);
      }
      if(choix == "chuck boire potion")
      {
           chuck.boirepotion(25); // Favoritisme :pp
      }
      if(choix == bruce attaquer chuck")
      {
           bruce.attaquer(Chuck);
      }
      Enfin vous avez compris, c'est pas super pratique



    Voilà mon code entier:
    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
    #include <iostream>
    #include <string>
    #include "Personnage.h"
     
    using namespace std;
     
     
    int main()
    {
        //Variable
        string choixtuto;
        // Création des personnages
        Personnage Bruce, Chuck("Epée aiguisée", 20, "Chuck");
     
        cout << "Bruce et Chuck sont dans l'arene ! Que souhaitez vous faire ?" << endl;
        cout << "TUTO: Selectionnez le personnage a utiliser, ensuite une action (boire potion, attaquer, lancer sort)" << endl;
        cout << "TUTO: Commencez par faire en sorte que Chuck attaque Bruce" << endl;
        cin >> choixtuto;
     
        if(choixtuto == "Chuck attaquer Bruce" || "chuck attaquer bruce")
        {
            chuck.attaquer(bruce);
            cout << "Bien joue, vous pouvez aussi afficher l'etat de votre personnage avec le nom suivis de etat, exemple: bruce etat" << endl;
            cout << "Amusez vous bien !" << endl;
            bruce.getm_vie() = 100;
        }
        else
        {
            cout << "Non, ce n'est pas ca ! Essayez: 'Chuck attaquer Bruce'" << endl;
            cin >> choixtuto;
        }
     
     
     
        return 0;
    }

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Bonjour

    Le mieux est de faire une fonction perso.restaure() qui restaure tous les points de vie du personnage.
    D'un point de vue syntaxique, tu peux aussi avoir le getter getm_vie() qui te retourne une référence pour pouvoir modifier directement la vie du personnage. Si tu fais ça, autant mettre l'attribut vie en public...

    Pour simplifier ton code, tu peux utiliser les références:
    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
    cin << nom;
    cin << action;
    cin << cible; // Si tu as une seule string, tu peux la découper avec un std::strinstream, ou avec boost (ou à la main)
     
    Personnage & perso = (perso == "bruce") ? bruce : chuck; // Il faut faire une fonction au lieu d'utiliser ce if bizarre, en plus cette fonction est appelée autre part
     
    if (action == "boire")
    {
        if (cible == "potion") { perso.boirepotion(); }
    }
    else if (action == "attaquer")
    {
        Personnage & perso_cible = (cible == "bruce") ? bruce : chuck;
        perso.attaquer(perso_cible);
    }
    Sinon, fait attention à la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Personnage Bruce, Chuck("Epée aiguisée", 20, "Chuck");
    car c'est équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Personnage Bruce; // Appel du constructeur par défaut
    Personnage Chuck("Epée aiguisée", 20, "Chuck");

  3. #3
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Personnage.h
    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
     
            class Personnage {
            public:
                    //Création du perso
                    Personnage( std::string nom ) : nom( nom ), force( 5 ), vie( 20 ) {}
                    //Revoyer les valeurs
                    std::string Nom() { return nom; }
                    const int Vie() { return vie; }
                    //Agir
                    void RecoitDegat( const int degats ) { vie -= degats; }
                    void DonneCoup( Personnage& p ) { p.RecoitDegat( force ); }
     
            private:
                    std::string nom;
                    int force;
                    int vie;
            };
    Scénario :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
            Personnage bruce( "Bruce" ), chuck( "Chuck" );
            std::cout << "Nom du perso : " << bruce.Nom() << ". Sa vie : " << bruce.Vie() << std::endl;
            while( bruce.Vie() > 0 ) {
                    chuck.DonneCoup( bruce );
                    std::cout << "Bruce n'a plus que " << bruce.Vie() << std::endl;
            }
            std::cout << "Bruce est mort." << std::endl;
    Ne passe pas par des strings pour tes comparaisons, généralement les fonctions sont faites pour cela, au pire il y a les enum

  4. #4
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Citation Envoyé par PilloBuenaGente Voir le message
    Ne passe pas par des strings pour tes comparaisons, généralement les fonctions sont faites pour cela, au pire il y a les enum
    ?

    Au passage, un peu de "chipotage" ^^
    Citation Envoyé par PilloBuenaGente Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //Revoyer les valeurs
    std::string Nom() { return nom; }
    const int Vie() { return vie; }
    //Agir
    void DonneCoup( Personnage& p ) { p.RecoitDegat( force ); }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //Revoyer les valeurs
    std::string const & Nom() const { return nom; }
    int Vie() const { return vie; }
    //Agir
    void DonneCoup(Personnage & p) const { p.RecoitDegat(force); }

  5. #5
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Envoyé par PilloBuenaGente Voir le message
    Ne passe pas par des strings pour tes comparaisons, généralement les fonctions sont faites pour cela, au pire il y a les enum
    Oula oui je ne me comprends même pas.
    Le if( choix == string ) n'est pas vraiment approprié, utilise :
    soit des fonctions différente, au lieu de trier le choix dans une seule fonction.
    soit des enum puis un switch :
    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
            enum {
                    FRAPPER,
                    MORDRE,
                    TUER
            };
     
            int action = FRAPPER;
     
            switch( action ) {
            case FRAPPER:
                    frapper;
                    break;
            case MORDRE:
                    mordre;
                    break;
            }
    std::string const & Nom() const { return nom; }
    Permet d'éviter la copie ?! Surtout si la string est grande ?!

  6. #6
    Membre confirmé
    Profil pro
    Lycéen
    Inscrit en
    Novembre 2009
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Novembre 2009
    Messages : 67
    Par défaut
    Une fois de plus merci de vos réponses (je dois vous donner plein de boulot :pp).

    @PilloBuenaGente:
    -Tu peux m'expliquer precisement enum ? Et pourquoi avec fait int action ?
    -Ce code affiche le nom et la vie du perso, et frappe bruce a mort c'est ca ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Personnage bruce( "Bruce" ), chuck( "Chuck" );
            std::cout << "Nom du perso : " << bruce.Nom() << ". Sa vie : " << bruce.Vie() << std::endl;
            while( bruce.Vie() > 0 ) {
                    chuck.DonneCoup( bruce );
                    std::cout << "Bruce n'a plus que " << bruce.Vie() << std::endl;
            }
            std::cout << "Bruce est mort." << std::endl;
    @Ehonn:
    -Super idée la fonction .
    -En revanche j'ai du mal a saisir les references.
    Pour moi une reference c'est ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    string adresse("escalope");
    string& adresseSecrete(adresse);
    cout << "vous habitez dans une " << adresse << endl;
    cout << "Oui, dans une " << adresseSecrete << endl;
    J'utilise donc par exemple dans mon Personnage.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void attaquer(std::string Personnage &cible, int nBdegats);
    {
          cible.m_vie -= nBdegats;
    }
    Mais n'ayant pas définis cible je ne pige pas :/. (J'ai recup le script sur le tuto que je fais)

  7. #7
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Tu peux m'expliquer precisement enum ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    enum {
       nom1,//Égal à 0
       nom2,//Égal à 1
       nom3//Égal à 2
       ....
    }
    Permet de remplacer des chiffres par des noms de variable, sert juste à mieux s'y retrouver.
    Ce code affiche le nom et la vie du perso, et frappe bruce a mort c'est ca ?
    C'est bien ça !
    Et pourquoi avec fait int action ?
    Dans ce cas il ne sert à rien... Tu peux en effet mettre directement...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    switch( FRAPPER ) { 
    }

  8. #8
    Membre confirmé
    Profil pro
    Lycéen
    Inscrit en
    Novembre 2009
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Novembre 2009
    Messages : 67
    Par défaut
    J'ai un petit soucis.
    Normalement la condition c'est que la variable choixtuto soit égal a Chuck attaque Bruce
    mais même si je marque n'importe quoi d'autre, la variable s'active:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if(choixtuto == "Chuck_attaquer_Bruce" || "chuck_attaquer_bruce")
        {
            chuck.attaquer(bruce);
            cout << "Bien joue, vous pouvez aussi afficher l'etat de votre personnage avec le nom suivis de etat, exemple: bruce etat" << endl;
            cout << "Amusez vous bien !" << endl;
            bruce.vieMax();
        }
        else
        {
            cout << "Non, ce n'est pas ca ! Essayez: 'Chuck attaquer Bruce'" << endl;
            cin >> choixtuto;
        }

  9. #9
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if(choixtuto == "Chuck_attaquer_Bruce" || "chuck_attaquer_bruce") =>
    if(choixtuto == "Chuck_attaquer_Bruce" || choixtuto == "chuck_attaquer_bruce")

  10. #10
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Citation Envoyé par Garwan50 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(choixtuto == "Chuck_attaquer_Bruce" || "chuck_attaquer_bruce")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(choixtuto == "Chuck_attaquer_Bruce" || choixtuto == "chuck_attaquer_bruce")
    Car tu fais une condition ou "chuck_attaquer_bruce", qui est un const char * et donc ça retourne l'adresse, qui est différente de 0 et donc c'est évalué à vrai (si c'est pas ça, c'est un truc du genre).

    Citation Envoyé par PilloBuenaGente Voir le message
    Le if( choix == string ) n'est pas vraiment approprié, utilise
    On teste des saisies utilisateur, comparer des std::string ne me choque pas plus que ça. Que ce soit d'un point de vue sécurité ou performance. Pour la sécurité, on pourrait définir des std::string constantes pour ne pas se tromper dans les choix possibles (mais ici, il n'y qu'un seul test par choix).

    Citation Envoyé par PilloBuenaGente Voir le message
    std::string const & Nom() const { return nom; }[/code]
    Permet d'éviter la copie ?! Surtout si la string est grande ?!
    Oui, même pour les petites
    La référence permet d'éviter la copie (et comme un std::string est forcément pluss grand qu'une adresse, cela est plus rapide, plus exactement, ce n'est jamais plus lent).
    Le const permet de ne pas modifier le std::string (comme lorsqu'on le passe pas copie).

    @Garwan50
    Voilà pour l'histoire des références et de la fonction.
    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
    // g++ -Wall -Wextra mini_mini_mini_rpg.cpp -o mini_mini_mini_rpg && mini_mini_mini_rpg
     
    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <vector>
    #include <stdexcept>
    #include <map>
     
     
    class personnage
    {
    private:
     
    	// Nom du personnage
    	std::string m_nom;
     
    	// Vie initiale du personne (le max)
    	unsigned int m_vie_initiale;
     
    	// Vie actuelle du personnage
    	unsigned int m_vie;
     
    	// Force du personnage
    	unsigned int m_force;
     
    public:
     
    	// Constructeur
    	personnage
    	(
    		std::string const & nom = "", // Valeur par défaut pour std::map
    		unsigned int const vie = 20,
    		unsigned int const force = 5
    	) :
    		m_nom(nom), m_vie_initiale(vie), m_vie(vie), m_force(force)
    	{ }
     
    	// Retourne le nom
    	std::string const & nom() const { return m_nom; }
     
    	// Retourne la vie initiale (la vie maximale)
    	unsigned int vie_initiale() const { return m_vie_initiale; }
     
    	// Retourne la vie actuelle
    	unsigned int vie() const { return m_vie; }
     
    	// Retourne la force
    	unsigned int force() const { return m_force; }
     
    	// Le personnage est vivant
    	bool est_vivant() const { return m_vie != 0; }
     
    	// Le personnage est mort
    	bool est_mort() const { return !est_vivant(); }
     
    	// Le personnage est blessé
    	void recoit_degat(unsigned int const nb_degat)
    	{
    		if (nb_degat >= m_vie) { m_vie = 0; }
    		else { m_vie -= nb_degat; }
    	}
     
    	// Le personnage frappe un autre
    	void donne_coup(personnage & victime) const { victime.recoit_degat(m_force); }
     
    	// Le personnage boit une potion
    	void boire_potion() { boire_potion(2); }
     
    	// Le personnage boit une potion
    	void boire_superpotion() { boire_potion(4); }
     
    	// Le personnage est entièrement soigné
    	void restaure() { m_vie = m_vie_initiale; }
     
    private:
     
    	// Le personnage boit une potion générique
    	void boire_potion(unsigned int const nb_point) { m_vie = std::min(m_vie + nb_point, m_vie_initiale); }
    };
     
     
    // Retourne une référence sur le personnage trouvé via son nom
    // Lance une exception sinon
    personnage & get_personnage_by_name(std::string const & nom_perso,std::vector<personnage> & persos)
    {
    	for (std::size_t i = 0; i < persos.size(); ++i)
    	{
    		if (persos[i].nom() == nom_perso) { return persos[i]; }
    	}
     
    	throw std::logic_error("Le personnage " + nom_perso + "n'a pas été trouvé");
    }
     
     
    // Programme principal
    int main()
    {
    	// Exemple
    	{
    		// Création des personnages
    		std::vector<personnage> persos;
    		persos.push_back(personnage("Bruce"));
    		persos.push_back(personnage("Chuck"));
     
    		// Aide utilisateur
    		std::cout << "Deux personnages (Bruce et Chuck) se battent." << std::endl;
    		std::cout << "Personnages possibles           : Bruce, Chuck" << std::endl;
    		std::cout << "Actions possibles               : boire, frapper" << std::endl;
    		std::cout << "Cibles possibles (selon action) : potion, superpotion, Bruce, Chuck" << std::endl;
    		std::cout << std::endl;
     
    		// Tant qu'un personnage n'est pas mort
    		while (persos.at(0).est_vivant() && persos.at(1).est_vivant())
    		{
    			// Variables pour la saisie utilisateur
    			std::string nom_perso;
    			std::string action;
    			std::string cible;
     
    			// Saisie utilisateur
    			std::cout << "Personnage ? "; std::cout.flush(); std::cin >> nom_perso;
    			std::cout << "Action ?     "; std::cout.flush(); std::cin >> action;
    			std::cout << "Cible ?      "; std::cout.flush(); std::cin >> cible;
     
    			// On recupère le personnage
    			personnage & perso = get_personnage_by_name(nom_perso, persos);
    			// Action
    			if (action == "boire")
    			{
    				if (cible == "potion")
    				{
    					perso.boire_potion();
    					std::cout << "Le personnage " << perso.nom() << " boit une potion, sa vie est de " << perso.vie() << std::endl;
    				}
    				else if (cible == "superpotion")
    				{
    					perso.boire_superpotion();
    					std::cout << "Le personnage " << perso.nom() << " boit une superpotion, sa vie est de " << perso.vie() << std::endl;
    				}
    				else if (cible == perso.nom())
    				{
    					std::cout << "Le personnage " << perso.nom() << " avale sa salive *glup*" << std::endl;
    				}
    				else if (cible == "Bruce" || cible == "Chuck")
    				{
    					std::cout << "Le personnage " << perso.nom() << " essaye de lécher son adversaire, mais celui-ci refuse !" << std::endl;
    				}
    				else
    				{
    					std::cout << "Le personnage " << perso.nom() << " refuse de boire une telle chose !" << std::endl;
    				}
    			}
    			else if (action == "frapper")
    			{
    				if (cible == perso.nom())
    				{
    					perso.donne_coup(perso);
    					std::cout << "Le personnage " << perso.nom() << " se blesse... sa vie est de " << perso.vie() << std::endl;
    				}
    				else if (cible == "Bruce" || cible == "Chuck")
    				{
    					personnage & victime = get_personnage_by_name(cible, persos);
    					perso.donne_coup(victime);
    					std::cout << "Le personnage " << perso.nom() << " frappe " << cible << ", la vie de " << cible << " est de " << victime.vie() << std::endl;
    				}
    				else
    				{
    					std::cout << "Le personnage " << perso.nom() << " frappe le vent. Ce n'est pas très efficace..." << std::endl;
    				}
    			}
    			else
    			{
    				std::cout << "Le personnage " << perso.nom() << " est limité, il ne comprend pas cette action" << std::endl;
    			}
    		}
    	}
     
    	// On peux aussi utiliser des std::map (le nom est inutile)
    	{
    		std::map<std::string, personnage> persos;
    		persos["Bruce"] = personnage("Bruce", 21);
    		persos["Chuck"] = personnage("Chuck", 42);
     
    		std::string nom_perso;
    		std::cout << "Personnage ? "; std::cout.flush(); std::cin >> nom_perso;
     
    		if (persos.find(nom_perso) != persos.end()) // Si on fait pas le find, la map va créer le personnage
    		{
    			std::cout << "Le personnage " << nom_perso << " a " << persos[nom_perso].vie() << " points de vie" << std::endl;
    		}
    		else
    		{
    			std::cout << "Le personnage " << nom_perso << " n'existe pas" << std::endl;
    		}
    	}
     
    	return 0;
    }

  11. #11
    Membre confirmé
    Profil pro
    Lycéen
    Inscrit en
    Novembre 2009
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Novembre 2009
    Messages : 67
    Par défaut
    Merci pour mon if, c'était encore une erreur bete :s.

    Ehonn, j'ai bien lu le programme que tu as écrit (d'ailleurs je te remercie ca a du prendre du temps)

    J'ai cependant quelques questions :/:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    personnage & get_personnage_by_name(std::string const & nom_perso,std::vector<personnage> & persos) // get_personnage_by_name est le nom de la fonction. Pourquoi mettre nom_perso ainsi que persos(qui est le tableau qui regroupe tout les personnages) en reference ? Je ne comprends pas ce que ca change.
    {
    	for (std::size_t i = 0; i < persos.size(); ++i) // Tant que i est inférieur a la tailles du tableau, alors on ajoute 1 a i.
    	{
    		if (persos[i].nom() == nom_perso) { return persos[i]; } // Si la case du tableau est égal au nom du personnages, alors on affiche la case
    	}
     
    	throw std::logic_error("Le personnage " + nom_perso + "n'a pas été trouvé"); // sinon il y a une erreur (qu'est ce que throw ainsi que logic error ?
    }
    C'est bizarre je trouve ca extremement complexe, je comprends limite rien au programme, pourquoi il y a des & partout ainsi que des const ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void boire_potion(unsigned int const nb_point) { m_vie = std::min(m_vie + nb_point, m_vie_initiale); } // qu'est ce que std::min ? Que fait cet fonction ??
    Et la:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::cout << "Le personnage " << nom_perso << " a " << persos[nom_perso].vie() << " points de vie" << std::endl; // Pourquoi ne pas faire nom_perso.vie() plutot ?
    J'ai beau lire je comprends pas :SS

  12. #12
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Citation Envoyé par Garwan50 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    personnage & get_personnage_by_name(std::string const & nom_perso,std::vector<personnage> & persos) // get_personnage_by_name est le nom de la fonction. Pourquoi mettre nom_perso ainsi que persos(qui est le tableau qui regroupe tout les personnages) en reference ? Je ne comprends pas ce que ca change.
    {
    	for (std::size_t i = 0; i < persos.size(); ++i) // Tant que i est inférieur a la tailles du tableau, alors on ajoute 1 a i.
    	{
    		if (persos[i].nom() == nom_perso) { return persos[i]; } // Si la case du tableau est égal au nom du personnages, alors on affiche la case
    	}
     
    	throw std::logic_error("Le personnage " + nom_perso + "n'a pas été trouvé"); // sinon il y a une erreur (qu'est ce que throw ainsi que logic error ?
    }
    C'est bizarre je trouve ca extremement complexe, je comprends limite rien au programme, pourquoi il y a des & partout ainsi que des const ?
    T & permet d'avoir une référence (sur une variable de type T), le const (s'applique à ce qu'il y a avant, s'il n'y a rien avant, s'applique à ce qu'il y a derrière) permet de ne pas la modifier (accidentellement).

    Une référence permet de ne pas copier l'objet.
    Une référence permet donc de modifier l'objet lui même.

    La fonction prend un nom à chercher (en référence sur membre constant (const &) pour éviter une copie inutile) et un tableau de personnage en référence (pour ne pas copier les personnages, on verra plus tard pourquoi c'est utile).
    La fonction cherche le personnage demandé (la boucle for). Si elle ne le trouve pas, on arrive à la fin de la boucle et on envoie une exception. Si on trouve le personnage, on renvoie une référence sur ce dernier (pour ne pas le copier, on va voir pourquoi maintenant).
    Lorsqu'on cherche un personnage avec la fonction, on veut pouvoir écrire get_personnage_by_name("Bruce", persos).boire_potion();. Si on ne retourne pas de référence dans la boucle for, Bruce sera copié et c'est sa copie qui boira la potion. Du coup le Bruce qui est dans le tableau persos ne boira pas la potion Si on ne passe pas le tableau de personnages persos en référence, on copie l'ensemble des personnages et donc on ne pourra pas faire boire le Bruce qui est dans le tableau original

    La boucle for parcoure un tableau (qui contient les personnages). std::size_t est un entier positif. On aurait pu utiliser un int mais c'est moins propre.
    ++i ajoute 1 à i, comme i++ et i += 1 (c'est équivalent dans ce contexte). La différence est que ++i est une preincrementation et i++ une postincremantation.
    Tu peux jouer à afficher std::cout << ++i << std::endl; std::cout << i << std::endl; std::cout << i++ << std::endl; std::cout << i << std::endl; dans un programme pour comprendre.

    Dans le if, on cherche une correspondance entre le nom du personnage demandée (nom_perso) et les personnages qu'on à (persos). Les personnages sont donc identifiés par leur nom. Si on le trouve, on retourne une référence sur ce personnage.

    Les exceptions permettent de gérer proprement les "erreurs". Ici on veut que notre fonction retourne un personnage. Si ce personnage n'est pas trouvé, on a clairement un bug dans notre programme. Lancer une exception permet au programmeur d'être averti. Si l'exception n'est pas attrapée grâce à un catch, le programme d'arrêtera.
    C++ fournit des classes pour lancer des exceptions (#include <stdexcept>) dans différents cas.
    FAQ C++ - Les exceptions
    http://www.cplusplus.com/reference/stdexcept/

    --- --- ---

    Citation Envoyé par Garwan50 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void boire_potion(unsigned int const nb_point) { m_vie = std::min(m_vie + nb_point, m_vie_initiale); } // qu'est ce que std::min ? Que fait cet fonction ??
    std::min est une fonction de la bibliothèque standard de C++ (#include <algorithm>). Elle prend deux paramètre et renvoie le minimum entre les deux.
    Ici ça renvoie le minimum entre m_vie + nb_point et m_vie_initiale. On ne veut pas que le personnage aie plus de point de vie qu'à son état de base qui était le maximum.
    C'est quasi-équivalent à ce code (plus gros et donc moins lisible) (il faudrait passer par une variable intermédiare pour ne pas faire deux fois les calculs) :
    [code]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void boire_potion(unsigned int const nb_point)
    {
        if (m_vie + nb_point <= m_vie_initiale) { return m_vie + nb_point };
        else { return m_vie_initiale; }
    }
    --- --- ---

    Citation Envoyé par Garwan50 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::cout << "Le personnage " << nom_perso << " a " << persos[nom_perso].vie() << " points de vie" << std::endl; // Pourquoi ne pas faire nom_perso.vie() plutot ?
    std::map peut être vue comme un tableau associatif. Lorsque tu utilises des tableaux, les indices sont des entiers positifs.
    Pour une std::map<std::string, T>, on stocke des T et les indices sont des std::string.
    http://www.cplusplus.com/reference/map/map/map/

    La variable nom_perso est un std::string, pas un personnage.

  13. #13
    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, il faut absolument éviter autant que possible de comparer des chaines de caractères pour une raison toute simple : ce genre de comparaison est, par nature, excessivement lente.

    De plus, cela oblige le joueur à introduire exactement la chaine de caractères que tu attends, ce qui implique que la moindre faute de frappe (une lettre oubliée, par exemple) enverra ton programme dans les choux... et je ne parle pas des actions qui ne sont simplement pas prévues

    L'idée serait plutôt de faire une sorte de menu dans lequel tu indiquerais toi même l'action que le joueur peut effectuer associée à un numéro d'ordre, et à demander à l'utilisateur d'introduire le numéro de l'action qu'il envisage.

    Ca prendrait, par exemple, 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
    25
    void afficheMenu()
    {
        std::cout<<"1 - Chuck frappe Bruce"<<std::endl
                 <<"2 - Bruce frappe Chuck"<<std::endl
                 <<"3 - Chuck boit potion"<<std::endltt
                 <<"4 - Bruce boit potion"<<std::endl
                 <<" les autres possibilites s'il y en a ;)"<<std::endl;
                 <<"0 - Quitter "<<std::endl
                 <<"    Introduisez votre choix (0 - X)"; 
    }
    int choisirAction()
    {
        int choix = -1; // pour être sur d'entrer une fois dans la boucle
        while(choix >=0 && choix <=4) // pour l'instant, on a 4 possibilités ;)
        {
            afficherMenu();
            cin>>choix;
            if(choix < 0 || choix > 4)
            {
                std::cout<<"veuillez introduire une valeur comprise entre 1 et 4"
                         <<std::endl;
            }
        } 
        return choix;
    }
    Le tout serait utilisé 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
    24
    25
    26
    27
    28
    29
    int main()
    {
       /* ce qu'il faut d'initialisation ;) */
        int choix = -1; // pour être sur de passer une fois dans la boucle
        while(choix != 0) // 0 c'est quitter ;)
        {
            choix= choisirAction();
            switch (choix)
            {
                case 1 : // "Chuck frappe Bruce" ;)
                    /* ce qu'il faut faire */
                    break;
                case 2 : // "Bruce frappe Chuck"
                    /* ce qu'il faut faire */
                    break;
                case 3 : //"Chuck boit potion"
                    /* ce qu'il faut faire */
                    break;
                case 4 : //"Bruce boit potion"
                    /* ce qu'il faut faire */
                    break;
                default : //" 0- Quitter"
                    std::cout<<"Merci d'avoir utilise ce merveilleux jeux, a bientot";
     
            }
            /* finalisation et "nettoyage" */
            return 0;
        }
    }
    Citation Envoyé par Ehonn Voir le message
    D'un point de vue syntaxique, tu peux aussi avoir le getter getm_vie() qui te retourne une référence pour pouvoir modifier directement la vie du personnage.
    Quelle horreur, non, surtout pas, malheureux!!

    On ne peut jamais (*) renvoyer une référence non constante sur un accesseur !!!

    C'est le meilleur moyen de perdre tout à fait le controle sur le membre renvoyé et d'arriver très facilement à s'étonner que la valeur ne soit pas celle à laquelle on s'attend

    (*) sauf pour quelques cas particuliers dans lesquels la classe ne sert que de "helper", comme les classes "itérateur" (non constant), car ce genre de classe est "simplement" destiné à "chacher" la structure interne réelle d'une autre classe
    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

  14. #14
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Citation Envoyé par koala01 Voir le message
    De manière générale, il faut absolument éviter autant que possible de comparer des chaines de caractères pour une raison toute simple : ce genre de comparaison est, par nature, excessivement lente.
    Cet argument ne s'applique pas vraiment ici. Il y a une saisie utilisateur.
    Pour la sécurité contre les fautes de frappe, j'ai proposé de fournir des constantes (mais toujours des strings).
    Si tu demandes à l'utilisateur de taper des numéros, ça change le gameplay.

    ---

    Citation Envoyé par koala01 Voir le message
    Citation Envoyé par Ehonn Voir le message
    D'un point de vue syntaxique, tu peux aussi avoir le getter getm_vie() qui te retourne une référence pour pouvoir modifier directement la vie du personnage.
    Quelle horreur, non, surtout pas, malheureux!!

    On ne peut jamais (*) renvoyer une référence non constante sur un accesseur !!!

    C'est le meilleur moyen de perdre tout à fait le controle sur le membre renvoyé et d'arriver très facilement à s'étonner que la valeur ne soit pas celle à laquelle on s'attend

    (*) sauf pour quelques cas particuliers dans lesquels la classe ne sert que de "helper", comme les classes "itérateur" (non constant), car ce genre de classe est "simplement" destiné à "chacher" la structure interne réelle d'une autre classe
    Tu as coupé ma citation !

    Citation Envoyé par Ehonn Voir le message
    D'un point de vue syntaxique, tu peux aussi avoir le getter getm_vie() qui te retourne une référence pour pouvoir modifier directement la vie du personnage. Si tu fais ça, autant mettre l'attribut vie en public...
    J'ai bien précisé que c'était valide sur le plan syntaxique. Et la dernière phrase dit que ça brise les règles d'encapsulation. J'aurais pu être un petit peu plus explicite.

    Autres exceptions: tous les conteneurs

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    Cet argument ne s'applique pas vraiment ici. Il y a une saisie utilisateur.
    Pour la sécurité contre les fautes de frappe, j'ai proposé de fournir des constantes (mais toujours des strings).
    Si tu demandes à l'utilisateur de taper des numéros, ça change le gameplay.
    Ca change peut etre le game play mais ca le rend, d'une certaine manière, bien plus agréable à l'utilisateur.

    Et, surtout, ca prend en compte le fait que l'origine de tous les bugs se trouve entre la chaise et le clavier (autrement dit, que l'utilisateur doit être considéré par défaut comme un imbécile distrait )

    J'ai d'ailleurs passé ce point sous silence dans le code, mais il faudrait prévoir de valider le fait que l'entrée utilisateur est bel et bien une valeur numérique
    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

  16. #16
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ca change peut etre le game play mais ca le rend, d'une certaine manière, bien plus agréable à l'utilisateur.

    Et, surtout, ca prend en compte le fait que l'origine de tous les bugs se trouve entre la chaise et le clavier (autrement dit, que l'utilisateur doit être considéré par défaut comme un imbécile distrait )
    Raison de plus pour lui pourrir la vie avec un gameplay en carton XD
    Vengeance !

  17. #17
    Membre confirmé
    Profil pro
    Lycéen
    Inscrit en
    Novembre 2009
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Novembre 2009
    Messages : 67
    Par défaut
    Bonjour et merci a vous deux.

    Vos explications ont vraiment été tres clair et j'ai appris pas mal de truc, nottament que si je ne comprends pas tes scripts Ehonn, c'est car (je pense) qu'ils sont trop simplifiés pour moi, et le code ne me parrait pas du tout familier et je m'y perd ^^.

    Sinon koala01, merci pour ces clarifications, ainsi que cet méthode, j'avoue que je n'aurais pas eu l'idée de le faire comme ca moi même, j'ose esperer que j'aurais ce genre d'habitude plus tard.

    Je vais donc continuer mon programme, merci beaucoup.

  18. #18
    Membre confirmé
    Profil pro
    Lycéen
    Inscrit en
    Novembre 2009
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Novembre 2009
    Messages : 67
    Par défaut
    J'ai juste un petit soucis.
    Quel est le meilleur moyen d'afficher le nom de l'objet concerner

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Personnage::attaquer(Personnage &cible) // En gros je souhaiterais afficher cet argument
    {
           cible.recevoirDegats(35);
                cout << m_nomPersonnage << " frappe "  << endl; // Je voudrais l'afficher là
            }

  19. #19
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Le mieux est de surcharger l'opérateur << entre un flux et un personnage, ce qui te permettra d'écrire std::cout << m_nomPersonnage << " frappe " << cible << std::endl;.
    FAQ C++ - Comment utiliser les flux pour afficher ou saisir mes objets ?

    Mais ici, si tu veux afficher uniquement le nom du personnage, tu peux te contenter de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::cout << m_nomPersonnage << " frappe " << cible.nomPersonnage() << std::endl;

  20. #20
    Membre confirmé
    Profil pro
    Lycéen
    Inscrit en
    Novembre 2009
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Novembre 2009
    Messages : 67
    Par défaut
    Merci ! Mais quand je met ca ca affiche cet erreur:

    In member function 'void Personnage::lancerSort(int, Personnage&)'
    |58|error: no match for call to '(std::string {aka std::basic_string<char>}) ()'|
    ||=== Build finished: 1 errors, 0 warnings (0 minutes, 1 seconds) ===|

    Extrait du code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void Personnage::lancerSort(int sortfeu, Personnage &cible)
    {
            if(sortfeu == 1 && m_mana >= 50)
            {
                cible.recevoirDegatsMagique(35);
                m_mana -= 50;
                cout << m_nomPersonnage << " lance un sort de feu de 35 de degats pour 50 de magie sur " << cible.m_nomPersonnage() << endl;
            }
            else
            {
                cout << "Vous n'avez pas assez de mana une fois";
            }
    }
    J'ai encore du mal a me familiariser avec les objets, j'espere que je finirais par tout comprendre

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [POO] Modifier un attribut du style sous Internet Explorer
    Par julien_mok dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 25/11/2008, 23h55
  2. Réponses: 6
    Dernier message: 30/10/2007, 15h04
  3. [POO] Modifier attributs d'un objet par référence
    Par justSam dans le forum Langage
    Réponses: 8
    Dernier message: 22/02/2007, 07h58
  4. [POO] Acces aux attributs d'un objet depuis une methode evenement :s
    Par NikoGJ dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 13/07/2006, 19h01
  5. [VBA-E]modifier les attributs d'un commentaire dans une cellule
    Par Olivier vb dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 15/03/2004, 10h26

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