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 :

crash de programme


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2013
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2013
    Messages : 38
    Points : 24
    Points
    24
    Par défaut crash de programme
    Bonjour,

    J'ai un souci avec mon programme. Je peux compiler et tout marche, mais lorsqu'une fonction est appelée le programme plante ("RPD.exe a cessé de fonctionner"). J'ai essayé le debugger et il me dit que j'ai une erreur de segmentation. J'ai pas mal cherché mais je n'arrive pas a le résoudre. Je sais que le problème vient de cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Personnage::deplacer(Case position)
    {
        m_position->pointeZero();    
        m_position=&position;
    }
    où Case et Personnage sont deux classes, m_position un pointeur de type classe déclaré comme suit, et pointeZero la fonction ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void pointeZero();
    void Case::pointeZero()   {m_occupant = 0;}
     
    void deplacer(Case position);
    Case *m_position;
    Cette fonction est appelée selon 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
       int tailleX(5);
        int tailleY(5);
        Case tabCase[tailleX][tailleY];         //création d'un tableau de case
     
         std::vector<Personnage> persos;     
    		persos.push_back(Personnage("David"));
    		persos.push_back(Personnage("Goliath"));
     
        for (int i=0;i<persos.size();i++)
        {                    
            cout << "Placez " << persos[i].getName() << " en inscrivant les coordonnees x puis y : ";
            cin >> posX;
            cin >> posY;
            persos[i].deplacer(tabCase[posX][posY]);
        }
    J'imagine que c'est un problème tout simple mais je débute, et les pointeurs sont encore une entité mystique à craindre....

    Merci d'avance

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    il te faut lire le cours sur la portée et la durée de vie des variables.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Personnage::deplacer(Case position)
    {
        m_position->pointeZero();    
        m_position=&position;
    }
    position est une variable temporaire, détruite à la sortie de la méthode.
    Tu crées un pointeur vers quelque chose qui sera détruit.
    Quand tu voudras l'utiliser, le pointeur sera pourri puisque pointant vers de la mémoire qui n'existe plus vraiment.
    Au mieux ça crash, parfois les conséquences sont bien pires !
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    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 bl4cksky Voir le message
    Bonjour,

    J'ai un souci avec mon programme. Je peux compiler et tout marche, mais lorsqu'une fonction est appelée le programme plante ("RPD.exe a cessé de fonctionner"). J'ai essayé le debugger et il me dit que j'ai une erreur de segmentation. J'ai pas mal cherché mais je n'arrive pas a le résoudre. Je sais que le problème vient de cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Personnage::deplacer(Case position)
    {
        m_position->pointeZero();    
        m_position=&position;
    }
    où Case et Personnage sont deux classes, m_position un pointeur de type classe déclaré comme suit, et pointeZero la fonction ci-dessous :
    Attention: danger...

    Je présumes que si m_position est un pointeur, c'est sans doute parce que tu veux faire une relation bidirectionnelle entre ta case et ton personnage:
    La cas doit fournir l'accès à ton personnage, et ton personnage doit fournir l'accès à la case.

    Seulement, si tu travailles comme tu le fait, quand tu invoque
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perso->deplacer(tabCase[index]);
    (ou toute syntaxe similaire), tu transmet une copie temporaire de tabCase[index] à ta fonction.

    Déjà, cela signifie que rien de ce que tu pourras faire, dans ta fonction deplacer, à position ne sera répercuté sur la case qui a été utilisée comme paramètre (tabCase[index]).

    Mais, surtout, et c'est beaucoup plus grave, cela signifie que, le paramètre position sera détruit au moment où l'on atteindra l'accolade fermante de la fonction, et donc que l'adresse de cette variable deviendra invalide.

    Cela signifie que le pointeur membre m_position de ta classe Personnage représentera une adresse invalide, et donc que toute tentative d'utilisation de ce pointeur ne pourra donner qu'un seul résultat: un comportement indéfini ("undefined behaviour), qui se traduira généralement par une erreur de segmentation.

    En outre, il ne devrait pas être de la responsabilité de ton personnage d'aller modifier en quoi que ce soit la case sur laquelle il se trouve.

    Je m'explique:

    Ton personnage doit être en mesure d'indiquer sa position dans un système de coordonnées (A3 ou 2,5 comme tu veux ), mais n'a strictement aucun besoin de savoir... ce qui se trouve réellement sous ses pieds.

    La case, quant à elle, doit aussi être "identifiée" par un système de coordonnées (toujours A3 ou 2,5), et doit "uniquement" pouvoir dire s'il y a un personnage ou non sur "sur elle", et, le cas échéant, pouvoir fournir l'accès au personnage qui est sur elle.

    "Tout ce qu'il te faudrait", c'est "quelque chose" qui puisse accéder à toutes les cases et dont la responsabilité unique serait de... "concrétiser" les déplacements de tes personnages.

    C'est à dire qu'il aurait trois communications à faire:
    • indiquer à la case d'origine que le personnage s'en va
    • indiquer à la case de destination s'en vient
    • indiquer sa nouvelle possition au personnage.
    De cette manière, tu n'aurais meme plus de dépendance circulaire, et chaque classe aurait sa propre responsabilité

    Il ne resterait, au final, plus qu'à mettre en place un système simple et efficace pour pouvoir faire la transition entre une position (une coordonnée en fait) et la case qui correspond à cette coordonnée, afin de pouvoir facilement accéder à la case correspondante.

    Enfin, la "touch of class" consisterait à ne pas considérer ton tableau comme une matrice deux dimensions (que tu initialise d'ailleurs très mal ) mais comme un tableau à une seule dimension contenant Lignes * Colonnes éléments. Pour accéder à la case se trouvant à la ligne l et à la colonne c, tu pourrait alors utiliser la formule index = l * Colonnes + c.

    au final, je te conseillerais bien travailler de la sorte:

    Une classe Coordonnee qui se contente de fournir les valeurs d'abscisse et de coordonné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
    class Coordonnee{
        public:
            Coordonnee(int x, int y):x_(x),y_(y){}
            int x() const{return x_;}
            int y() const{return y_;}
        private:
            int x_;
            int y_;
    };
    Une classe "Case", identifiable par une coordonnée, dont la responsabilité est de représenter "physiquement" une position sur ton plateau de jeu.

    Elle sera en mesure de savoir qu'un personnage arrive / part, devra pouvoir nous dire s'il y a un personnage sur elle, et, le cas échéant, pouvoir nous donner l'accès à ce personnage.

    Elle ressemblera à 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
    class Case{
        public:
            /* C++11 inside ;) */
            Case(Coordonnee const & coord):coord_(coord),perso_(nullptr){}
            /* respectons la loi de déméter: l'utilisateur n'a pas "forcément" besoin
             * de connaitre le type Coordonnee pour récupérer l'abscisse ou
             * l'ordonnée de la case
             */
            int x() const{return coord_.x();}
            int y() const{return coord_.y();}
            /* par contre, ca peut quand meme etre utile ;) */
            Coordonnee const & coordonnee() const{return coord_;}
            /* on veut pouvoir indiquer que le personnage s'en va */
            void persoQuitte(){perso_ = nullptr;}
            /* on veut pouvoir indiquer que le personnage s'en vient */
            void persoArrive(Personnage * p){perso_=p;}
            /* on veut savoir la case est libre */
            bool estLibre() const{return perso_== nullptr;}
            /* on veut pouvoir récupérer le personnage qui est sur la case */
            Personnage * perso() {return perso_;}
        private:
            Coordonnee coord_;
            Personnage * perso_;
    };
    Une classe "Plateau" qui correspond au plateau de jeu, dont la responsabilité est de maintenir l'indispensable cohérence entre les plateau de jeu.

    Il devra permettre l'ensemble des manipulation possibles pour toutes les cases qui le composent et ressemblera donc sans doute à 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
    34
    35
    36
    37
    38
    39
    class Plateau{
            /* converti une coordonnée en index  */
            int versIndex(Coordonnee const & c){
                return c.y()*colonnes_ + c.x();
            }
        public:
            Plateau(int lignes, int colonnes):lignes_(lignes),colonnes_(colonnes){
                /*on crée lignes_ * colonnes_ cases identifiée par leur coordonnées 
                 */
                for(int i=0;i<lignes_;++i){
                    for(int j = 0; j<colonnes_;++j){
                        cases_.push_back(Case(Position(j,i));
                    }
                }
            }
            /* on veut savoir si une case donnée est libre */
            bool estLibre(Coordonnee const & c){
                return case_[versIndex(c)].estLibre();
            }
            /* on veut indiquer qu'un personnage quitte une case donnée */
            void persoQuitte(Coordonnee const & c){
                cases_[versIndex(c)].persoQuitte();
            }
            /* on veut indiquer qu'un personnage arrive sur une case donnée 
             */
            void persoArrive(Personnage * p, Coordonnee const & c){
                cases_[versIndex(c)].persoArrive(p);
            }
            /* on veut pouvoir récupérer le personnage qui se trouve sur une
             * case donnée
             */
           Personnage * persoSurCase(Coordonnee const & c){
               return case_(versIndex(c)].perso();
           }
        private:
            int lignes_;
            int colonnes_;
            std::vector<Case> cases_;
    };
    Evidemment, il nous faut une classe "Personnage".

    Il est identifiable par un nom qui lui est propre et il est (essentiellement) localisable. A ce titre, il doit pouvoir se déplacer vers de nouvelles coordonnées.

    La classe ressemblera donc à 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
    class Personnage{
        public:
            Personnage(std::string const & nom, Coordonnee const & c):
                      nom_(nom), coord_(c){}
             std::string const & nom() const{return nom_;}
             /* respectons, encore, la loi de déméter ;) */
             int x() const{return coord_.x();}
             int y() const{return coord_.y();}
             Coordonnee const & coordonnee() const{return coord_;}
             /*et donnons lui l'occasion de se déplacer */
             void moveTo(Coordonnee const & c){coord_ = c;}
        private:
            std::string nom_;
            Coordonnee coord_;
    };
    Il ne nous reste plus qu'une dernière classe à mettre au point.

    Enfin, normalement, il en faudrait encore d'autres, mais je m'arrêterai là car je vais finir par écrire un roman autrement
    Je vais la nommer "mover" et son role sera de répercuter correctement les déplacement d'un personnage sur les cases du plateau.

    Cette classe peut très bien servir de foncteur, ce qui fait qu'il n'y aura qu'une seule fonction de définie : l'opérateur () et ressemblera à 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
    struct Mover { /* struct et class sont strictement pareil en C++, à
                   * l'exception de la visibilité par défaut ;) 
                   */
        Mover(Plateau & pl, Personnage * perso):pl_(pl),perso_(perso){}
        Plateau & pl_;
        Personnage * perso_;
        void operator()(Coordonne const & c){
            /* on récupère la coordonnée actuelle du personnage */
            Coordonnee const & old = perso_->coordonnee();
            /* on indique au plateau que le personnage quitte cette coordonnée */
            pl.persoQuitte(old);
            /* on indique au plateau que le personnage arrive sur la nouvelle
             * coordonnee
             */
            pl.persoArrive(c);
            /* on indique la nouvelle coordonnee au personnage */
            perso->moveTo(c);
        }
    };
    Une fois que tu as tout cela, le reste devient un jeu d'enfant
    tu crées un plateau aux dimensions que tu veux, autant de personnages que tu veux, et tu utilise la classe Mover pour faire bouger tes personnage.

    Cela 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
    int main(){
        Personnage * current =  new Personnage("Goliath", Coordonnee(0,0)); // il faut bien savoir quel perso va bouger ;)
        Personnage * next = new Personnage("David", Coordonnee(10,10)); // et celui qui bougera au tour suivant
        Plateau plateau(10,10);
         /* on place les joueurs sur le plateau */
        plateau.persoArrive(current,current->position());
        plateau.persoarrive(next,next->position());
        bool encore = true; // la condition de fin de jeu ;)
        while(encore){
            int x;
            int y;
            std::cout<<"veuillez indiquer le déplacement pour "<<current->nom()<<std::endl;
            std::cout<<"l'abscisse :";
            std::cin>>x;
            std::cout<<"et l'ordonnee :";
            std::cin>>y;
            /* deux lignes pour le déplacement :D */
            Mover m(plateau, current);
            m(Coordonnee(x,y));
            /* n'oublie pas de vérifier si le fin du jeu est atteint ;) */
            /* on inverse les joueurs pour le tour suivant */
            std::swap(current, next);
        }
        /* on libère correctement les deux joueurs */
        delete current;
        delete next;
        return 0;
    }
    NOTA: j'ai gardé une approche simple, mais le principal est là
    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

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2013
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2013
    Messages : 38
    Points : 24
    Points
    24
    Par défaut
    bonjour,

    D'abord merci pour vos réponses rapides.

    @Koala01

    Merci d'avoir répondu de façon si ... complète . Mais il me reste quelques questions :

    -D'abord une question bête. Tu initialise souvent tes fonctions comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type nom(arguments)  const &  {fonction}
    A quoi sert l'esperluette? Ça signifie que la valeur retournée est une référence?

    -Une classe coordonnes est-elle vraiment nécessaire? Est-ce que c'est juste une question d'accessibilité? on pourrait juste donner des attributs aux classes Cases et Personnage, avec une méthode d'accession.

    -Dans la classe Case tu utilise une fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Personnage * perso {return perso;}
    Cette fonction est censée retourner un pointeur vers le personnage présent sur la case c'est ça? Et dans ce cas la déclaration en Private ne devrait pas être avec une étoile puisque c'est un pointeur?
    Autre chose : dans le constructeur tu donne en argument
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Coordonnee const & coord
    Mais il ne faut pas donner en plus les arguments de l'objet coordonnee?
    un truc comme ce que tu utilise un peu plus loin, dans la classe plateau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Coordonnee const & coord(i,j)

    -On arrive à la classe Mover, et là, c'est le drame. D'abord c'est un foncteur, et j'ai juste survolée cette notion dans les tuto (je ne suis pas encore très avancé), mais si je comprends bien l'intérêt est de définir une partie des arguments une seule fois pour une fonction (lors de la création de l'objet Mover) pour ensuite appliquer cette fonction plusieurs fois avec d'autres arguments, eux qui peuvent différer d'une utilisation à l'autre.

    Si c'est ça je suppose qu'implémenter les autres méthodes d’interactions de mes personnages devrait aussi se faire de cette façon.

    -Pour l'aspect graphique un ami utilise la SDL (il redébute et on en est a peu près au même niveau) et il ne fait que ça. De mon programme il utilise les pointeurs Case->perso pour dessiner le personnage sur sa case. De plus les cases ont différents types. Mais dans ta proposition cela se ferait comment?

    D'instinct je dirais dans la classe Plateau, avec une fonction d'appel vers les coordonnées, mais ça nous obligerait à vérifier tous les objets à chaque case dessinée...long.

  5. #5
    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 bl4cksky Voir le message
    bonjour,

    D'abord merci pour vos réponses rapides.

    @Koala01

    Merci d'avoir répondu de façon si ... complète .
    De rien, avec plaisir
    Mais il me reste quelques questions :

    -D'abord une question bête. Tu initialise souvent tes fonctions comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type nom(arguments)  const &  {fonction}
    A quoi sert l'esperluette? Ça signifie que la valeur retournée est une référence?
    Tout à fait, la fonction renvoie une référence constante vers un objet du type indiqué.

    Cela permet d'éviter les copies lorsqu'elles ne sont pas utiles, et donc d'éviter de perdre le temps qui est nécessaire à une telle copie.

    Un gain de performance qui ne coute rien en somme

    -Une classe coordonnes est-elle vraiment nécessaire? Est-ce que c'est juste une question d'accessibilité? on pourrait juste donner des attributs aux classes Cases et Personnage, avec une méthode d'accession.
    L'idée de base est d'avoir un type par responsabilité.

    La notion de coordonnée est totalement transversale dans le projet car on l'utilise à plusieurs endroits.

    Il est donc "logique" de créer un type qui représente cette notion pour se faciliter la vie
    -Dans la classe Case tu utilise une fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Personnage * perso {return perso;}
    Cette fonction est censée retourner un pointeur vers le personnage présent sur la case c'est ça? Et dans ce cas la déclaration en Private ne devrait pas être avec une étoile puisque c'est un pointeur?
    En effet, perso_ devrait bien être un pointeur sur Personnage. j'ai oublié l'étoile par erreur
    Autre chose : dans le constructeur tu donne en argument
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Coordonnee const & coord
    Mais il ne faut pas donner en plus les arguments de l'objet coordonnee?
    un truc comme ce que tu utilise un peu plus loin, dans la classe plateau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Coordonnee const & coord(i,j)
    Non, on indique à la fonction qu'elle prend comme paramètre une coordonnée, et c'est tout ce qu'elle a besoin de savoir
    -On arrive à la classe Mover, et là, c'est le drame. D'abord c'est un foncteur, et j'ai juste survolée cette notion dans les tuto (je ne suis pas encore très avancé), mais si je comprends bien l'intérêt est de définir une partie des arguments une seule fois pour une fonction (lors de la création de l'objet Mover) pour ensuite appliquer cette fonction plusieurs fois avec d'autres arguments, eux qui peuvent différer d'une utilisation à l'autre.
    En fait, un foncteur est "simplement" une classe (ou une structure) dont la seule fonction membre hormis le constructeur est l'opérateur ().

    J'aurais tout aussi bien pu utiliser une fonction nommée "move()" ou "execute()", cela n'aurait rien changé à part la manière d'utiliser l'objet de type Mover
    Si c'est ça je suppose qu'implémenter les autres méthodes d’interactions de mes personnages devrait aussi se faire de cette façon.
    Sans doute, mais pas dans la classe Mover parce que tu dois respecter la règle de la responsabilité unique
    -Pour l'aspect graphique un ami utilise la SDL (il redébute et on en est a peu près au même niveau) et il ne fait que ça. De mon programme il utilise les pointeurs Case->perso pour dessiner le personnage sur sa case. De plus les cases ont différents types. Mais dans ta proposition cela se ferait comment?
    Exactement de la même manière...

    Tu aurais un "système" qui utilise SDL et qui maintient, entre autre, l'instance de la fenêtre active, le support du clavier, de la souris ou du joystick. et qui dispose d'une classe susceptible de dessinger les cases et d'une autre susceptible de dessiner le(s) personnage(s).

    Tu parcoures les cases du plateau et tu les affiches. Et au besoin, tu affiche le personnage sur la case sur laquelle il se trouve

    C'est pour cela que le plateau fournit exactement toutes les possibilités que fourni une case sous réserve de préciser de quelle case on parle

    Et si tu disposes de plusieurs types de cases, tu devras peut etre envisager d'utiliser le double dispatch pour savoir comment tracer quel type de case.

    Le patron de conception "visiteur" pourrait te servir d'exemple, la case étant l'objet visité, la classe qui s'occupe du tracé des case étant le visiteur
    D'instinct je dirais dans la classe Plateau, avec une fonction d'appel vers les coordonnées, mais ça nous obligerait à vérifier tous les objets à chaque case dessinée...long.
    La classe plateau n'a rien à faire de plus que ce qu'elle ne fait déjà!

    Si tu veux rajouter des fonctions au plateau, il faut que ce soient des fonctions compatibles avec la responsabilité de celui-ci, comme:
    • Permettre d'obtenir le nombre de lignes du plateau
    • Permettre d'obtenir le nombre de colonnes du plateau
    • Permettre d'obtenir l'index maximal pour les cases du plateau (qui n'est jamais que le produit du nombre de lignes et du nombre de colonnes )
    • Permettre de convertir un index en coordonnée.
    Il serait alors de la responsabilité de la classe qui doit afficher le plateau d'interroger le plateau pour savoir de combien de lignes ou de combien de colonnes il est composé et d'aller voir ce qui se trouve sur les différentes cases afin d'effectuer un affichage correct

    Quoi qu'il en soit, il n'est de la responsabilité ni du plateau, ni de la case, ni du personnage (et encore moins de la coordonnée) d'être en mesure de s'afficher.

    Par contre, il est de la responsabilité d'une classe (par exemple) TraceurDePlateau, TraceurDeCase ou TraceurDePersonnage de tracer le plateau, la case ou le personnage qu'on lui transmet en paramètre
    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

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2013
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2013
    Messages : 38
    Points : 24
    Points
    24
    Par défaut
    Merci beaucoup je vais tâcher de digérer tout ça.

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

Discussions similaires

  1. [OpenCV 2.2] cvNamedWindow crashe le programme
    Par sonorc dans le forum OpenCV
    Réponses: 0
    Dernier message: 20/03/2011, 13h23
  2. Crash du programme basé sur le tuto
    Par Demystificator dans le forum Ogre
    Réponses: 5
    Dernier message: 25/03/2010, 10h58
  3. Crash du programme à l'exécution
    Par MaTtaW dans le forum C++
    Réponses: 8
    Dernier message: 10/06/2009, 10h16
  4. Crash de programme selon les machines
    Par Lutarez dans le forum C#
    Réponses: 2
    Dernier message: 04/06/2009, 16h21
  5. Intercepter un crash du programme ?
    Par Rudyweb dans le forum MFC
    Réponses: 3
    Dernier message: 03/03/2005, 13h58

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