M2103-TP9-EXO-0-Corrigé

/**
 *
 * @file   partied_echec.cpp
 *
 * @author M. Laporte
 *
 * @date   06/06/2019
 *
 * @brief  M2103 Testt 2 partie d'échec
 *
 **/

#include <vector>
#include <string>
#include <iostream>

 using namespace std;

namespace
{
    class Piece;

    #define classdef typedef
    classdef vector <Piece *> VPiece;
    enum Couleur {KBlanc, KNoir};
    enum Piece_t {KAucun, KRoi, KReine, KFou, KCavalier, KTour, KPion};
    vector <string> vNom {"", "Roi", "Reine", "Fou",
                          "Cavalier", "Tour", "Pion"};

    class Case;
    class Echiquier;
    class Joueur;

    class Piece
    {
      protected :
        Couleur  myCouleur;
        Piece_t  myNom;
        Case   * myCase;
        Joueur * myJoueur;
      public :
        Piece (Piece_t nom, Couleur couleur)
              : myCouleur (couleur), myNom (nom) {}

        Couleur getCouleur (void) const { return myCouleur; }
        Piece_t getNom     (void) const { return myNom; }
        Case *  getCase    (void) const { return myCase; }
        void setJoueur (Joueur * joueur) { myJoueur = joueur; }
        void setCase   (Case * laCase)   { myCase = laCase; }

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Piece (void) {}

    }; // Piece

    class Pion : public Piece
    {
      public :
        Pion (Piece_t nom, Couleur couleur) : Piece (nom, couleur)
        {}

        virtual bool operator () (Case * laCase) { return true; }
        virtual ~Pion (void) {}

    }; // Pion

    class Roi : public Piece
    {
      public :
        Roi (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Roi (void) {}

    }; // Roi

    class Reine : public Piece
    {
      public :
        Reine (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Reine (void) {}

    }; // Reine

    class Fou : public Piece
    {
      public :
        Fou (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Fou (void) {}

    }; // Fou

    class Cavalier : public Piece
    {
      public :
        Cavalier (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Cavalier (void) {}

    }; // Cavalier

    class Tour : public Piece
    {
      public :
        Tour (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Tour (void) {}

    }; // Tour

    class Case
    {
        unsigned myLigne;
        unsigned myColonne;
        Piece  * myPiece;
      public :
        Case (unsigned ligne = 0, unsigned colonne = 0,
              Piece * piece = nullptr)
            : myLigne (ligne), myColonne (colonne), myPiece (piece) {}
        unsigned getLigne   (void) const      { return myLigne; }
        unsigned getColonne (void) const      { return myColonne; }
        Piece *  getPiece   (void) const      { return myPiece; }

        void     setPiece   (Piece * piece)   { myPiece  = piece; }

    }; // Case
    class Echiquier
    {
        vector <vector <Case>> myPlateau;
        vector <Piece>         myPieces;
        void addPions (Couleur couleur, unsigned numLigne)
        {
            for (unsigned col (0); col < myPlateau [numLigne].size ();
                 ++col)
            //for (Case & laCase : myPlateau [numLigne])
            {
                myPieces.push_back (Pion (KPion, couleur));
                myPieces.back().setCase (& (myPlateau [numLigne][col]));
                myPlateau [numLigne][col].setPiece (& (myPieces.back ()));
            }
        }// addPions()

      public :
        Echiquier (void)
        {
            myPlateau.resize (8);
            for (unsigned li (0); li < 8; ++li)
            {
                myPlateau [li].resize (8);
                for (unsigned col (0); col < 8; ++col)
                {
                    myPlateau [li][col] = Case (li, col);
                }
            }
            myPieces.reserve (32);
            // placer les pions
            addPions (KBlanc, 6);
            addPions (KNoir,  1);

            // placer les reines
            myPieces.push_back        (Reine (KReine, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][3]));
            myPlateau [0][3].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Reine (KReine, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][3]));
            myPlateau [7][3].setPiece (& (myPieces.back ()));

            // placer les rois
            myPieces.push_back        (Roi (KRoi, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][4]));
            myPlateau [0][4].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Roi (KRoi, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][4]));
            myPlateau [7][4].setPiece (& (myPieces.back ()));

