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 :

[C++11] Premier programme.


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut [C++11] Premier programme.
    Salut les C++,

    je débute vraiment avec le langage C++, environ depuis le début du moi de mai, et je suis loin de tout savoir sur le C++.

    A noter que je pratique le C brute depuis plus de 2 ans et que j'ai débuter la programmation avec python il y a 5 ans.

    Alors je vous présente, (enfin vous soumet a commenter (RFC)) mon premier mini programme.

    Mais avant j'aimerai vous faire partager mon ressentis a propos du langage C++.

    Alors m'étant renseigner avant de sauter le pas, il a été dit que le C++ n'est pas un C étendus objet.

    Bon d'accord mais ca y ressemble quand ont regarde plus près: les classes n'étant rien d'autres que des structures (très) améliorées et les conteneurs ressemble au ensemble de données que l'on peut trouver en C (arbre, set, listes chainées, etc...)... Ca reste a débattre.

    Ce qui me déplait avec le C++ c'est le nombre de mots clefs (keyword) et opérateurs que contient le langage je trouve qu'il y en a trop, chacun a son utilité mais il n'est pas facile de tous les retenir et surtout des exceptions d'utilisation de ceux -ci (je ne trouve pas d'exemple tellement je suis perdu).

    Mais assez de bla bla, voici mon premier mini programme en C++:

    Il s'agit d'une implémentation du jeu des tours de hanoi:

    Au début du jeu sont empiler un nombre donné de disques sur un piquet a gauche, du plus grand en bas au plus petit en haut. Et il y a 2 autres piquets a la droite qui sont vide.

    Le but du jeu est refaire une pile croissante sur un des deux piquets autres piquets.

    +) En ne déplacant qu'un seule disque a la fois.

    +) On ne peut pas empiler un disque plus grand sur un disque plus petit.

    Le programme a la structure suivante:

    2 classes: Tower et Game.

    -+-> Tower.h
    |
    -+ -> Tower.cpp
    |
    -+-> Game_Tower.h
    |
    -+-> Game_Tower.cpp
    |
    -+-> main.cpp

    Voici le fichier Tower.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
    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
     
    #ifndef TOWER_H
    #define TOWER_H
     
    #include <vector>
    #include <string>
     
    class Tower {
     
      int upper_disc_index ;
     
      int upper_disc_value ;
     
      public :
     
        /** Disc container. */
        std::vector<int> disc ;
     
        /** Maximum disc number set from the user. **/
        int max_disc ;
     
        /** DEBUG Identifier **/
        std::string name ;
     
        /** Constructors **/
        Tower(int max, std::string n) ;
     
        Tower() ;
     
        /** getters. **/
        int get_upper_disc_value() const ;
     
        int get_upper_disc_index() const ;
     
        /** Setters. **/
        void set_upper_disc_value(int value) ;
     
        void set_upper_disc_index(int index) ;
     
     
        /** Check if game finish. **/
        int disc_on_tower_count() const ;
     
        /** Validity check. **/
        bool is_entry_valid(int to_place_on) const ;
     
    } ;
     
    #endif
    Le fichier Tower.cpp:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    #ifndef TOWER_CPP
    #define TOWER_CPP
     
    #include "Tower.h"
    #include <algorithm>
     
    Tower::Tower(int max, std::string n) : name(n)  {
     
      max_disc=max ;
     
    }
     
    Tower::Tower() {} ;
     
    int Tower::get_upper_disc_value() const {
     
      /** Return the tower highest disc value.
        **************************************/
     
     return upper_disc_value ;
     
    }
     
    void Tower::set_upper_disc_value(int value) {
     
      /** Set the tower highest disc value.
        ***********************************/
     
     upper_disc_value=value ;
     
     return ;
     
    }
     
    int Tower::get_upper_disc_index() const {
     
      /** Return the index of the highest valid disc from the tower.
        ************************************************************/
     
      return upper_disc_index ;
     
    }
     
    void Tower::set_upper_disc_index(int index) {
     
      /** Set the index of the highest valid disc from the tower.
        *********************************************************/
     
      upper_disc_index = index ;
     
      return ;
     
    }
     
    int Tower::disc_on_tower_count() const {
     
      /** Count the number of disc onto a tower. **/
     
      return max_disc-count(disc.begin(), disc.end(), 0) ;
     
    }
     
    bool Tower::is_entry_valid(int to_place_on) const {
     
      /** Return if the given disc value is valid according the game rules:
        * only a littler disc can be set on a bigger one.
        *******************************************************************/
     
      int upper_disc_value =  get_upper_disc_value() ;
     
      if ( upper_disc_value > to_place_on || upper_disc_value == 0 ) {
        /** Okay or tower empty (=0). **/
     
        return true ;
      }
     
      return false ;
     
    }
     
    #endif
    Le fichier Game_Tower.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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    #ifndef HANOI_TOWER_GAME_H
    #define HANOI_TOWER_GAME_H
     
    #include "Tower.cpp"
     
     
    class Game {
     
      public :
     
      /** The tree towers **/
      Tower tower_1 ;
      Tower tower_2 ;
      Tower tower_3 ;
     
      /** Contructor **/
      Game(int max) ;
     
      /** Move a disc onto another tower. **/
      bool moving(Tower &from, Tower &to) ;
     
      /** Check if the player win. **/
      bool end_game(void) ;
     
      /** Displaying method. **/
      void display() ;
     
      /** DEBUG function. **/
      friend void display_debug(Game &g) ;
     
    } ;
     
    #endif
    Le fichier Game_Tower.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    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
     
     
    #ifndef HANOI_TOWER_GAME_CPP
    #define HANOI_TOWER_GAME_CPP
     
    #include "Game_Tower.h"
     
    #include <iostream>
    #include <string>
     
    void display_debug(Game &g) {
     
      /** DEBUG function which display the disc values in columns representing the towers. **/
     
      std::cout << std::endl ;
     
      for (int c=0 ; c < g.tower_1.max_disc ; c++) {
     
        std::cout << g.tower_1.max_disc-c << " -> " << g.tower_1.disc[c] << " " << g.tower_2.disc[c] << " " << g.tower_3.disc[c] << std::endl ;
     }
     
     std::cout << std::endl ;
     
    }
     
    /** Contructor: **/
    Game::Game(int max) : tower_1(max,"tower 1"), tower_2(max,"tower 2"), tower_3(max,"tower 3")  { }
     
     
    bool Game::moving(Tower &from, Tower &to) {
     
      /** Move a disc from a tower onto another if valid disc move. **/
     
      if ( ! to.is_entry_valid(from.get_upper_disc_value())) {
        return false ;
      }
     
      if (from.disc_on_tower_count() == 0) {
        return false ;
      }
     
     
     
      int to_index   = to.get_upper_disc_index() ;
      int from_index = from.get_upper_disc_index() ;
     
      /** Move disc: **/
      to.disc.at( to_index-1 ) = from.disc.at( from_index ) ;
     
      /** Adjust the indexes. **/
      to.set_upper_disc_index(to_index - 1) ;
      from.set_upper_disc_index(from_index+1) ;
     
      /** Adjust the values. **/
      to.set_upper_disc_value(to.disc.at( to.get_upper_disc_index() )) ;
      if (from_index+1 < tower_1.max_disc-1) {
        from.set_upper_disc_value( from.disc.at(from.get_upper_disc_index())  ) ;
      }
      else {
        from.set_upper_disc_value(0) ;
      }
     
      /** Set the source disc on zero (=0 represent no disc). **/
      from.disc.at(from_index) = 0 ;
     
      return true ;
     
    }
     
     
     
    bool Game::end_game(void) {
     
      /** Check if the player has terminate the game. **/
     
      int max_disc= tower_1.max_disc ;
     
      if (tower_2.get_upper_disc_value() == 1 && tower_2.disc_on_tower_count() == max_disc) {
        return true ;
      }
     
      if (tower_3.get_upper_disc_value() == 1 && tower_3.disc_on_tower_count() == max_disc) {
        return true ;
      }
     
      return false ;
     
    }
     
     
     
     
     
    void Game::display() {
     
      /** Terminal game playground displaying method.  **/
     
      unsigned int max_disc = tower_1.max_disc ;
     
      std::string line_begin_space(3,' ') ;
     
      for (int c=0 ; c < 2 ; c++) {
        std::cout << std::endl ;
      }
     
      /** We display the towers line after line. **/
      for (int c=0 ; c < tower_1.max_disc ; c++) {
     
     
          std::cout << line_begin_space ;
     
     
          /** Tower 1: **/
     
          /** Set the disc middle part (represent as '=' sign). **/
          std::string side1(tower_1.disc[c],'=') ;
     
          /** Compute the spaces to display. **/
          std::string space1(max_disc-tower_1.disc[c]+max_disc/2,' ') ;
     
          /** Set the disc borders or space if empty.**/
          std::string side_left1(1,  (tower_1.disc[c] == 0) ? ' ' : '<') ;
          std::string side_right1(1, (tower_1.disc[c] == 0) ? ' ' : '>') ;
     
          /** Display a line from the first tower. **/
          std::cout << space1 << side_left1 << side1  << "!" << side1 << side_right1 << space1 ;
     
     
     
          /** Tower 2: **/
     
          /** Set the disc middle part (represent as '=' sign). **/
          std::string side2(tower_2.disc[c],'=') ;
     
          /** Compute the spaces to display. **/ 
          std::string space2(max_disc-tower_2.disc[c]+max_disc/2,' ') ;
     
          /** Set the disc borders or space if empty.**/
          std::string side_left2(1,  (tower_2.disc[c] == 0) ? ' ' : '<') ;
          std::string side_right2(1, (tower_2.disc[c] == 0) ? ' ' : '>') ;
     
          /** Display a line from the second tower. **/
          std::cout << space2 << side_left2  << side2  << "!" << side2 << side_right2 << space2 ;
     
     
          /** Tower 2: **/
     
          /** Set the disc middle part (represent as '=' sign). **/
          std::string side3(tower_3.disc[c],'=') ;
     
          /** Compute the spaces to display. **/
          std::string space3(max_disc-tower_3.disc[c]+max_disc/2,' ') ;
     
          /** Set the disc borders or space if empty.**/
          std::string side_left3(1,  (tower_3.disc[c] == 0) ? ' ' : '<') ;
          std::string side_right3(1, (tower_3.disc[c] == 0) ? ' ' : '>') ;
     
          /** Display a line from the third tower. **/
          std::cout <<  space3 << side_left3  << side3  << "!" << side3 <<  side_right3 << space3 ;
     
     
        std::cout << std::endl ;
     
     
     
      }
     
      std::cout << std::endl ;
     
     
      /** Finally we display a number reconizing the towers. **/
     
     
      /** Compute the amount of space between 2 towers numbers. **/
      std::string spaces_tower_side(max_disc+max_disc/2+1,' ') ;
     
     
      std::cout << line_begin_space ;
     
      for (int c=1 ; c <= 3 ; c++) {
        /** Display the towers numbers under the towers. **/
        std::cout << spaces_tower_side << c << spaces_tower_side ;
      }
     
      std::cout << std::endl ;
     
      for (int c=0 ; c < 2 ; c++) {
        std::cout << std::endl ;
      }
     
     
     
      return ;
     
    }
     
    #endif
    Le fichier main.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    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
     
    #include <cstdlib>
     
     
    #include "Game_Tower.cpp"
     
    //#define DEBUG_MATRIX
     
    /** Hanoi tower game:
      * usage: game number_of_disc.
      *
      * To compil with:
      *
      * $ g++ -o game -Wall -Wextra -std=c++11
      *
      ****************************************/
     
    int main(int argc, char *argv[]) {
     
      if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " number of disc" << std::endl ;
        exit(EXIT_FAILURE) ;
      }
     
      int max_disc  ;
     
      if ((max_disc = atoi(argv[1])) <= 0) {
        std::cout << "Usage: " << argv[0] << " number of disc" << std::endl ;
        exit(EXIT_FAILURE) ;
      }
     
      Game game(max_disc) ;
     
     
     
      for (int c = 1 ; c < max_disc+1 ; c++) {
     
        /** We create a vector as an array of integer for every tower.
          * Ordered at start:
          * The biggest disc is down.
          * And the littles index is the highest disc in the tower.
          ***********************************************************/
     
        game.tower_1.disc.push_back(c) ;  /** We fill the tower one.   **/
        game.tower_2.disc.push_back(0) ;  /** We fill the tower two.   **/
        game.tower_3.disc.push_back(0) ;  /** We fill the tower three. **/
     
     
     
      }
     
      /** We set the upper tower disc value at start. **/
      game.tower_1.set_upper_disc_value(1) ;
      game.tower_2.set_upper_disc_value(0) ;
      game.tower_3.set_upper_disc_value(0) ;
     
      /** We set the upper tower disc index at start. **/ 
      game.tower_1.set_upper_disc_index(0) ;
      game.tower_2.set_upper_disc_index(max_disc) ;
      game.tower_3.set_upper_disc_index(max_disc) ;
     
     
     
      bool end_game = false ;
     
      int round_counter = 1 ;
     
      while (!(end_game)) {
        /** Game mainloop. **/
        game.display() ;
     
     
        #ifdef DEBUG_MATRIX
          display_debug(game) ;
        #endif
     
        int from, to ;
     
        std::cout << "Move From [1-3]...: "  ;
     
        while (! (std::cin >> from)) {
          /** Getting the source disc moving tower. **/
          if (from < 1 || from > 3) {
            std::cout << "Invalid move !!!" << std::endl ;
            continue ;
          }
     
          std::cout << "Invalid entry !!!" << std::endl ;
        }
     
        std::cout << "Move to   [1-3]...: "  ;
     
        while (! (std::cin >> to)) {
          /** Getting the destination disc moving tower. **/
          if ((to < 1 || to > 3) || (from == to)) {
            std::cout << "Invalid move !!!" << std::endl ;
            continue ;
          }
     
          std::cout << "Invalid entry !!!" << std::endl ;
        }
     
        #ifdef DEBUG
          std::cout << "From " << from << " To " << to << std::endl ;
        #endif
     
        switch (from) {
     
          /** Process disc moving with errors catching. **/
     
          case 1 :
     
            if (to == 2) {
              if (! game.moving(game.tower_1, game.tower_2) ) {
                std::cout << "Invalid move !!!" << std::endl ;
              }
              else {
                round_counter++ ;
              }
            }
            else if (to == 3) {
              if (! game.moving(game.tower_1, game.tower_3) ) {
                std::cout << "Invalid move !!!" << std::endl ;
              }
              else {
                round_counter++ ;
              }
     
            }
            else {
              std::cout << "Invalid move !!!" << std::endl ;
            }
     
     
     
            break ;
     
          case 2 :
     
            if (to == 1) {
              if (! game.moving(game.tower_2, game.tower_1) ) {
                std::cout << "Invalid move !!!" << std::endl ;
              }
              else {
                round_counter++ ;
              }
            }
            else if (to == 3) {
              if (! game.moving(game.tower_2, game.tower_3) ) {
                std::cout << "Invalid move !!!" << std::endl ;
              }
              else {
                round_counter++ ;
              }
            }
            else {
              std::cout << "Invalid move !!!" << std::endl ;
            }
     
            break ;
     
          case 3 :
     
            if (to == 1) {
              if (! game.moving(game.tower_3, game.tower_1) ) {
                std::cout << "Invalid move !!!" << std::endl ;
              }
              else {
                round_counter++ ;
              }
            }
            else if (to == 2) {
              if (! game.moving(game.tower_3, game.tower_2) ) {
                std::cout << "Invalid move !!!" << std::endl ;
              }
              else {
                round_counter++ ;
              }
            }
            else {
              std::cout << "Invalid move !!!" << std::endl ;
            }
     
            break ;
     
        }
     
        end_game=game.end_game() ;
      }
     
      game.display() ;
     
      std::cout << "YOU WIN !!!" << std::endl ;
      std::cout << "With " << max_disc << " disc in " << round_counter << " rounds !!!" << std::endl ;
     
     
      return 0 ;
     
    }
    Remarque: je n'ai pas réussis a mettre les instances de Tower de la classe Game dans un conteneur ce qui m'aurai arranger. Il y a avait une erreur quand je récupérais les vector "disc"...???? C'est peut-être du au faîte que Tower est une classe et c'est pour cela qu'il y a un constructeur sans argument déclaré qui ne sert a rien.

    Je vous serai grandement reconnaisant de toute aide dans la quête du C++: conseils, conseils de lecture, remarque sur mon code, avis sur mon bout de code etc...
    Je suis ouvert a tous et vous remercie pour vos éclaicissement.

    Sur ceux bon C++ a vous.

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Bon d'accord mais ca y ressemble quand ont regarde plus près: les classes n'étant rien d'autres que des structures (très) améliorées
    en C tes structures n'étaient que des aggrégats, ne pouvaient pas avoir de constructeur ou de fonction membre. N'avaient aucune notion d'héritage*, fonction virtuelle, ... ce qui n'empechait pas de faire de l'objet
    http://cpp.developpez.com/faq/cpp/?p...lass-et-struct

    et les conteneurs ressemble au ensemble de données que l'on peut trouver en C (arbre, set, listes chainées, etc...)... Ca reste a débattre.
    D'un autre côté tu espérais quoi ? Qu'en changeant de langage on réinventerait la roue ?
    Dans ce cas, Python ressemble au C, on a les mêmes structures, ainsi que JAVA, C#, javascript, ....

    trop de mot-clés ?
    En pratique, sorti de template, class et virtual tu couvres déjà une bonne partie de tes besoins quotidiens
    trop d'opérateurs ?

    * pourtant ça existait déjà, à base de cast barbare, cf le code-source de Python et autres projets écrits en C
    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
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Alors m'étant renseigner avant de sauter le pas, il a été dit que le C++ n'est pas un C étendus objet.
    Bon d'accord mais ca y ressemble quand ont regarde plus près: les classes n'étant rien d'autres que des structures (très) améliorées et les conteneurs ressemble au ensemble de données que l'on peut trouver en C (arbre, set, listes chainées, etc...)... Ca reste a débattre.
    Oui, comme tu le dis, ça reste à débattre Je te répondrais qu'il faut 1) prendre en considération d'autres aspects essentiels du C++, comme la programmation générique (les template), parce que, tout de même, un conteneur générique en C ça reste à voir, sauf à faire des cast affreux tout le temps, ou bien la gestion des exceptions et 2) regarde un peu l'évolution du C++, les fonctions lambda, l'inférence de types, etc. et tu verras que le chemin parcouru depuis le C est énorme et ne se résume pas aux classes. Et puis, quant aux "structures améliorées", je trouve que tu exagères un peu puisqu'elles permettent la gestion de la mémoire et toute autre ressource partagée d'une façon dont on ne peut pas rêver en C...

    Ce qui me déplait avec le C++ c'est le nombre de mots clefs (keyword) et opérateurs que contient le langage je trouve qu'il y en a trop, chacun a son utilité mais il n'est pas facile de tous les retenir et surtout des exceptions d'utilisation de ceux -ci (je ne trouve pas d'exemple tellement je suis perdu).
    Mais c'est vrai que la syntaxe du C++ est extraordinairement compliquée et l'est de plus en plus avec l'évolution du standard. Il y en a une bonne dans A Brief, Incomplete, and Mostly Wrong History of Programming languages:
    1983 - Bjarne Stroustrup bolts everything he's ever heard of onto C to create C++. The resulting language is so complex that programs must be sent to the future to be compiled by the Skynet artificial intelligence. Build times suffer. Skynet's motives for performing the service remain unclear but spokespeople from the future say "there is nothing to be concerned about, baby," in an Austrian accented monotones. There is some speculation that Skynet is nothing more than a pretentious buffer overrun.

    Remarque: je n'ai pas réussis a mettre les instances de Tower de la classe Game dans un conteneur ce qui m'aurai arranger. Il y a avait une erreur quand je récupérais les vector "disc"...???? C'est peut-être du au faîte que Tower est une classe et c'est pour cela qu'il y a un constructeur sans argument déclaré qui ne sert a rien.
    Si tu pouvais apporter quelques précisions supplémentaires...

    Sur le programme de façon générale, il y a plein de bonnes choses mais tu n'utilises pas suffisamment les classes. Ton main est beaucoup trop gros, tu devrais avoir l'essentiel dans des classes ou au moins des fonctions séparées, là ça fait un peu code spaghetti quand même...

  4. #4
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Plusieurs remarques, mais qui sont plutôt d’ordre conceptuel que véritablement C++ :

    Dans ta classe Tower :
    - c’est quoi « upper_disc_index » ? Chez moi, les disques n’ont qu’une seule propriété, leur valeur (= diamètre). Ton « index », je ne vois pas ce que c’est (et d’ailleurs, je crois que tu ne t’en sers pas).
    - pas de getter / setter. Une tour est un objet qui fournit quelques fonctionnalités :
    * empiler un jeton (peut échouer si le jeton n’est pas empilable)
    * dépiler un jeton
    * connaître la taille de la pile
    * connaître le diamètre du jeton du dessus

    le vector<int> disc ne devrait sûrement pas être public, mais privé : c’est un détail d’implémentation de la classe.

    max_disc ne te sert à rien. Je ne comprends pas comment tu as fait ton int Tower::disc_on_tower_count() const, logiquement c’est juste disc.size().

    Pour game_tower :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool moving(Tower &from, Tower &to)
    --> move(), pas moving.

    Tower1, Tower2 et Tower3 ne devraient pas être publics, et accessibles directement en const uniquement (pas possible de modifier les tours sans passer par la classe game) --> la signature de move doit être changée pour prendre simplement les index des tours.

    end_game -> terminer le jeu. Donc renommer cette fonction en quelque chose comme is_game_won par exemple.


    Bon, ça fait une grosse liste, mais autant que tu prennes de bonnes habitudes dès le début .

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pourquoi as-tu un .h qui inclut un .cpp?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Hello,

    Quelques remarques en vrac :
    • Quand une fonction ne retourne rien (void function(...) { }), tu n'as pas besoin d'y mettre un return;, mais ce n'est pas faux.
    • On inclue JAMAIS un .cpp, par exemple dans "Game.h", il faut inclure "Tower.h" et non "Tower.cpp".
    • On évite généralement les copies d'objets "lourds" (en simplifiant - surement un peu trop - tout ce qui n'est pas un type primitif (char, int, float) est "lourd"): on préfère les passer par référence constante. Ou si tu préfère, partout où tu passais un pointeur en C, tu passeras une référence ou un pointeur en C++ (souvent une référence).
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      struct Foo;
      void bar(Foo const& f) { }
      // au lieu de 
      void bar(Foo f) { }
    • Il faut user et abuser de la liste d'initialisation : tu ne fais ça qu'à moitié (cf ctor de Tower).
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      Tower::Tower(int max, std::string n) : name(n) {
      	max_disc=max ;
      }
      // devrait être
      Tower::Tower(int max, std::string const& n) : name(n), max_disc(max) { }
    • if(truc == true) { return true; } return false; est redondant : return truc; est plus clair. (cf Tower::is_entry_valid()).
    • Attention aux ctors qui ne prennent qu'un argument (cf Game::Game(int)) : ils permettent une conversion automatique (ici un int peut être converti en Game automatiquement. On peut empêcher ça avec explicit.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      class Game {
      public:
      	Game(float f); // sans explicit, conversion possible
      	Game(std::string const& str, float f=42.f); // 2 paramètres, mais 1 par défaut -> conversion possible
      	explicit Game(int max); // explicit, pas de conversion implicite
      };
      Game g = 42.f; // valide, conversion implicite
      Game g = std::string("foo"); // valide
      Game g = 42; // invalide
      Game g = Game(42); // valide
    • Tu devrais vraiment avoir un vector de Tower dans Game, tu pourrais avoir un algo générique dans Game pour bouger un disque au lieu de cet énorme switch affreux dans ton main.
    • Tes fonctions display (cf Game::display) pourraient être des surcharges de std::ostream& operator<<(std::ostream& os, Game const& game);

  7. #7
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    Merci pour vos nombreuse réactions,

    tout d'abord heureusement que personne n'a compiler / tester le jeu car il y a avait un bug

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    if (from_index+1 < 5) {
        from.set_upper_disc_value( from.disc.at(from.get_upper_disc_index())  ) ;
      }
      else {
        from.set_upper_disc_value(0) ;
      }
    que j'ai vite remplacer par la valeur qui permet de jouer avec n'importe quel nombre de disques au lieu du 5 disques de test que j'avais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if (from_index+1 < tower_1.max_disc-1) {
        from.set_upper_disc_value( from.disc.at(from.get_upper_disc_index())  ) ;
      }
      else {
        from.set_upper_disc_value(0) ;
      }
    Tout d'abords:

    D'un autre côté tu espérais quoi ? Qu'en changeant de langage on réinventerait la roue ?
    Non je cherche un langage orienter objet compiler (question de performances) car python est un gentil petit langage de script qui sait tout faire mais n'est pas assez rapide et le C n'est pas orienter objet.

    Je vient de sortir de la notion de classe en C++ et j'ai commencer les exceptions mais pas encore les templates. Donc je suis loin de tout connaître des bases du C++.

    Mais c'est vrai que la syntaxe du C++ est extraordinairement compliquée et l'est de plus en plus avec l'évolution du standard.
    Je suis d'accord et le plus affreux dans l'affaire c'est la redéfinition de mots clefs comme auto, qui casse le rétrocompatiblité, enfin personnellement je m'en tape je commence avec le standart c++11.

    Sur le programme de façon générale, il y a plein de bonnes choses mais tu n'utilises pas suffisamment les classes. Ton main est beaucoup trop gros, tu devrais avoir l'essentiel dans des classes ou au moins des fonctions séparées, là ça fait un peu code spaghetti quand même...
    En faîtes j'ai eu des problème pour accéder au vectors disc des instances de type Tower donc j'ai du faire ce premier code sans un conteneur d'instances de Tower et je ne sais absolument pas pourquoi ca ne marchait pas.
    Mais la bonne nouvelle est que l'on a pas encore vraiment attaquer les conteneurs de la library standart (libc++ ?).
    D'ailleurs en parlant de library standart: j'ai télécharger les références et apparament C++ n'est pas un langage batteries included...

    c’est quoi « upper_disc_index » ?
    C'est une variable privée avec méthode d'accesseur permettant de récupérer l'index du disque le plus haut car une valeur 0 signifie vide.
    Et je m'en sert dans la méthode moving(), que je devrai appeler move().
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int to_index     = to.get_upper_disc_index() ;
    int from_index = from.get_upper_disc_index() ;
    max_disc ne te sert à rien. Je ne comprends pas comment tu as fait ton int Tower::disc_on_tower_count() const, logiquement c’est juste disc.size().
    Tu a parfaitement raison j'aurai du stocker le nombre de disque dans la classe Game.
    Car il faut que je sache combien de disque en tout d'abord pour les dessiner (ligne après ligne. Y a pas de fonctionnalitées pour le terminal dans le C++ ?) et bon disc.size() fait l'affaire pour vérifier si un piquet est plein.

    On inclue JAMAIS un .cpp, par exemple dans "Game.h", il faut inclure "Tower.h" et non "Tower.cpp".
    D'accord mais normalement ont a:
    1. La déclaration d'une classe dans un *.h
    2. La définition de celle-ci dans un fichier *.cpp homonyme.
    Donc le fichier *.cpp inclus le *.h, ou c'est pas comme ca ?
    Peut-être mettre la défintion de la classe sous la déclaration dans le fichier *.h et inclure celui-ci...????

    Je prend note de vos bons conseils, si j'ai poster c'est bien pour vos bons conseils et remarques ce pourquoi je vous suis très reconnaissant.

    Le plus gros défaut du jeu est donc qu'il n'y a pas de conteneur pour les instances des 3 tours, je ferai plus attention la prochane fois...

    Et faire des attributs privée au lieu de publique, mais ce n'est pas facile a debugger au début.

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

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par Luke spywoker Voir le message
    D'accord mais normalement ont a:
    1. La déclaration d'une classe dans un *.h
    2. La définition de celle-ci dans un fichier *.cpp homonyme.
    Donc le fichier *.cpp inclus le *.h, ou c'est pas comme ca ?
    C'est bien ça, mais nulle part tu n'inclus le .cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // tower.h
    class Tower {
        Tower();
    };
     
    // tower.cpp
    #include "tower.h"
    Tower::Tower() { }
     
    // game.h
    #include "tower.h"
    #include <vector>
    class Game {
        std::vector<Tower> m_towers;
        Game();
    };
     
    // game.cpp
    #include "game.h"
    Game::Game() { }
    Seulement des .h inclus.

  9. #9
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    le C n'est pas orienter objet
    Il est tout à fait possible de faire de la programmation objet en C.
    Tu n'auras pas d'héritage etc, bien que tu puisses le "feinter" de manière généralement décriée et "sale", mais c'est possible.
    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.

  10. #10
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    C'est bien ça, mais nulle part tu n'inclus le .cpp :
    J'ai pas compris dans ton code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    // tower.h
    class Tower {
        Tower();
    };
     
    // tower.cpp
    #include "tower.h"
    Tower::Tower() { }
     
    // game.h
    #include "tower.h"
    #include <vector>
    class Game {
        std::vector<Tower> m_towers;
        Game();
    };
     
    // game.cpp
    #include "game.h"
    Game::Game() { }
    En faite tu n'inclus jamais les fichiers *.cpp même pas dans a la fin du fichier *.h, donc le code contenus dans les fichiers *.cpp n'est jamais pris en compte, vue que le fichier n'est jamais inclus ???

    A moins que cela soit une mecanique interne du C++, d'inclure automatiquement le fichier *.cpp homonyme...

    Merci pour vos réponses éclairées.

Discussions similaires

  1. [JDOM] Mon premier programme java-xml
    Par adilo dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 12/07/2006, 13h12
  2. premier programme!
    Par kriskikout dans le forum Langage
    Réponses: 8
    Dernier message: 11/02/2006, 16h10
  3. [Debutant]Premier programme blemes+ questions
    Par Bakura dans le forum Débuter
    Réponses: 21
    Dernier message: 07/10/2005, 18h26
  4. [Language] Aide sur mon premier programme Java?
    Par hash2zo dans le forum Langage
    Réponses: 15
    Dernier message: 27/09/2005, 19h26
  5. [Débutant] Mon premier programme: rien ne va...
    Par vincent0 dans le forum OpenGL
    Réponses: 10
    Dernier message: 02/08/2005, 13h59

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