Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Exercices] Venez vous entraîner !

(v2)

    2 septembre 2011 à 16:23:35

    Puissance 4 - Niveau 2


    N'ayant encore jamais fait d'IA (sauf avec plein de rand() partout :lol: ), je n'ai pas encore fait le niveau 3 mais ça ne serait tarder. Pour l'instant, je vous montre le niveau 2 :
    (Petit bonus : Le joueur peut choisir le nombre de colonne et de ligne de la grille)
    main.cpp
    #include "Menu.h"
    
    int main()
    {
        Menu m;
        m.show();
        return 0;
    }
    


    Grille.h
    #ifndef GRILLE_H_INCLUDED
    #define GRILLE_H_INCLUDED
    
    #include <string>
    
    class Grille
    {
        public:
    
            Grille(int sizeX = 6, int sizeY = 7);
            std::string play(); // fonction principal renvoyant le vainqueur à la fin
            void show() const; // affiche la grille
            int height(int const &y) const; // retourne la hauteur de la colonne choisis
            bool victory() const; // vérifie si un joueur à gagné
            bool full() const; // vérifie si la grille est remplie
            void reset(); // initialise la grille
    
        private:
    
            int m_sizeX, m_sizeY;
            char m_grid[10][10];
            char m_player;
            bool m_equality;
    
    };
    
    #endif // GRILLE_H_INCLUDED
    


    Grille.cpp
    #include <iostream>
    #include "Grille.h"
    
    using namespace std;
    
    Grille::Grille(int sizeX, int sizeY) : m_sizeX(sizeX), m_sizeY(sizeY)
    {
        reset();
    }
    
    void Grille::reset()
    {
        for(int i(0); i < m_sizeX; i++)
            for(int j(0); j < m_sizeY; j++)
                m_grid[i][j] = ' ';
        m_equality = false;
        m_player = 'O';
    }
    
    string Grille::play()
    {
        do
        {
            show();
            m_player = (m_player == 'O')? 'X' : 'O';
            cout << "Player " << 1 + (m_player == 'O') << ", what's your choice ? ";
            int x, y;
            do
            {
                cin >> y;
            }while(y < 0 || y > m_sizeY - 1);
            try
            {
                x = height(y);
            }
            catch(string &erreur)
            {
                cerr << erreur << endl;
                m_player = (m_player == 'O')? 'X' : 'O'; // changement pour que le joueur actuel continue de jouer
            }
            catch(int &x)
            {
                m_grid[x][y] = m_player;
            }
            m_equality = full();
        }while(!(victory() || m_equality));
        show();
        return (m_equality)? "Nobody" : (m_player == 'X')? "Player 1" : "Player 2 ";
    }
    
    int Grille::height(int const &y) const
    {
        for(int i(0); i < m_sizeX; i++)
        {
            if(m_grid[i][y] == ' ')
                throw i;
        }
        throw string("This column is full !");
    }
    
    void Grille::show() const
    {
        for(int i(m_sizeX - 1); i > -1; i--)
        {
            for(int j(0); j < m_sizeY; j++)
                cout << "     |";
            cout << endl;
            for(int j(0); j < m_sizeY; j++)
                cout << "  " << m_grid[i][j] << "  |";
            cout << endl;
            for(int j(0); j < m_sizeY; j++)
                cout << "_____|";
            cout << endl;
        }
        for(int j(0); j < m_sizeY; j++)
            cout << "  "<< j <<"  |";
        cout << endl;
    }
    
    bool Grille::victory() const
    {
        // vérifie les verticales
        for(int i(0); i < m_sizeX - 3; i++)
        {
            for(int j(0); j < m_sizeY; j++)
            {
                if(m_grid[i][j] != ' ' && m_grid[i][j] == m_grid[i + 1][j] && m_grid[i][j] == m_grid[i + 2][j] && m_grid[i][j] == m_grid[i + 3][j])
                    return true;
            }
         }
         // vérifie les horizontales
        for(int i(0); i < m_sizeX; i++)
        {
            for(int j(0); j < m_sizeY - 3; j++)
            {
                if(m_grid[i][j] != ' ' && m_grid[i][j] == m_grid[i][j + 1] && m_grid[i][j] == m_grid[i][j + 2] && m_grid[i][j] == m_grid[i][j + 3])
                    return true;
            }
        }
        // vérifie les diagonales gauches
        for(int i(0); i < m_sizeX - 3; i++)
        {
            for(int j(3); j < m_sizeY; j++)
            {
                if(m_grid[i][j] != ' ' && m_grid[i][j] == m_grid[i + 1][j - 1] && m_grid[i][j] == m_grid[i + 2][j - 2] && m_grid[i][j] == m_grid[i + 3][j - 3])
                    return true;
            }
         }
         // vérifie les diagonales droites
        for(int i(0); i < m_sizeX - 3; i++)
        {
            for(int j(0); j < m_sizeY - 3; j++)
            {
                if(m_grid[i][j] != ' ' && m_grid[i][j] == m_grid[i + 1][j + 1] && m_grid[i][j] == m_grid[i + 2][j + 2] && m_grid[i][j] == m_grid[i + 3][j + 3])
                    return true;
            }
         }
        return false;
    }
    
    bool Grille::full() const
    {
        int full(0);
        for(int i(0); i < m_sizeY; i++)
        {
            if(m_grid[m_sizeX - 1][i] != ' ')
                full++;
        }
        return (full == m_sizeY);
    }
    


    Menu.h
    #ifndef MENU_H_INCLUDED
    #define MENU_H_INCLUDED
    
    class Menu
    {
        public:
    
            Menu();
            void show();
            void play();
            void score();
            void openScore();
            void saveScore();
    
        private:
    
            int player1, player2;
    };
    
    
    #endif // MENU_H_INCLUDED
    


    Menu.cpp
    #include <iostream>
    #include <fstream>
    #include <string>
    #include "Menu.h"
    #include "Grille.h"
    
    using namespace std;
    
    Menu::Menu() : player1(0), player2(0)
    {
    
    }
    
    void Menu::show()
    {
        int choice;
        openScore();
        do
        {
            cout << "*** Connect Four ***\n\n";
            cout << "1 : Play" << endl;
            cout << "2 : Score" << endl;
            cout << "3 : Exit" << endl;
            cout << "Your choice : ";
            do
            {
                cin >> choice;
            }while(choice != 1 && choice != 2 && choice != 3);
            if(choice == 1)
                play();
            if(choice == 2)
                score();
        }while(choice != 3);
        saveScore();
    }
    
    void Menu::play()
    {
        cout << "Enter the height of the grid (4 - 10): ";
        int height;
        do
        {
            cin >> height;
        }while(height < 4 || height > 10);
        cout << "Enter the width of the grid (4 - 10): ";
        int width;
        do
        {
            cin >> width;
        }while(width < 4 || width > 10);
        Grille g(height, width);
        string winner = g.play();
        cout << winner << " has won !" << endl;
        if(winner == "Player 1")
            ++player1;
        if(winner == "Player 2")
            ++player2;
    }
    
    void Menu::score()
    {
        cout << "Player 1 : " << player1 << endl;
        cout << "Player 2 : " << player2 << endl;
    }
    
    void Menu::openScore()
    {
        ifstream scores("/scores.txt");
        if(scores)
        {
            scores >> player1;
            scores >> player2;
        }
        else
        {
            cout << "ERROR: Unable to open the file for reading." << endl;
        }
    }
    
    void Menu::saveScore()
    {
        ofstream saves("/scores.txt");
        if(saves)
        {
            saves << player1;
            saves << player2;
        }
        else
        {
            cout << "ERROR: Unable to open the file." << endl;
    
        }
    }
    

    (Désolé pour le mélange franco-anglais entre la classe Grille et l'attribut m_grid. Je trouvais que ça le faisait moins en anglais)

    N'hésitez pas à commenter mon code, je débute et j'ai besoin de conseil.
    • Partager sur Facebook
    • Partager sur Twitter
      2 septembre 2011 à 22:01:35

      Vous pouvez passer quelques liens intéressants sur min-max et negamax ? Merci :)
      • Partager sur Facebook
      • Partager sur Twitter
        2 septembre 2011 à 22:17:32

        negamax dans le code du tic tac toe ...
        Et le principe expliqué (mais buggué) sur wikipédia.
        • Partager sur Facebook
        • Partager sur Twitter
        C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
          3 septembre 2011 à 16:24:07

          Quelques critiques sur le code de Metallica-z80:

          1) Il y a quelques warnings avec gcc:
          Grille.cpp: In constructor ‘Grille::Grille(int, int)’: Grille.cpp:6:1: warning: ‘Grille::m_player’ should be initialized in the member initialization list Grille.cpp:6:1: warning: ‘Grille::m_equality’ should be initialized in the member initialization list Grille.cpp: In member function ‘std::string Grille::play()’: Grille.cpp:41:20: warning: declaration of ‘x’ shadows a previous local Grille.cpp:27:13: warning: shadowed declaration is here Grille.cpp: In member function ‘bool Grille::full() const’: Grille.cpp:123:11: warning: declaration of ‘full’ shadows a member of `this'

          Je critique juste la grille, le reste n'est pas très intéressant.

          2) Pourquoi un tableau de 10x10 si tu veux laisser la liberté de la taille aux joueurs ?

          3) Tu utilises les exceptions pour sortir d'une boucle dans play(). Ce n'est pas le but des exceptions.

          4) Je n'aime pas trop utiliser un char pour m_player. Ce n'est pas une lettre, c'est une variable qui a deux états autorisés uniquement.

          5) Passer un entier par référence constante est inutile.

          6) cout << "Player " << 1 + (m_player == 'O') << ", what's your choice ? ";
          Tu supposes que le test renvoie un. Je ne suis pas sûr que ce soit standard et c'est de toute façon bizarre. Ceci serait mieux :
          cout << "Player " << (m_player == 'O' ? 2 : 1) << ", what's your choice ? ";

          7) Ta fonction height() est sensée renvoyer un entier, mais elle ne le fait pas. Elle lance une exception.
          • Partager sur Facebook
          • Partager sur Twitter
          Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
            3 septembre 2011 à 16:31:18

            6) C'est très standard tant que tu mets des parenthèses comme il l'a fait. Mais des raisons de lisibilités, je choisirais toujours la seconde version. (N'allez pas me parler d'optimisation, le compilo fait ça mieux que nous pauvres humains !).
            • Partager sur Facebook
            • Partager sur Twitter
              3 septembre 2011 à 16:39:00

              Citation : germino

              6) C'est très standard tant que tu mets des parenthèses comme il l'a fait. Mais des raisons de lisibilités, je choisirais toujours la seconde version. (N'allez pas me parler d'optimisation, le compilo fait ça mieux que nous pauvres humains !).



              Non c'est pas standard. 0 c'est false, true c'est tout sauf 0. Nul part y'a une garantie que ça sera 1.

              edit : autant pour moi, en cas de promotion intégrale la valeur 1 est bien garantie.
              • Partager sur Facebook
              • Partager sur Twitter
                3 septembre 2011 à 16:48:12

                bool x = true
                

                x = 1
                int x = 24;
                if(x)
                {
                }
                

                on passe obligatoirement dedans.


                Initialiser à true et afficher ce true est tout le temps 1, mais nimporte quoi d'autre peut afficher true. C'est pas pareil ;)
                • Partager sur Facebook
                • Partager sur Twitter
                  3 septembre 2011 à 16:50:41

                  Citation : TrackOut

                  bool x = true
                  


                  x = 1

                  int x = 24;
                  if(x)
                  {
                  }
                  


                  on passe obligatoirement dedans.


                  Initialiser à true et afficher ce true est tout le temps 1, mais nimporte quoi d'autre peut afficher true. C'est pas pareil ;)



                  C'est pas une question "d'afficher" mais de promotion. (voir mon edit).

                  Pour référence (et parce que le comportement d'un compilo n'est pas un gage de validité):
                  4.7[conv.integral] / 4:

                  Citation


                  If the source type is bool, the value false is converted to zero
                  and the value true is converted to one.




                  (mais c'était une erreur de lecture de ma part au début de toute façon)
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Anonyme
                    3 septembre 2011 à 18:00:33

                    Bonjour à tous. Je débute en programmation (à savoir que j'ai fini le tuto C++ il y a moins d'un mois) et je tente de m'exercer. J'ai donc fait les exercices Tic Tac Toe (qui fonctionne, mais j'ai pas implémenté d'IA parce que c'est un peu difficile) et Puissance 4.

                    Mes codes sont donc très brouillons et vous sembleront parfois bizarres et c'est justement pourquoi je les poste. Est-ce que mes codes sont propres ? Bien ordonnés ? Que pourrais-je faire pour les améliorer ?

                    Je ne poste que le Puissance 4 mais si je peux, je posterais aussi le Tic Tac Toe (mais ça en énerverait peut être certains de revenir sur un programme aussi "facile").


                    Je le poste pour deux raisons : savoir si je code "bien" (code propre, ordonné, améliorations possibles, etc ...) et comprendre pourquoi ma fonction Grille::gagner() ne fonctionne pas.


                    main.cpp
                    #include <iostream>
                    #include "Grille.h"
                    
                    using namespace std;
                    
                    int main()
                    {
                        Grille grille;
                    
                        grille.jouer();
                    
                    
                        return 0;
                    }
                    


                    Grille.h
                    #ifndef GRILLE_H_INCLUDED
                    #define GRILLE_H_INCLUDED
                    
                    class Grille{
                    
                        public:
                            Grille();
                            void jouer();
                            bool gagner() const;
                            bool estRemplie() const;
                            void afficher();
                            void modifier(int a);
                    
                        private:
                            char m_grille[10][10];
                            int m_joueur;
                            static int colonne;
                    
                    };
                    
                    
                    #endif // GRILLE_H_INCLUDED
                    


                    Grille.cpp
                    #include <iostream>
                    #include "Grille.h"
                    
                    Grille::Grille()
                    {
                        for(int i(0); i < 10; i++)
                        {
                            for(int j(0); j < 10; j++)
                            {
                                m_grille[i][j] = ' ';
                            }
                        }
                    
                        m_joueur = 1;
                    }
                    
                    
                    void Grille::afficher()
                    {
                        for(int i(0); i < 10; i++)
                        {
                            std::cout << " " << m_grille[i][0] << " | " << m_grille[i][1] << " | " << m_grille[i][2] << " | " << m_grille[i][3] << " | " << m_grille[i][4] << " | " << m_grille[i][5] << " | " << m_grille[i][6] << " | " << m_grille[i][7] << " | " << m_grille[i][8] << " | " << m_grille[i][9] << std::endl;
                            if(i != 9)
                                std::cout << " - + - + - + - + - + - + - + - + - + -" << std::endl;
                        }
                    }
                    
                    int Grille::colonne = 0;
                    
                    void Grille::jouer()
                    {
                        do{
                            Grille::afficher();
                            std::cout << "Quelle colonne ? ";
                            std::cin >> colonne;
                            std::cout << std::endl << std::endl;
                    
                            if(colonne < 11)
                            {
                              Grille::modifier(colonne);
                            }
                    
                            if(!gagner())
                            {
                                if(m_joueur == 1)
                                    m_joueur++;
                                else
                                    m_joueur--;
                            }
                    
                        }while(!Grille::gagner() && !Grille::estRemplie());
                    
                        Grille::afficher();
                        if(Grille::gagner())
                            std::cout << "Le joueur " << m_joueur << " gagne la partie !" << std::endl;
                        else
                            std::cout << "La partie est nulle !";
                    }
                    
                    void Grille::modifier(int a)
                    {
                        bool modif(false);
                        int compteur(9); // Sert à arcourir la colonne de ligne en ligne
                    
                        do{
                            if(m_grille[compteur][a-1] != 'X' && m_grille[compteur][a-1] != 'O')
                            {
                                if(m_joueur == 1)
                                    m_grille[compteur][a-1] = 'X';
                                else
                                    m_grille[compteur][a-1] = 'O';
                    
                                modif = true;
                            }
                            else
                            {
                                compteur--;
                                modif = false;
                            }
                        }while(!modif);
                    }
                    
                    bool Grille::gagner() const
                    {
                        for(int i(0); i < 10; i++)
                        {
                            for(int j(0); j < 10; j++)
                            {
                                // Test horizontaux
                                if(m_grille[i][j] == m_grille[i][j+1] && m_grille[i][j] == m_grille[i][j+2] && m_grille[i][j] == m_grille[i][j+3] && m_grille[i][j] != ' ')
                                    return true;
                                //Test verticaux
                                else if(m_grille[i][j] == m_grille[i+1][j] && m_grille[i][j] == m_grille[i+2][j] && m_grille[i][j] == m_grille[i+3][j] && m_grille[i][j] != ' ')
                                    return true;
                                // Test pour la diagonale montante
                                else if(m_grille[i][j] == m_grille[i+1][j+1] && m_grille[i][j] == m_grille[i+2][j+2] && m_grille[i][j] == m_grille[i+3][j+3] && m_grille[i][j] != ' ')
                                    return true;
                                // Test pour la diagonale descendante
                                else if(m_grille[i][j] == m_grille[i+1][j-1] && m_grille[i][j] == m_grille[i+2][j-2] && m_grille[i][j] == m_grille[i+3][j-3] && m_grille[i][j] != ' ')
                                    return true;
                                else
                                    return false; // On retourne faux si les 4 testes sont faux
                            }
                        }
                    }
                    
                    bool Grille::estRemplie() const// Retourne vrai si TOUS les caractères sont différents d'un espace
                    {
                        for(int i(0); i < 10; i++)
                        {
                            for(int j(0); j < 10; j++)
                            {
                                if((m_grille[i][j] == ' '))
                                    return false;
                            }
                        }
                    
                        return true;
                    }
                    




                    PS : Je n'écris pas mes fonctions, variables et commentaires en anglais car ce ne sont pas des codes partagés ailleurs que sur le Sdz.

                    PS2 : S'il manque des commentaires (ou si vous ne comprenez pas une fonction ou une ligne de code (même si j'en doute de ça)), n'hésitez pas à me le signaler.

                    PS3 : J'ai découvert il y a pas longtemps la bibliothèque boost mais je me demandais s'il y avait un tutoriel (sur le Sdz, je n'en ai pas trouvé) présentant boost et "apprenant à s'en servir", en français de préférence. Il y a la doc mais c'est un peu monstrueux pour tenter d'apprendre à utiliser une telle bibliothèque (qui, à ce que j'ai compris, serait une sorte d'extension de la SL).
                    • Partager sur Facebook
                    • Partager sur Twitter
                      3 septembre 2011 à 18:15:15

                      @ Nanoc :

                      1) C'est bizarre, il ne me semble pas avoir vu de warning à la compilation o_O .

                      2) Je n'ai pas trouvé mieux. Comment ferais-tu ?

                      3) L’exception ne fait pas sortir de la boucle. Elle affiche que la colonne est pleine pour refaire jouer le joueur actuel.

                      4) C'est une façon de voir les choses, mais par la suite, je pourrais par exemple laisser le joueur choisir son symbole.

                      5) OK.

                      6) Je n'y avais pas pensé. C'est vrai que c'est plus lisible.

                      7) J'aurais pu la mettre en void mais ça permet de me repérer et de savoir qu'elle renvoie (par exception) un int quand la colonne n'est pas pleine.
                      • Partager sur Facebook
                      • Partager sur Twitter
                        3 septembre 2011 à 18:16:08

                        @ @rthur : Parce que ta fonction est const?
                        • Partager sur Facebook
                        • Partager sur Twitter
                          3 septembre 2011 à 18:20:46

                          @Mettalica-z80:

                          1) Parce que tu ne les as pas activé.

                          2) vector

                          3) Ce n'est pas fait pour ça. Une exception est là pour activer un traitement particulier quand un une erreur survient. Pas pour sortir d'une boucle de deux manières différentes. C'est une grave erreur et ce genre de chose ne serait jamais accepté dans aucun projet sérieux.

                          4) Il faut séparer le fait qu'on a besoin d'une variable pour indiquer quel joueur est en train de jouer et la variable contenant le symbole de chaque joueur. La première est une variable à deux états qui change à chaque tour. La deuxième est une constante lors d'une partie.

                          7) C'est lié à 3.
                          • Partager sur Facebook
                          • Partager sur Twitter
                          Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
                          Anonyme
                            3 septembre 2011 à 18:24:16

                            @TrackOut : Nan, ma fonction ne fonctionnait pas même en non const.

                            En fait ma fonction gagner() renvoie true quand deux colonnes sont pleines du même signe. Bon pour dire vrai, la fonction ne fonctionne pas du tout correctement, or qu’algorithmiquement elle semble correcte (sauf si je me trompe).


                            Autrement, pourrais-je avoir des commentaires sur mon code (propreté, ordonnancement, améliorations possibles, ...) ainsi qu'une explication sur la fonction gagner() (comme expliqué juste au dessus).
                            • Partager sur Facebook
                            • Partager sur Twitter
                              3 septembre 2011 à 18:27:35

                              @ Nanoc :
                              1) Pourtant quand je fais rebuild (sous C::B), il m'écrit :
                              Process terminated with status 0 (0 minutes, 1 seconds)
                              0 errors, 0 warnings

                              2) OK, je vais changer ça.

                              3) Que faire alors ? Au début, je renvoyé -1 pour dire que la colonne était pleine puis je traitais ce cas et c'est pour cela qu'il m'a paru plus judicieux d'utiliser les exceptions.

                              4) D'accord.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                3 septembre 2011 à 18:32:52

                                Metallika : Quelles sont tes options de compilation?
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  3 septembre 2011 à 18:39:02

                                  Citation : @rthur59

                                  Autrement, pourrais-je avoir des commentaires sur mon code (propreté, ordonnancement, améliorations possibles, ...) ainsi qu'une explication sur la fonction gagner() (comme expliqué juste au dessus).


                                  Ben, premièrement, tu as fait ce qui s'appelle une "god-classe" (classe qui gère tout). Ce n'est par exemple pas à la classe Grille de gérer la partie... (la fonction jouer n'a rien à faire dedans) cette fonction aurait plus sa place dans le main ou dans une classe Joueur...
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    3 septembre 2011 à 18:42:33

                                    Citation : TrackOut

                                    Metallika : Quelles sont tes options de compilation?



                                    Je ne sais pas trop où les trouver mais pourtant, j'ai cocher l'option "enable all compiler warnings [...] -Wall"
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      3 septembre 2011 à 18:43:40

                                      Coche aussi -WExtra (ou dans le genre :euh: )
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        3 septembre 2011 à 18:46:15

                                        Pour les options de compilation, c.f. mon tuto en signature.

                                        Pour le point 3, je te laisse réfléchir. Utilise des booléens par exemple.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
                                          3 septembre 2011 à 19:06:03

                                          Citation : TrackOut

                                          Coche aussi -WExtra (ou dans le genre :euh: )



                                          Ça ne change toujours rien :(

                                          Citation : Nanoc

                                          Pour les options de compilation, c.f. mon tuto en signature.

                                          Pour le point 3, je te laisse réfléchir. Utilise des booléens par exemple.



                                          OK, j'y jetterais un coup d'oeil quand j'aurais le temps.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            3 septembre 2011 à 23:42:25

                                            Metallica-z80 > -Wall -Wextra -pedantic ; et -Werror (ou -Werrors, plus sûr) pour être sûr de n'avoir rien loupé ^^
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              9 septembre 2011 à 1:33:53

                                              Bonjour !

                                              Je viens de faire le jeu Tic Tac Toe, pour le moment sans l'IA. Je voudrais avoir vos commentaires sur mon code :)
                                              Le programme est constitué de deux classes : Game pour gérer le jeu et Grid pour gérer la grille.
                                              Voici le code sources des 5 fichiers :
                                              #include <iostream>
                                              #include "Game.h"
                                              
                                              int main()
                                              {
                                                  Game newGame; //L'objet newGame gérera le cours du jeu
                                                  return 0;
                                              }
                                              


                                              #ifndef GAME_H_INCLUDED
                                              #define GAME_H_INCLUDED
                                              
                                              #include <iostream>
                                              
                                              class Grid;
                                              class Game //Classe pour gérer le jeu
                                              {
                                                  public:
                                                  Game();
                                                  void new1vs1Game();
                                                  void newSoloGame(); //Indisponible pour le moment
                                                  void setWinner(int winner); // Setter pour determiner le gagnant
                                                  enum mode { DUEL, SOLO}; //Enumeration qui determine le mode du jeu
                                                  ~Game();
                                              
                                                  private:
                                                  mode gameMode; //Mode solo ou duel
                                                  int currentPlayer; //le joueur qui a la main (1 ou 2)
                                                  Grid *m_grid ; //la grille
                                                  int m_winner; //le gagnant (1 ou 2) si 0, alors c'est une partie nulle
                                              };
                                              
                                              
                                              #endif // GAME_H_INCLUDED
                                              


                                              #include "Game.h"
                                              #include "Grid.h"
                                              using namespace std ;
                                              Game::Game()
                                              {
                                                  cout<<"Choisissez le mode de jeu :"<<endl;
                                                  cout<<"1) Mode 2 joueurs"<<endl;
                                                  cout<<"2) Mode solo"<<endl;
                                                  int input = 0 ;
                                                  cin>>input ;
                                                  gameMode = (input==1) ? DUEL : SOLO ;
                                                  m_grid = new Grid;
                                                  m_grid->showGrid();
                                                  if(gameMode==DUEL) //pour le moment, que le mode duel
                                                      new1vs1Game();
                                              }
                                              Game::~Game()
                                              {
                                                  delete m_grid ;
                                              }
                                              void Game::new1vs1Game()
                                              {
                                                  currentPlayer = 1 ; // Joueur 1 a la main
                                                  int input = 0 ;
                                                  int round = 1 ; //numéro de la manche
                                                  do
                                                  {
                                                      do
                                                      {
                                                          cout<<"Joueur "<<currentPlayer<<" :"<<endl;
                                                          cin>>input;
                                                      }
                                                      while(!m_grid->isValid(input)); // on redemande la saise tant que la case est invalide
                                              
                                                      m_grid->update(input, currentPlayer); //on met à jour la grille
                                                      m_grid->showGrid();
                                                      currentPlayer = (currentPlayer == 1) ? 2 : 1; // Si c'est le joueur 1, alors ca devient 2 et vice versa
                                                      round++ ; // On incrément le numéro de la manche
                                                  }
                                                  while(!m_grid->verify(round,this)); // Tant que la partie n'est pas finie
                                              
                                                  if(m_winner == 0)
                                                      cout<<"Partie nulle !"<<endl; // à la fin si m_winner=0 alors c'est une partie nulle
                                                  else
                                                      cout<<"Joueur "<<m_winner<<" est le gagnant !"<<endl; //Sinon c'est 1 ou 2, le gagnant est ainsi determiné
                                              }
                                              void Game::setWinner(int winner) //setter du gagnant
                                              {
                                                  m_winner = winner;
                                              }
                                              



                                              #ifndef GRID_H_INCLUDED
                                              #define GRID_H_INCLUDED
                                              
                                              #include <iostream>
                                              #include "Game.h"
                                              class Grid //classe pour gérer le jeu
                                              {
                                                  public:
                                                  Grid();
                                                  void showGrid(); //affiche la grille
                                                  void update(int cell, int currentPlayer); //met à jour la grille
                                                  bool verify(int round, Game* gameObject); //verifie si la partie est finie ou pas
                                                  bool isValid(int input); //verifie si la case input est valide ou pas
                                              
                                                  private:
                                                  char currentGrid[9]; //l'état de la grille (peut comporter 1~9 , X ou O )
                                              
                                              };
                                              
                                              #endif // GRID_H_INCLUDED
                                              


                                              #include "Grid.h"
                                              
                                              using namespace std;
                                              Grid::Grid() //Le Constructeur initialise la grille
                                              {
                                                  for (char c = 0 ; c < 9 ; ++c) currentGrid[c] = c + '1';
                                              
                                              }
                                              void Grid::showGrid()
                                              {
                                                  // Il n'y a rien à commenter...
                                                  for(int j=1;j<=11;j++)
                                                      cout<<"-" ;
                                                  cout<<endl;
                                                  for(int i=0; i<9; i++)
                                                  {
                                                      cout << currentGrid[i] << " | ";
                                                      if((i+1)%3 == 0)
                                                      {
                                                          cout<<endl;
                                                          for(int j=1;j<=11;j++)
                                                              cout<<"-" ;
                                                          cout<<endl;
                                                      }
                                              
                                                  }
                                              }
                                              void Grid::update(int cell, int currentPlayer)
                                              {
                                                  char marker = ' '; // La marque X ou O
                                                  //X pour joueur 1 et O pour joueur 2
                                                  marker = (currentPlayer ==1) ? 'X' : 'O' ;
                                              
                                                  currentGrid[cell-1] = marker ; //La case correspondante est marquée de X ou O selon le joueur à qui est la main
                                              }
                                              bool Grid::verify(int round, Game* gameObject)
                                              {
                                                  int output = 0; // contiendra le numéro du joueur gagnant
                                              
                                                  //Tous les cas possible pour qu'il y ait un gagnant
                                                  if(currentGrid[0] == currentGrid[1] && currentGrid[0] == currentGrid[2])
                                                      output = (currentGrid[0] == 'X') ? 1 : 2 ; //Si les cases sont de meme signe, le gagnant est determiné selon le signe qui lui correspond X pour joueur 1 et O pour joueur 2
                                                  else if(currentGrid[3] == currentGrid[4] && currentGrid[3] == currentGrid[5])
                                                      output = (currentGrid[3] == 'X') ? 1 : 2 ;
                                                  else if(currentGrid[6] == currentGrid[7] && currentGrid[6] == currentGrid[8])
                                                      output = (currentGrid[6] == 'X') ? 1 : 2 ;
                                                  else if(currentGrid[0] == currentGrid[3] && currentGrid[0] == currentGrid[6])
                                                      output = (currentGrid[0] == 'X') ? 1 : 2 ;
                                                  else if(currentGrid[1] == currentGrid[4] && currentGrid[1] == currentGrid[7])
                                                      output = (currentGrid[1] == 'X') ? 1 : 2 ;
                                                  else if(currentGrid[2] == currentGrid[5] && currentGrid[2] == currentGrid[8])
                                                      output = (currentGrid[2] == 'X') ? 1 : 2 ;
                                                  else if(currentGrid[0] == currentGrid[4] && currentGrid[0] == currentGrid[8])
                                                      output = (currentGrid[0] == 'X') ? 1 : 2 ;
                                                  else if(currentGrid[2] == currentGrid[4] && currentGrid[2] == currentGrid[6])
                                                      output = (currentGrid[2] == 'X') ? 1 : 2 ;
                                                  else if(round==10) //Si la 9ieme manche s'est déroulée et toujours pas de gagnant, alors c'est une partie nulle
                                                      return true;
                                              
                                                  if(output==1 || output==2)
                                                  {
                                                      gameObject->setWinner(output);
                                                      return true;
                                                  }
                                                  return false ;
                                              }
                                              bool Grid::isValid(int input)
                                              {
                                                  if(input<=9 && input>=1) //L'entrée doit etre comprise entre 1 et 9
                                                  {
                                                      if(currentGrid[input-1] != 'X' && currentGrid[input-1] != 'O') //et la case correpondante n'est déja pas occupée
                                                          return true;
                                                      else
                                                          return false;
                                                  }
                                                  else
                                                      return false;
                                              }
                                              



                                              J'espère avoir de retours plutôt positifs, même si j'en doute :-°
                                              Le code est clair, indenté et commenté. Les identificateurs sont en anglais.
                                              J'attends vos commentaires puis je me lance dans l'IA.
                                              Merci beaucoup :)


                                              • Game : Ajout des énumérations.
                                              • Grid.cpp :Utilisation de l'opérateur ? pour déterminer le marqueur correspondant au joueur.
                                              • Utilisation des références croisées. verify prend maintenant un pointeur vers l'objet newGame en argument.
                                              • Ajout du destructeur dans Game
                                              </span></span>
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                9 septembre 2011 à 6:35:08

                                                1) Pour commencer, je trouve inappropriée d'utiliser un int pour le mode de jeu (gameMode). Tu devrais plutôt utiliser un bool ou un enum.
                                                2) Ensuite, pour l'initialisation de ta grille, utilise une bouucle for au lieu de récrire 9 fois un code presque identique.
                                                3) Enfin, pour le changement de joueur, tu utilise deux tests plus deux affectations. Comme je vois que tu sais te servir de l'opérateur "?", c'est le moment idéal pour t'en servir.





                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  9 septembre 2011 à 7:17:46

                                                  static int m_winner; //le gagnant (1 ou 2) si 0, alors c'est une partie nulle
                                                  

                                                  Pourquoi cet attribut en static ???
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    9 septembre 2011 à 13:39:31

                                                    @Metallica-z80
                                                    1)Un bool... c'est pas un truc pour dire oui ou non... J'opterai pour l'enum, même si je les ai très très rarement manipulé.
                                                    2)C'est fait par obligation. Comme c'est un tableau de char, et i est un int, j'ai beau cherché une fonction qui convertit int en char mais j'ai pas trouvé ce qu'il me fallait. Si tu connais une fonction qui fait le boulot dis le moi ;)
                                                    3)Ok.

                                                    @germino
                                                    Au fait, si je ne met pas static, ça compile pas et ça me sort cette erreur :
                                                    invalid use of member 'Game::m_winner' in static member function|

                                                    Remarque que la fonction en l’occurrence est la fonction statique setWinner.
                                                    Je viens d'avoir une idée pour remédier au problème, mais je veux savoir comment remédier à cela en utilisant la fonction en static.
                                                    L'idée est de mettre Grid amie de Game.


                                                    J'éditerai mon code et je l'adapterai au fur et à mesure ;)

                                                    Merci :)
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      9 septembre 2011 à 13:53:03

                                                      friend : tu oublies.
                                                      static : idem.
                                                      si tu enlèves tous tes static et que tu envoies une référence sur Game à la fonction Grid::verify(), ça résoudra tous tes problèmes (et par la même occasion, ça me permettra de garder quelques cheveux :-° )
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        9 septembre 2011 à 14:18:41

                                                        Citation : germino

                                                        friend : tu oublies.
                                                        static : idem.
                                                        si tu enlèves tous tes static et que tu envoies une référence sur Game à la fonction Grid::verify(), ça résoudra tous tes problèmes (et par la même occasion, ça me permettra de garder quelques cheveux :-° )



                                                        Lol :honte:
                                                        Bon j'obtiens une erreur à la ligne Grid *m_grid ; du fichier Game.h
                                                        ISO C++ forbids declaration of 'Grid' with no type|
                                                        
                                                        expected ';' before '*' token|


                                                        J'ai juste changer la fonction verify (j'ai utilisé le pointeur et pas les référence) :
                                                        bool verify(int round, Game* gameObject);
                                                        Pourquoi pointeur et pas référence ? Parce que au moment d'utiliser verify dans la classe Game, quelle référence puis-je lui passer en argument ? J'ai opté pour le pointeur et j'ai utilisé this .

                                                        Edit: Je n'ai pas édité le code précédent.
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          9 septembre 2011 à 15:17:42

                                                          t'as raison pour le pointeur.
                                                          error: je pense que c'est une référence croisée.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          [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