            // placer les fous
            myPieces.push_back        (Fou (KFou, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][2]));
            myPlateau [0][2].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Fou (KFou, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][2]));
            myPlateau [7][2].setPiece (& (myPieces.back ()));

            myPieces.push_back        (Fou (KFou, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][5]));
            myPlateau [0][5].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Fou (KFou, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][5]));
            myPlateau [7][5].setPiece (& (myPieces.back ()));

            // placer les cavaliers
            myPieces.push_back        (Cavalier (KCavalier, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][1]));
            myPlateau [0][1].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Cavalier (KCavalier, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][1]));
            myPlateau [7][1].setPiece (& (myPieces.back ()));

            myPieces.push_back        (Cavalier (KCavalier, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][6]));
            myPlateau [0][6].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Cavalier (KCavalier, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][6]));
            myPlateau [7][6].setPiece (& (myPieces.back ()));

            // placer les tours
            myPieces.push_back        (Tour (KTour, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][0]));
            myPlateau [0][0].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Tour (KTour, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][0]));
            myPlateau [7][0].setPiece (& (myPieces.back ()));

            myPieces.push_back        (Tour (KTour, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][7]));
            myPlateau [0][7].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Tour (KTour, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][7]));
            myPlateau [7][7].setPiece (& (myPieces.back ()));

        } // Echiquier()

        VPiece getPieces (const Couleur & couleur) const
        {
            vector <Piece *> v;
            v.reserve (16);
            unsigned cpt = 0;
            for (vector <Case> vCase : myPlateau)
                for (Case laCase : vCase)
                {
                    if (laCase.getPiece () != nullptr)
                    {						//&&
                        if (laCase.getPiece ()->getCouleur () == couleur)
                            v.push_back (laCase.getPiece ());
                    }
                }
            return v;

        } // getPieces()

        Case * getCase (unsigned i, unsigned j)
        { return &(myPlateau[i][j]); }

    }; // Echiquier
    
    class Joueur
    {
        string myNom;
        VPiece myPieces;
        Echiquier * myPlateau;
      public :
        Joueur (const string & nom, const VPiece &vPieces,
                 Echiquier * plateau)
               : myNom (nom), myPieces (vPieces), myPlateau (plateau)  {}

        Piece * choisirPiece (void)
        {
            for (unsigned i (0); i < myPieces.size (); ++i)
                cout << i << ' ' << vNom [myPieces [i]->getNom ()]
                     << myPieces [i]->getNom ()
                     << ' ' << myPieces [i]->getCase ()->getLigne ()
                     << ' ' << myPieces [i]->getCase ()->getColonne ()
                     << endl;
            cout << "Quelle piece voulez-vous jouer ?";
            unsigned piece;
            cin >> piece;
            return myPieces [piece];

        } // choisirPiece()

        void move (Case * laCase, Piece * piece)
        {
            piece->getCase()->setPiece (nullptr);
            piece->setCase (laCase);
            laCase->setPiece (piece);

        } // move()

        void jouer (Piece * piece)
        {
            unsigned ligne;
            unsigned colonne;
            do
            {
                cout << "Où voulez-vous jouer "
                     << vNom [piece->getNom ()] << " ? "
                     << "Ligne Colonne ? ";
                cin >> ligne >> colonne;
            } while ((*piece)(myPlateau->getCase (ligne, colonne)));
            move (myPlateau->getCase (ligne, colonne), piece);


        } // jouer()

    }; // Joueur

    class Partie
    {
        Echiquier * myEchiquier;
        vector <Joueur *> myJoueurs;
      public :
        Partie (Joueur * j1, Joueur * j2, Echiquier * echiquier)
               : myEchiquier (echiquier)
        {
            myJoueurs.reserve (2);
            myJoueurs.push_back (j1);
            myJoueurs.push_back (j2);

            bool aJ2 = false;

            /*    */
            while (true)
            {
                Piece * piece = myJoueurs [aJ2]->choisirPiece ();
                myJoueurs [aJ2]->jouer (piece);
                aJ2 = ! aJ2;
                break;
            }
            /*     */
        } // Partie()

    }; // Partie

}// namespace
int main (void)
{
    Echiquier plateau;
    Joueur joueur1 ("Alain", plateau.getPieces (KBlanc), & plateau);
    Joueur joueur2 ("Marc",  plateau.getPieces (KNoir),  & plateau);

    Partie unePartie (& joueur1, & joueur2, & plateau);

    return 12;

} // main()