Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Exercices] Venez vous entraîner !

(v2)

    1 juillet 2011 à 18:32:52

    Une séance de désassemblage :

    Pour -O0 :
    (gdb) disas main
    Dump of assembler code for function main:
       0x0000000000400594 <+0>:     push   %rbp
       0x0000000000400595 <+1>:     mov    %rsp,%rbp
       0x0000000000400598 <+4>:     sub    $0x10,%rsp
       0x000000000040059c <+8>:     lea    -0x8(%rbp),%rax
       0x00000000004005a0 <+12>:    mov    %rax,%rsi
       0x00000000004005a3 <+15>:    mov    $0x4006cc,%edi
       0x00000000004005a8 <+20>:    mov    $0x0,%eax
       0x00000000004005ad <+25>:    callq  0x400498 <scanf@plt>
       0x00000000004005b2 <+30>:    mov    -0x8(%rbp),%edx
       0x00000000004005b5 <+33>:    mov    %edx,%eax
       0x00000000004005b7 <+35>:    add    %eax,%eax
       0x00000000004005b9 <+37>:    add    %edx,%eax
       0x00000000004005bb <+39>:    mov    %eax,-0x4(%rbp)
       0x00000000004005be <+42>:    mov    -0x4(%rbp),%eax
       0x00000000004005c1 <+45>:    mov    %eax,%esi
       0x00000000004005c3 <+47>:    mov    $0x4006cc,%edi
       0x00000000004005c8 <+52>:    mov    $0x0,%eax
       0x00000000004005cd <+57>:    callq  0x400478 <printf@plt>
       0x00000000004005d2 <+62>:    mov    $0x0,%eax
       0x00000000004005d7 <+67>:    leaveq 
       0x00000000004005d8 <+68>:    retq   
    End of assembler dump.

    J'observe particulièrement :
    0x00000000004005b7 <+35>:    add    %eax,%eax
    0x00000000004005b9 <+37>:    add    %edx,%eax

    Donc, au lieu de x*3, il fait x+x+x. Or un décalage d'un bit sur la gauche est plus rapide qu'une addition.
    Donc, pour O0, il vaut mieux la micro-optimisation.

    Pour O1, O2 et O3, je dois admettre ne pas comprendre le fonctionnement : ils utilisent LEA, que je ne comprends pas (par ailleurs, je note qu'il me semble que O2 et O3 ajoutent des instructions par rapport à O1, sans en enlever aucune).

    Mais, dans au moins un cas, il est préférable de faire la micro-optimisation, et dans les autres on n'y perd rien. Donc j'ai gagné, et j'ai un bénéfice de 1 nanoseconde ! :D
    • Partager sur Facebook
    • Partager sur Twitter
      1 juillet 2011 à 19:09:44

      Si tu compiles en -O0 (des gens font ça?! :) ) tu compiles pas pour les perfs et donc tu sors pas des tricks de sioux. En résumé tu obfusques une opération élémentaire pour un gain négligeable effectif que dans un seul mode de compilation? J'appelle pas ça gagner :).
      Fin bref, de toute façon, c'est un cas isolé et simple, sur des choses bien plus compliqué y'a peu de chance que tu fasses mieux que le compilo dans le cas scalaire en tout cas et si tu y'arrives ça sera au prix de la lisibilité.

      Mais vraiment, au delà de la mesure de cycle gagné/perdu l'argument de poids c'est la lisibilité et la simplicité de tes sources.
      • Partager sur Facebook
      • Partager sur Twitter
        1 juillet 2011 à 19:41:42

        Citation : Equinoxe

        Pour O1, O2 et O3, je dois admettre ne pas comprendre le fonctionnement : ils utilisent LEA, que je ne comprends pas (par ailleurs, je note qu'il me semble que O2 et O3 ajoutent des instructions par rapport à O1, sans en enlever aucune).


        Quand tu compiles vers l'assembleur, utilise plutôt le format Intel (option "-masm=intel" pour gcc), il est beaucoup plus clair que le format AT&T:
                .cfi_startproc
                mov        eax, DWORD PTR [esp+4]
                lea        eax, [eax+eax*2]
                ret
                .cfi_endproc


        • Partager sur Facebook
        • Partager sur Twitter
          1 juillet 2011 à 19:51:03

          Pour les gens nés dans la syntaxe intel. ceux qui aiment la syntaxe AT&T la trouve toute aussi claire et simple :). (moi perso les deux me vont).
          • Partager sur Facebook
          • Partager sur Twitter
            1 juillet 2011 à 19:58:23

            Oui je fais ça, mais juste pour tester. :D

            Et je sais que c'est inutile, c'est juste pour le fun que je proposais ça. :)

            @alexisdm:

            Je viens de comprendre le sens de lea, grâce à toi. Merci pour l'astuce. :)

            Du coup, je fais un nouveau comparatif :
            int op(int a) {
                return a * 3;
            }
            

            int op(int a) {
                return (a << 1) + a;
            }
            


            [ekinox@leortable tmp]$ g++ -masm=intel -c a.cpp -o a0 -O0
            [ekinox@leortable tmp]$ g++ -masm=intel -c a.cpp -o a1 -O1
            [ekinox@leortable tmp]$ g++ -masm=intel -c a.cpp -o a2 -O2
            [ekinox@leortable tmp]$ g++ -masm=intel -c a.cpp -o a3 -O3
            [ekinox@leortable tmp]$ g++ -masm=intel -c b.cpp -o b3 -O3
            [ekinox@leortable tmp]$ g++ -masm=intel -c b.cpp -o b2 -O2
            [ekinox@leortable tmp]$ g++ -masm=intel -c b.cpp -o b1 -O1
            [ekinox@leortable tmp]$ g++ -masm=intel -c b.cpp -o b0 -O0


            Pour O0 :
            (gdb) file a0
            Reading symbols from /tmp/a0...(no debugging symbols found)...done.
            (gdb) disas op
            Dump of assembler code for function _Z2opi:
               0x0000000000000000 <+0>:     push   %rbp
               0x0000000000000001 <+1>:     mov    %rsp,%rbp
               0x0000000000000004 <+4>:     mov    %edi,-0x4(%rbp)
               0x0000000000000007 <+7>:     mov    -0x4(%rbp),%edx
               0x000000000000000a <+10>:    mov    %edx,%eax
               0x000000000000000c <+12>:    add    %eax,%eax
               0x000000000000000e <+14>:    add    %edx,%eax
               0x0000000000000010 <+16>:    pop    %rbp
               0x0000000000000011 <+17>:    retq   
            End of assembler dump.
            (gdb) file b0
            Reading symbols from /tmp/b0...(no debugging symbols found)...done.
            (gdb) disas op
            Dump of assembler code for function _Z2opi:
               0x0000000000000000 <+0>:     push   %rbp
               0x0000000000000001 <+1>:     mov    %rsp,%rbp
               0x0000000000000004 <+4>:     mov    %edi,-0x4(%rbp)
               0x0000000000000007 <+7>:     mov    -0x4(%rbp),%eax
               0x000000000000000a <+10>:    add    %eax,%eax
               0x000000000000000c <+12>:    add    -0x4(%rbp),%eax
               0x000000000000000f <+15>:    pop    %rbp
               0x0000000000000010 <+16>:    retq   
            End of assembler dump.

            On peut noter qu'il n'y a que, dans le calcul lui-même, des instructions mov et add dans les deux cas.
            Le calcul -0x4(%rbp) est présent 3 fois dans le b, 2 dans le a. Petit avantage pour a, donc, ici.
            Mais b a un mov de moins, ce que je pense (peut-être à tort ?) plus important.
            De toute façon, peu importe O0.

            Pour O1, O2 et O3, on peut noter que le code généré est strictement identique.

            Donc c'est une partie d'échecs qui se termine en ex-aeco. :'(
            • Partager sur Facebook
            • Partager sur Twitter
              1 juillet 2011 à 20:14:49

              Si tu compiles, puis que tu désassembles, -masm=intel ne sert pas à grand chose :)
              Utilise l'option -S au lieu de -c pour obtenir le code source assembleur (toujours dans le fichier indiqué par -o):
              g++ -masm=intel -S a.cpp -o a0 -O0

              Pour avoir le même format sous gdb, il faut utiliser set disassembly-flavor intel.

              Edit: correction de -s => -S
              • Partager sur Facebook
              • Partager sur Twitter
                1 juillet 2011 à 20:49:51

                J'ai essayé la commande que tu indiques, mais il me crache "undefined reference to `main'".
                Par contre, je note pour le disassembly-flavor.

                Enfin, l'important est de (com|ap)prendre. :D

                Edit : D'ailleurs, il y aurait un moyen de faire un set disassembly-flavor automatique ?
                • Partager sur Facebook
                • Partager sur Twitter
                  1 juillet 2011 à 21:01:50

                  Il faudrait tester avec des unsigned je pense.

                  Il semble me souvenir d'une discussion de comp lang c sur le sujet.

                  Pour en arriver au même point de vue que Goten, finalement.

                  edit:
                  discussion
                  ici.
                  edit2:

                  Citation : Goten


                  tu gagnerais si on vivait dans les années 60. De nos jours ton compilo est bien plus efficace que toi pour faire ce genre de chose et le fera mieux et sûrement même plus agressivement.


                  Tu as un peu forcé le trait là. :-°
                  Ce genre d'opti était encore très, très utilisé dans les années 90.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Zeste de Savoir, le site qui en a dans le citron !
                    1 juillet 2011 à 21:53:13

                    Citation : Equinoxe

                    Edit : D'ailleurs, il y aurait un moyen de faire un set disassembly-flavor automatique ?

                    Oui, il faut ajouter la commande dans $HOME/.gdbinit
                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 juillet 2011 à 11:27:46

                      voila j'ai fini la correction de l'exo "Tic-Tac-Toe", avec les corrections. Voici ;) :

                      main.cpp :
                      #include <iostream>
                      #include <cstdlib>
                      #include "grille.h"
                      
                      using namespace std;
                      
                      int main()
                      {
                          Grille g;
                          int choix = 0;
                          cout << "bienvenu dans ce Tix-Tac-Toe, voici la grille numérotée" << endl;
                          g.afficher();
                          g.init();
                          while(1)
                          {
                              cout << "c'est à '" << g.next() << "' de jouer" << endl;
                              do
                              {
                                  choix = 0;
                                  cout << "quel est votre choix '" << g.next() << "' ?" << endl;
                                  cin >> choix;
                              }while(!g.playAt(choix));
                              #ifdef _WIN32
                                  system("cls");
                              #else
                                  system("clear");
                              #endif
                      
                              g.afficher();
                      
                              if(g.won() == 'e' || g.won() == 'x' || g.won() == 'o')
                                  break;
                          }
                          if(g.won() == 'e')
                              cout << "egalité !!!" << endl;
                          else
                              cout << g.won() << " a gagné la partie" << endl;
                      
                          return 0;
                      }
                      


                      grille.h :

                      #ifndef GRILLE_H
                      #define GRILLE_H
                      
                      #include <iostream>
                      
                      class Grille
                      {
                          public:
                              Grille(char starting = 'o');// génère la grille remplit par défaut par les nombre 1, 2, 3, ..., 7, 8, 9
                              void afficher();// affiche la grille
                              void init();// initialise toute les cases de m_grille à ' '
                              bool playAt(int x, int y = -1);// soit les coordonnées de m_grille, soit un nombre entre 1 et 9
                              char won();// 0 si personne, 1 si o, 2 si x
                              char next();
                          private:
                              char m_grille[3][3];// la grille
                              char m_next;// le prochain "joueur" à jouer : 'o' ou 'x'
                      };
                      
                      #endif
                      


                      grille.cpp :

                      #include "grille.h"
                      
                      using namespace std;
                      
                      Grille::Grille(char starting) : m_next(starting)
                      {
                          for(int i = 0 ; i < 9 ; i++)
                              m_grille[i/3][i%3] = i+'1';
                      }
                      
                      void Grille::afficher()
                      {
                          cout << "     |     |" << endl;
                          cout << "  " << m_grille[2][0] << "  |  " << m_grille[2][1] << "  |  " << m_grille[2][2] << endl;
                          cout << "_____|_____|_____" << endl;
                          cout << "     |     |" << endl;
                          cout << "  " << m_grille[1][0] << "  |  " << m_grille[1][1] << "  |  " << m_grille[1][2] << endl;
                          cout << "_____|_____|_____" << endl;
                          cout << "     |     |" << endl;
                          cout << "  " << m_grille[0][0] << "  |  " << m_grille[0][1] << "  |  " << m_grille[0][2] << endl;
                          cout << "     |     |" << endl;
                      }
                      
                      void Grille::init()
                      {
                          for(int i = 0 ; i < 9 ; i++)
                              m_grille[i/3][i%3] = ' ';
                      }
                      
                      char Grille::next()
                      {
                          return m_next;
                      }
                      
                      bool Grille::playAt(int x, int y)
                      {
                          if(y < 0)
                          {
                              x--;
                              y = x/3;
                              x %= 3;
                          }
                      
                          if(m_grille[y][x] == 'o' || m_grille[y][x] == 'x' || x < 0 || x > 2 || y < 0 || y > 2)
                              return false;
                      
                          m_grille[y][x] = m_next;
                          m_next = (m_next == 'o')?'x':'o';
                          return true;
                      }
                      
                      char Grille::won()
                      {
                          if(((m_grille[0][0] == m_grille[1][1] && m_grille[1][1] == m_grille[2][2]) || (m_grille[0][2] == m_grille[1][1] && m_grille[1][1] == m_grille[2][0])) && (m_grille[1][1] == 'o' || m_grille[1][1] == 'x'))
                          {
                              return m_next;
                          }
                          else
                          {
                              for(int i = 0 ; i < 3 ; i++)
                              {
                                  if(m_grille[i][0] == m_grille[i][1] && m_grille[i][1] == m_grille[i][2] && (m_grille[i][1] == 'o' || m_grille[i][1] == 'x'))
                                      return m_next;
                                  else if(m_grille[0][i] == m_grille[1][i] && m_grille[1][i] == m_grille[2][i] && (m_grille[1][i] == 'o' || m_grille[1][i] == 'x'))
                                      return m_next;
                              }
                              bool b = true;
                              for(int i = 0 ; i < 9 ; i++)
                              {
                                  if(m_grille[i/3][i%3] != 'o' && m_grille[i/3][i%3] != 'x')
                                      b = false;
                              }
                              if(b)
                                  return 'e';
                          }
                          return ' ';
                      }
                      
                      • Partager sur Facebook
                      • Partager sur Twitter
                        2 juillet 2011 à 11:59:00

                        Pour la fonction playat(), c'est moche. Tu ferais mieux (je pense) de faire des surcharges de ta fonction plutôt !
                        • Partager sur Facebook
                        • Partager sur Twitter
                          2 juillet 2011 à 14:13:14

                          if(g.won() == 'e' || g.won() == 'x' || g.won() == 'o')

                          Un peu lourd tu crois pas ? 3 appels à la même fonction ?
                          • Partager sur Facebook
                          • Partager sur Twitter

                          🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                            2 juillet 2011 à 14:30:58

                            pas si lourd que sa (dans la tête du compilateur :) ) il appelle une première fois la fonction. Si elle est vérifier, il ne se casse plus la tête et va donc lire la suite. sinon, il lis l'autre appelle de la fonction etc... (de mon point de vue :) )
                            • Partager sur Facebook
                            • Partager sur Twitter
                              2 juillet 2011 à 14:38:11

                              Ben ça fais 3 appel à la même fonction. Sachant que cette fonction parcoure 2 fois la grille. Et que l'on pourrait récupérer son retour.
                              • Partager sur Facebook
                              • Partager sur Twitter

                              🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                2 juillet 2011 à 15:04:58

                                Bin moi pareil, je me faisais un peu ch*** :p , alors j'ai pensé cet exercice assez simple, donc j'ai essayé :-° :

                                Ça tiens en un fichier, le main.cpp :)
                                /*
                                          ...Tic-Tac-Toe...
                                main.cpp :
                                ----------
                                Creation : 02/07/11
                                Author   : TrackOut
                                Role     : Play the Tic Tac Toe's game
                                */
                                
                                #include <iostream>        //Les
                                #include <vector>          //Includes
                                
                                using namespace std;
                                
                                int Play();                                    //Fonction
                                void PrintScreen(std::vector<char> numbers);   //Print  the : 7 | 8 | 9
                                                                                           //---+---+---
                                int main()                                              //    4 | 5 | 6
                                {                                                            //---+---+---
                                                                                      //      1 | 2 | 3 
                                    int continuer = 0;                         //Play an other game or not?
                                    cout << "You're playin' Tic-Tac-Toe :" << endl;
                                    do
                                    {
                                        int winner = Play();                       //The winner :  
                                        if(winner == 1)                                  //1 for player 1
                                            cout << "Player 1 'XXX' win!" << endl;
                                        if(winner == 2)                                  //2 for player 2
                                            cout << "Player 2 'OOO' win!" << endl;
                                        if(winner == 0)                                  //Or 0 for egality....
                                            cout << "Ohoh! There is no winner!" << endl;
                                            
                                        cout << "Replay? 1.Oui  OU 2.Non" << endl;
                                        cin >> continuer;
                                    }while(continuer == 1);
                                    cout << "Au revoir ;)" << endl;
                                    return 0;                                        //End.
                                }
                                
                                int Play()           //Play() : The hole game
                                {
                                    std::vector<char> numbers;  //this is the grid
                                    numbers.push_back('1');
                                    numbers.push_back('2');
                                    numbers.push_back('3');
                                    numbers.push_back('4');
                                    numbers.push_back('5');
                                    numbers.push_back('6');
                                    numbers.push_back('7');
                                    numbers.push_back('8');
                                    numbers.push_back('9');
                                
                                    std::vector<bool> BoxesOccuped(numbers.size(), false);  //All the boxes occuped
                                    std::vector<bool> Player1Boxes(numbers.size(), false);  //Only the one occuped by player 1
                                    std::vector<bool> Player2Boxes(numbers.size(), false);  //Only the one occuped by player 2
                                
                                    short int ToReturn;                   //The number to return (0, 1, 2)
                                
                                    bool end = false;                 //End of the game?
                                    bool Player1Win = false;          //The player 1 won?
                                    bool Player2Win = false;          //Or is it the player 2?
                                    bool Player1Play = true;          //Who's turn is it?
                                    short int NumberChoice;           //Wich box is chosen?
                                
                                    PrintScreen(numbers);   //Print the grid
                                
                                    do
                                    {
                                        cout << " Please enter the number of your choice    :  ";
                                        cin  >> NumberChoice;
                                        cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";  //Clear screen
                                
                                        if(NumberChoice >= 1 && NumberChoice <= 9)   //Test if number's correct
                                        {
                                            if(!BoxesOccuped.at(NumberChoice -1))   //If this box isn't occuped already
                                            {
                                                if(Player1Play)                     //If it's player 1's turn
                                                {
                                                    numbers.at(NumberChoice - 1) = 'X'; //Replace the number by a X
                                                    Player1Boxes.at(NumberChoice -1) = true; //It's Player 1's box
                                                }
                                                else                                 //If it's player 2's turn
                                                {
                                                    numbers.at(NumberChoice - 1) = 'O';  //Replace the number by a 'O'
                                                    Player2Boxes.at(NumberChoice - 1) = true; //It's Player 2's box
                                                }
                                            }
                                        }
                                        if(((Player1Boxes.at(0) && Player1Boxes.at(4) && Player1Boxes.at(8))) ||       // If
                                                (Player1Boxes.at(0) && Player1Boxes.at(3) && Player1Boxes.at(6)) ||    // Player
                                                (Player1Boxes.at(0) && Player1Boxes.at(1) && Player1Boxes.at(2)) ||    // 1
                                                (Player1Boxes.at(1) && Player1Boxes.at(4) && Player1Boxes.at(7)) ||    // Straits
                                                (Player1Boxes.at(2) && Player1Boxes.at(4) && Player1Boxes.at(6)) ||    // 3
                                                (Player1Boxes.at(2) && Player1Boxes.at(4) && Player1Boxes.at(8)) ||    // Boxes,
                                                (Player1Boxes.at(3) && Player1Boxes.at(4) && Player1Boxes.at(5)) ||    // He
                                                (Player1Boxes.at(6) && Player1Boxes.at(7) && Player1Boxes.at(8)))      // Win
                                        {
                                            end = true; Player1Win = true; Player2Win = false; ToReturn = 1; 
                                        }  //It's the end, the player 1 win, the player 2 didn't won, we return 1
                                
                                        else if(((Player2Boxes.at(0) && Player2Boxes.at(4) && Player2Boxes.at(8))) ||    // If
                                                (Player2Boxes.at(0) && Player2Boxes.at(3) && Player2Boxes.at(6)) ||      // Player
                                                (Player2Boxes.at(0) && Player2Boxes.at(1) && Player2Boxes.at(2)) ||      // 2
                                                (Player2Boxes.at(1) && Player2Boxes.at(4) && Player2Boxes.at(7)) ||      // Straits
                                                (Player2Boxes.at(2) && Player2Boxes.at(4) && Player2Boxes.at(6)) ||      // 3
                                                (Player2Boxes.at(2) && Player2Boxes.at(4) && Player2Boxes.at(8)) ||      // Boxes,
                                                (Player2Boxes.at(3) && Player2Boxes.at(4) && Player2Boxes.at(5)) ||      // He
                                                (Player2Boxes.at(6) && Player2Boxes.at(7) && Player2Boxes.at(8)))        // Win
                                        {
                                            end = true; Player2Win = true; Player1Win = false; ToReturn = 2;
                                        }  //It's the end, the player 2 win, the player 1 didn't won, we return 2
                                
                                        else   //Or
                                        {
                                            short int x;        //x is the number of TRUE boxes in BoxesOccuped
                                            for(unsigned int i = 0; i < numbers.size(); i++)
                                            {
                                                if(BoxesOccuped.at(i))  //If it's true
                                                    x ++;               //x + 1
                                            }
                                            if(x == 9)                  //If x = 9 (all the boxes)
                                            {
                                                end = true; Player1Win = false; Player2Win = false; ToReturn = 0;
                                            }  //It's the end, the player 1 didn't won, the player 2 didn't won, we return 0
                                        }
                                        if(Player1Play)                //If it was the player 1's turn
                                            Player1Play = false;       //Now it's the turn of player 2
                                        else if(!Player1Play)        //If it was the player 2's turn   
                                            Player1Play = true;      //Now it's the turn of player 1
                                        PrintScreen(numbers);
                                    }while(!end);
                                    return ToReturn;
                                }
                                
                                
                                
                                void PrintScreen(std::vector<char> numbers)       //We print the grid
                                {
                                
                                    cout << "\t " << numbers.at(6) << " | " << numbers.at(7) << " | " << numbers.at(8) << endl;
                                    cout << "\t---+---+---" << endl;
                                    cout << "\t " << numbers.at(3) << " | " << numbers.at(4) << " | " << numbers.at(5) << endl;
                                    cout << "\t---+---+---" << endl;
                                    cout << "\t " << numbers.at(0) << " | " << numbers.at(1) << " | " << numbers.at(2) << endl;
                                }  //No need of comment in this function, I think...
                                


                                C'est pas le meilleur code, mais comme j'avais pas envie de m'embeter, du coup y a des variables un peu inutiles.... mais ça marche ^^

                                Voila ;)
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  2 juillet 2011 à 15:11:05

                                  "ça marche"
                                  Sûr ?

                                  Je peux affirmer que non. Rien qu'en regardant la coloration des lignes 18-19 de ton code. :p
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    2 juillet 2011 à 15:14:29

                                    int main() en commentaire ? :-°

                                    Je pense que tu peux faire mieux pour certain truck comme :
                                    if(Player1Play)                //If it was the player 1's turn
                                                Player1Play = false;       //Now it's the turn of player 2
                                            else if(!Player1Play)        //If it was the player 2's turn   
                                                Player1Play = true;      //Now it's the turn of player 1
                                    

                                    Ou :
                                    if(((Player1Boxes.at(0) && Player1Boxes.at(4) && Player1Boxes.at(8))) ||       // If
                                                    (Player1Boxes.at(0) && Player1Boxes.at(3) && Player1Boxes.at(6)) ||    // Player
                                                    (Player1Boxes.at(0) && Player1Boxes.at(1) && Player1Boxes.at(2)) ||    // 1
                                                    (Player1Boxes.at(1) && Player1Boxes.at(4) && Player1Boxes.at(7)) ||    // Straits
                                                    (Player1Boxes.at(2) && Player1Boxes.at(4) && Player1Boxes.at(6)) ||    // 3
                                                    (Player1Boxes.at(2) && Player1Boxes.at(4) && Player1Boxes.at(8)) ||    // Boxes,
                                                    (Player1Boxes.at(3) && Player1Boxes.at(4) && Player1Boxes.at(5)) ||    // He
                                                    (Player1Boxes.at(6) && Player1Boxes.at(7) && Player1Boxes.at(8)))      // Win
                                            {
                                                end = true; Player1Win = true; Player2Win = false; ToReturn = 1; 
                                            }  //It's the end, the player 1 win, the player 2 didn't won, we return 1
                                    
                                            else if(((Player2Boxes.at(0) && Player2Boxes.at(4) && Player2Boxes.at(8))) ||    // If
                                                    (Player2Boxes.at(0) && Player2Boxes.at(3) && Player2Boxes.at(6)) ||      // Player
                                                    (Player2Boxes.at(0) && Player2Boxes.at(1) && Player2Boxes.at(2)) ||      // 2
                                                    (Player2Boxes.at(1) && Player2Boxes.at(4) && Player2Boxes.at(7)) ||      // Straits
                                                    (Player2Boxes.at(2) && Player2Boxes.at(4) && Player2Boxes.at(6)) ||      // 3
                                                    (Player2Boxes.at(2) && Player2Boxes.at(4) && Player2Boxes.at(8)) ||      // Boxes,
                                                    (Player2Boxes.at(3) && Player2Boxes.at(4) && Player2Boxes.at(5)) ||      // He
                                                    (Player2Boxes.at(6) && Player2Boxes.at(7) && Player2Boxes.at(8)))        // Win
                                            {
                                                end = true; Player2Win = true; Player1Win = false; ToReturn = 2;
                                            }  //It's the end, the player 2 win, the player 1 didn't won, we return 2
                                    



                                    Aussi, on peut écrire sur une case ou il y a déjà un nombre, pratique :-°

                                    Pour finir :
                                             X | O | X
                                            ---+---+---
                                             X | O | O
                                            ---+---+---
                                             O | X | X
                                     Please enter the number of your choice    :

                                    o_O


                                    Bonne chance ;)
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                      2 juillet 2011 à 15:29:59

                                      @@che : Je ne suis encore jamais tombé sur ce probleme o_O c'est etrange...

                                      Pour les morceaux de codes : je ne sais pas comment faire mieux en fait ^^

                                      EDIT du code : le main n'est plu en commentaire ^^

                                      Citation : @che

                                      Aussi, on peut écrire sur une case ou il y a déjà un nombre, pratique :-°


                                      Oui, effectivement... mais cette ligne etait sensée l'eviter :
                                      if(!BoxesOccuped.at(NumberChoice -1))   //If this box isn't occuped already
                                      


                                      Et sinon pour la gesion de l'egalité, ça ne marche pas... sauriez vous pourquoi?
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        2 juillet 2011 à 15:36:39

                                        Pour le premier :
                                        if(Player1Play)                //If it was the player 1's turn
                                                    Player1Play = false;       //Now it's the turn of player 2
                                                else if(!Player1Play)        //If it was the player 2's turn   
                                                    Player1Play = true;      //Now it's the turn of player 1
                                        

                                        Peut simplement devenir :
                                        Player1Play = !Player1Play;

                                        Le deuxième, je pense que cela vient de la structure même de ton code.
                                        Pour le reste, j'avoue ne pas avoir le courage de regarder le tout. :(
                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                          2 juillet 2011 à 18:31:57

                                          Voilà !

                                          Comme vous aimez bien l'OO, je vous ai concocté un truc spécialement fait en OO, et dont toutes les fonctionnalités méritant de l'être le sont.

                                          J'ai même fait un petit diaramme de dépendance, pour prouver qu'il n'y a pas de couplage trop fort entre deux classes. (Bon, le diagramme de dépendance m'a pris plus de temps que le code, mais c'est à la fois parce que je suis nul en dessin, que je découvrais inkscape, et que je ne connais aucun vrai programme d'édition d'UML : BoUML, j'ai essayé de m'en servir, j'ai abandonné. Il me semble qu'à une époque j'avais utilisé quelque chose comme graphviz, mais je ne me souviens plus de comment faire précisément.)

                                          Voici tout ce que j'ai fait :
                                          Diagramme de dépendance du TicTacToe
                                          Il est à noter que, puisque chaque flèche ne pointe que vers un élément plus haut que son origine (même si ce n'est pas toujours très visible), il n'y a pas de couplage fort.

                                          Voici, maintenant, le code source (à noter : il y a quelques bouts de c++11 dont je me suis servi) :

                                          main.cpp :
                                          #include <vector>
                                          
                                          #include "Plate.hpp"
                                          #include "Player.hpp"
                                          #include "PlayerFactory.hpp"
                                          #include "User.hpp"
                                          
                                          typedef std::vector<PlayerPtr>  PlayerList;
                                          
                                          int main(int, char**) {
                                              PlayerList players;
                                              Plate plate;
                                          
                                              int nbPlayers = User::AskNbPlayers();
                                              while (--nbPlayers >= 0) {
                                                  players.push_back(PlayerFactory::CreateConsolePlayer());
                                              }
                                          
                                              PlayerPtr winner;
                                              bool stop;
                                              while (!stop) {
                                                  for (PlayerPtr & p : players) {
                                                      User::DisplayPlate(plate);
                                                      plate.Play(p->Play(plate), p->Code());
                                                      if (plate.Ended()) {
                                                          winner = p;
                                                          stop = true;
                                                          break;
                                                      }
                                                  }
                                              }
                                              User::DisplayPlate(plate);
                                              if (plate.ExAeco()) {
                                                  User::ExAeco();
                                              } else {
                                                  User::Winner(winner);
                                              }
                                              return EXIT_SUCCESS;
                                          }
                                          

                                          Position.hpp :
                                          #ifndef POSITION_HPP_INCLUDED__
                                          #define POSITION_HPP_INCLUDED__ 1
                                          
                                          #include <cstdint>
                                          
                                          struct Position {
                                              std::size_t x, y;
                                          };
                                          
                                          #endif
                                          

                                          User.hpp :
                                          #ifndef USER_HPP_INCLUDED__
                                          #define USER_HPP_INCLUDED__ 1
                                          
                                          #include <string>
                                          #include <utility>
                                          
                                          #include "Plate.hpp"
                                          #include "Player.hpp"
                                          #include "Position.hpp"
                                          
                                          struct User
                                          {
                                              static int AskNbPlayers();
                                              static std::pair<std::string, char> CreatePlayer();
                                          
                                              static void DisplayPlate(const Plate &);
                                              static Position AskPosition(const Player &, const Plate &);
                                          
                                              static void ExAeco();
                                              static void Winner(const PlayerPtr &);
                                          };
                                          
                                          #endif
                                          

                                          User.cpp :
                                          #include "User.hpp"
                                          
                                          #include <cstdint>
                                          #include <iostream>
                                          #include <string>
                                          #include <utility>
                                          
                                          #include "Player.hpp"
                                          #include "read.hpp"
                                          
                                          int User::AskNbPlayers()
                                          {
                                              std::cout << "Jouer a combien ? ";
                                              int nbPlayers = read<int>();
                                              while (nbPlayers < 2) {
                                                  if (nbPlayers == 1) {
                                                      std::cout << "Pas si drole quand on est tout seul." << std::endl;
                                                  } else if (nbPlayers == 0) {
                                                      std::cout << "Tu te moques de moi ?" << std::endl;
                                                  } else {
                                                      std::cout <<
                                                          "Un nombre negatif de joueurs, "
                                                          "le voyage dans le temps arrive !"
                                                          << std::endl;
                                                  }
                                                  std::cout << "Jouer a combien ? ";
                                                  nbPlayers = read<int>();
                                              }
                                              if (nbPlayers > 100) {
                                                  std::cout << "Vous etes vraiment beaucoup !" << std::endl;
                                              }
                                              return nbPlayers;
                                          }
                                          
                                          std::pair<std::string, char> User::CreatePlayer()
                                          {
                                              std::cout << "Creation d'un joueur." << std::endl;
                                              std::cout << "Nom ? ";
                                              std::string name = readLine();
                                              std::cout << "Code ? ";
                                              char code = read<char>();
                                          
                                              return std::make_pair(name, code);
                                          }
                                          
                                          #define FOR(V) for (Plate::dim_t V = 0 ; V < Plate::MAX_ ## V ; ++V)
                                          void User::DisplayPlate(const Plate & plate)
                                          {
                                              std::string sep("-+");
                                              FOR(X) {
                                                  sep += "-+";
                                              }
                                          
                                              std::cout << " |";
                                              FOR(X) {
                                                  std::cout << (X + 1) << "|";
                                              }
                                              std::cout << std::endl;
                                              std::cout << sep << std::endl;
                                          
                                              FOR(Y) {
                                                  std::cout << (Y + 1) << "|";
                                                  FOR(X) {
                                                      std::cout << plate(X, Y) << "|";
                                                  }
                                                  std::cout << std::endl;
                                                  std::cout << sep << std::endl;
                                              }
                                          }
                                          
                                          Position User::AskPosition(const Player & player, const Plate & plate)
                                          {
                                              std::size_t X = Plate::MAX_X, Y = Plate::MAX_Y;
                                              while (X >= Plate::MAX_X || Y >= Plate::MAX_Y || !plate.MayPlay({X, Y})) {
                                                  std::cout << "Joueur " << player.Name() << ", ou voulez-vous jouer ?" << std::endl;
                                                  X = read<std::size_t>() - 1;
                                                  Y = read<std::size_t>() - 1;
                                              }
                                              return Position{X, Y};
                                          }
                                          
                                          void User::ExAeco()
                                          {
                                              std::cout << "Ex aeco !" << std::endl;
                                          }
                                          
                                          void User::Winner(const PlayerPtr & player)
                                          {
                                              std::cout << "Bravo " << player->Name() << " !" << std::endl;
                                          }
                                          

                                          read.hpp
                                          #ifndef READ_HPP_INCLUDED__
                                          #define READ_HPP_INCLUDED__ 1
                                          
                                          #include <iostream>
                                          #include <stdexcept>
                                          #include <string>
                                          
                                          template <typename T> T read();
                                          std::string readLine(bool onANewLine = true);
                                          
                                          struct ReadException : std::runtime_error
                                          { ReadException(const std::string &); };
                                          
                                          struct ReadExceptionEOF : ReadException
                                          { ReadExceptionEOF(); };
                                          struct ReadExceptionFail : ReadException
                                          { ReadExceptionFail(); };
                                          struct ReadExceptionBad : ReadException
                                          { ReadExceptionBad(); };
                                          
                                          // ======== IMPLEMENTATION =========
                                          
                                          extern bool read_lastReadWasLine;
                                          
                                          void check();
                                          
                                          template <typename T>
                                          T read() {
                                              T t;
                                              std::cin >> t;
                                              check();
                                              read_lastReadWasLine = false;
                                              return t;
                                          }
                                          
                                          #endif
                                          

                                          read.cpp :
                                          #include "read.hpp"
                                          
                                          #include <iostream>
                                          #include <limits>
                                          #include <string>
                                          
                                          bool read_lastReadWasLine = true;
                                          
                                          std::string readLine(bool onANewLine) {
                                              std::string s;
                                              if (onANewLine && !read_lastReadWasLine) {
                                                  std::cin.ignore(std::numeric_limits<int>::max(), '\n');
                                                  check();
                                              }
                                              std::getline(std::cin, s);
                                              check();
                                              read_lastReadWasLine = true;
                                              return s;
                                          }
                                          
                                          void check()
                                          {
                                              if (std::cin.eof()) {
                                                  throw ReadExceptionEOF();
                                              } else if (std::cin.fail()) {
                                                  throw ReadExceptionFail();
                                              } else if (std::cin.bad()) {
                                                  throw ReadExceptionBad();
                                              }
                                          }
                                          
                                          ReadException::ReadException(const std::string & str)
                                              : std::runtime_error("Read exception : " + str)
                                          { }
                                          
                                          ReadExceptionEOF::ReadExceptionEOF()
                                              : ReadException("EOF") { }
                                          ReadExceptionFail::ReadExceptionFail()
                                              : ReadException("Fail") { }
                                          ReadExceptionBad::ReadExceptionBad()
                                              : ReadException("Bad") { }
                                          

                                          Plate.hpp
                                          #ifndef PLATE_HPP_INCLUDED__
                                          #define PLATE_HPP_INCLUDED__ 1
                                          
                                          #include <cstdint> // std::size_t
                                          
                                          #include "Position.hpp"
                                          
                                          class Plate
                                          {
                                          public:
                                              typedef std::size_t dim_t;
                                          
                                              static const dim_t MAX_X = 3;
                                              static const dim_t MAX_Y = 3;
                                          
                                              static const dim_t REQUIRED_TO_WIN = 3;
                                          
                                              static const dim_t NB_PLACES = MAX_X * MAX_Y;
                                          
                                              Plate();
                                          
                                              const char & at(dim_t x, dim_t y) const;
                                              const char & operator () (dim_t x, dim_t y) const;
                                          
                                              bool Ended(bool CheckExAeco = true) const;
                                              bool ExAeco() const;
                                          
                                              bool MayPlay(Position p) const;
                                              void Play(Position p, char c);
                                          
                                          private:
                                              char & get_(dim_t x, dim_t y);
                                              const char & get_(dim_t x, dim_t y) const;
                                          
                                              char arr_[NB_PLACES];
                                              dim_t nb_occupied_;
                                          };
                                          
                                          #endif
                                          

                                          Plate.cpp :
                                          #include "Plate.hpp"
                                          
                                          #include <algorithm>
                                          #include <iterator>
                                          #include <stdexcept>
                                          #include <sstream>
                                          
                                          #include "Position.hpp"
                                          
                                          #define FOR(V) for (dim_t V = 0 ; V < MAX_ ## V ; ++V)
                                          
                                          Plate::Plate()
                                          {
                                              std::fill(std::begin(arr_), std::end(arr_), ' ');
                                              nb_occupied_ = 0;
                                          }
                                          
                                          const char & Plate::at(Plate::dim_t x, Plate::dim_t y) const
                                          {
                                              if (x < MAX_X && y < MAX_Y) {
                                                  return get_(x, y);
                                              } else {
                                                  std::ostringstream oss;
                                                  oss <<
                                                          "Plate::at(" << x << ", " << y << ") "
                                                          "called, whereas maximum values are "
                                                          "(" << MAX_X << ", " << MAX_Y << ")"
                                                          ;
                                                  throw std::out_of_range(oss.str());
                                              }
                                          }
                                          const char & Plate::operator () (Plate::dim_t x, Plate::dim_t y) const
                                          {
                                              return get_(x, y);
                                          }
                                          
                                          #define CHECK_ON(A, B) \
                                              FOR(A) { \
                                                  player = ' '; \
                                                  onARow = 0; \
                                                  FOR(B) { \
                                                      if (player == get_(X, Y)) ++onARow; \
                                                      else { \
                                                          player = get_(X, Y); \
                                                          onARow = 1; \
                                                      } \
                                                      if (onARow == REQUIRED_TO_WIN && player != ' ') return true; \
                                                  } \
                                              } \
                                              useless()
                                          static void useless() {}
                                          
                                          bool Plate::Ended(bool CheckExAeco) const
                                          {
                                              if (CheckExAeco && ExAeco()) {
                                                  return true;
                                              }
                                              char player;
                                              dim_t onARow;
                                              // Check on rows
                                              CHECK_ON(Y, X);
                                              // Check on columns
                                              CHECK_ON(X, Y);
                                              // Check on diagonals : topleft - bottomright
                                              // FIXME: ATM, it's only possible to use X <= Y
                                              // FIXME: ATM, only strict diagonals are managed
                                              player = ' ';
                                              onARow = 0;
                                              FOR(X) {
                                                  if (player == get_(X, X)) ++onARow;
                                                  else {
                                                      player = get_(X, X);
                                                      onARow = 1;
                                                  }
                                                  if (onARow == REQUIRED_TO_WIN && player != ' ') return true;
                                              }
                                              // Check on diagonals : topright - bottomleft
                                              player = ' ';
                                              onARow = 0;
                                              FOR(X) {
                                                  if (player == get_(X, MAX_X - X - 1)) ++onARow;
                                                  else {
                                                      player = get_(X, MAX_X - X - 1);
                                                      onARow = 1;
                                                  }
                                                  if (onARow == REQUIRED_TO_WIN && player != ' ') return true;
                                              }
                                              // None matched
                                              return false;
                                          }
                                          
                                          bool Plate::ExAeco() const
                                          {
                                              if (nb_occupied_ != NB_PLACES) {
                                                  return false;
                                              }
                                              if (Ended(false)) { // If ended without ex-aeco
                                                  return false;
                                              }
                                              return true;
                                          }
                                          
                                          bool Plate::MayPlay(Position p) const
                                          {
                                              return get_(p.x, p.y) == ' ';
                                          }
                                          void Plate::Play(Position p, char c)
                                          {
                                              if (p.x < MAX_X && p.y < MAX_Y && get_(p.x, p.y) == ' ') {
                                                  get_(p.x, p.y) = c;
                                                  ++nb_occupied_;
                                              }
                                          }
                                          
                                          char & Plate::get_(Plate::dim_t x, Plate::dim_t y)
                                          {
                                              return arr_[y * MAX_X + x];
                                          }
                                          
                                          const char & Plate::get_(Plate::dim_t x, Plate::dim_t y) const
                                          {
                                              return arr_[y * MAX_X + x];
                                          }
                                          

                                          Player.hpp :
                                          #ifndef PLAYER_HPP_INCLUDED__
                                          #define PLAYER_HPP_INCLUDED__ 1
                                          
                                          #include <memory>
                                          #include <string>
                                          
                                          #include "Plate.hpp"
                                          #include "Position.hpp"
                                          
                                          class Player
                                          {
                                          public:
                                              Player(const std::string & name, char code);
                                          
                                              char Code() const;
                                              const std::string & Name() const;
                                          
                                              virtual Position Play(const Plate &) = 0;
                                          
                                          private:
                                              std::string name_;
                                              char code_;
                                          };
                                          
                                          typedef std::shared_ptr<Player> PlayerPtr;
                                          
                                          #endif
                                          

                                          Player.cpp :
                                          #include "Player.hpp"
                                          
                                          #include <string>
                                          
                                          Player::Player(const std::string & name, char code)
                                              : name_(name), code_(code)
                                          { }
                                          
                                          char Player::Code() const
                                          {
                                              return code_;
                                          }
                                          const std::string & Player::Name() const
                                          {
                                              return name_;
                                          }
                                          

                                          PlayerFactory.hpp :
                                          #ifndef PLAYERFACTORY_HPP_INCLUDED__
                                          #define PLAYERFACTORY_HPP_INCLUDED__ 1
                                          
                                          #include "Player.hpp"
                                          
                                          class PlayerFactory
                                          {
                                          public:
                                              static PlayerPtr CreateConsolePlayer();
                                          };
                                          
                                          #endif
                                          

                                          PlayerFactory.cpp :
                                          #include "PlayerFactory.hpp"
                                          
                                          #include <string>
                                          #include <utility>
                                          
                                          #include "ConsolePlayer.hpp"
                                          #include "Player.hpp"
                                          #include "User.hpp"
                                          
                                          PlayerPtr PlayerFactory::CreateConsolePlayer()
                                          {
                                              std::pair<std::string, char> playerInfo = User::CreatePlayer();
                                              return static_cast<PlayerPtr>(
                                                      new ConsolePlayer(playerInfo.first, playerInfo.second)
                                                      );
                                          }
                                          

                                          ConsolePlayer.hpp :
                                          #ifndef CONSOLEPLAYER_HPP_INCLUDED__
                                          #define CONSOLEPLAYER_HPP_INCLUDED__ 1
                                          
                                          #include <string>
                                          
                                          #include "Plate.hpp"
                                          #include "Player.hpp"
                                          #include "Position.hpp"
                                          
                                          class ConsolePlayer : public Player
                                          {
                                          public:
                                              ConsolePlayer(const std::string & name, char code);
                                          
                                              virtual Position Play(const Plate &);
                                          };
                                          
                                          #endif
                                          

                                          ConsolePlayer.cpp :
                                          #include "ConsolePlayer.hpp"
                                          
                                          #include <string>
                                          
                                          #include "Plate.hpp"
                                          #include "Player.hpp"
                                          #include "Position.hpp"
                                          #include "User.hpp"
                                          
                                          ConsolePlayer::ConsolePlayer(const std::string & name, char code)
                                              : Player(name, code)
                                          { }
                                          
                                          Position ConsolePlayer::Play(const Plate & plate)
                                          {
                                              return User::AskPosition(*this, plate);
                                          }
                                          


                                          Qu'en pensez-vous ? :)

                                          Equinoxe

                                          Edit : @TrackOut : Ton erreur vient du fait que tu ne mets pas à jour BoxesOccuped.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            2 juillet 2011 à 19:05:39

                                            Equinoxe : Ajout des auteurs manquants.
                                            Equinoxe : Ajout de nombreuses solutions.
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              2 juillet 2011 à 20:06:32

                                              @Equinoxe: Sympa ton Tic-Tac-Toe (ça m'a permit de me mettre à jour au niveau de la norme en plus :lol: ).
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                2 juillet 2011 à 20:09:08

                                                la norme est-elle vraiment importante ou on peut sans passer ?
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                Anonyme
                                                  2 juillet 2011 à 20:12:30

                                                  Sauf si tu implémente un compilateur, tu peut t'en passer.
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    2 juillet 2011 à 20:12:56

                                                    Je crois que le code ne compilera pas sans la norme.
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      2 juillet 2011 à 20:14:14

                                                      Tu sais, en anglais ta classe "Plate" elle s'appelle "Field", parce que "plate" ça veut dire "assiette" ^^ !
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        2 juillet 2011 à 21:34:55

                                                        Euh ... C'est-à-dire que ... En fait ... Bah ...
                                                        C'est une assiette de morpion !
                                                        En fait, si on veut être précis, ce que je dessine c'est une plaque.
                                                        Parce que, après tout, il n'y a pas de champ de morpion. :p
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          2 juillet 2011 à 21:42:38

                                                          Citation : Equinoxe


                                                          C'est une assiette de morpion !

                                                          Bon appétit !



                                                          :lol:
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                                          [Exercices] Venez vous entraîner !

                                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                          • Editeur
                                                          • Markdown