BOOKS i'm reading
 |
/*
* Module ID: chess.h
* Titre : Declaration de classes pour le jeu d'echec
*
* Auteur : Olivier Langlois <olivier@olivierlanglois.net>
* Date : 4 Fevrier 1998
*
*/
#ifndef _CHESS_H_
#define _CHESS_H_
#include "collect/idlist.h"
#include <iostream>
/*
* Definitions
*/
#define NUMROW 8
#define NUMCOL 8
/*
* Declarations partielles
*/
class ChessBoard;
class Column;
class ChessCase;
class GamePiece
{
private:
// Position de la piece.
ChessCase *position;
public:
GamePiece() : dx(NULL), dy(NULL), position(NULL) {}
GamePiece( ChessCase *Case ) : dx(NULL), dy(NULL), position(Case) {}
virtual ~GamePiece() = 0;
/*
* Fonctions Setters
*/
void setPos( ChessCase *pos ) { position = pos; }
/*
* A l'origine, les fonctions visit*() avaient tous le nom visit.
* Tant qu'il n'existe pas de classe derivee qui override aucune de ces
* fonctions cela ne cause aucun probleme puisque le compilateur performe un
* 'name mangling' a partir du nom ET des parametres.
* Cependant, des qu'une classe possede une fonction qui override une des
* fonctions visit*, elle cache les autres.
*/
virtual void visitCase( ChessCase &Case );
virtual void visitCol( Column &col );
virtual void visitBoard( ChessBoard &board );
protected:
/*
* Variables qui definit les deplacements possibles de la piece.
*/
int numMove;
int *dx, *dy;
};
class Knight : public GamePiece
{
public:
Knight() {init();}
Knight( ChessCase *initialPos ) { init(); setPos(initialPos); }
~Knight();
private:
void init(void);
};
class ChessCase : public IsvDlink
{
private:
// Piece presente sur la case.
GamePiece *presentPiece;
protected:
ChessBoard *Board;
/*
* La presence de la position dans cette classe peut sembler redondante
* puisqu'elle doit etre connue pour atteindre la case. Cependant, lorsque
* l'on desire faire interagir la case avec une piece, les objets doivent
* avoir un moyen d'acceder a cette information. Cela aurrait pu etre
* accompli de d'autres facons:
*
* 1 - Passer la position aux fonctions necessitant cette information
*
* 2 - La position aurrait pu etre contenue dans les objets de pieces
* (Mauvaise idee car elle aurrait du etre ajustee a chaque
* deplacement)
*
* En conclusion, la presence de la position dans la classe ChessCase
* semble etre la meilleure solution car elle necessite qu'une seule
* initialisation puisqu'il est tres peu probable que les cases ait a se
* deplacer.
*/
int x, y;
public:
/*
* Les valeurs par defaut de x & y sont choisies loin des coordonnees du
* jeu de sorte que si jamais par erreur une Piece tentait de se deplacer a
* partir d'une case non-initialisee qu'il soit impossible pour n'importe
* quel (dx,dy) que la piece se retrouve sur le Chessboard.
*/
ChessCase() : presentPiece(NULL), x(-256), y(-256) {}
/*
* Ce constructeur a peu de chance d'etre utilise frequemment car il est
* anticipe que les objets seront construit en array la majorite du temps,
* situation ou le constructeur par defaut est appelle.
*/
ChessCase( int new_x, int new_y, GamePiece *piece = NULL )
: x(new_x), y(new_y), presentPiece(piece) {}
virtual ~ChessCase() {}
virtual void init( void ) {}
virtual void print( ostream &os ) {}
// Fonctions Setters
void setBoard( ChessBoard *cb ) { Board = cb; }
void setPiece( GamePiece *piece ) { presentPiece = piece; }
void setPosition( int new_x, int new_y ) { x = new_x; y = new_y; }
// Fonctions Getters
void getPosition( int &xRef, int &yRef ) { xRef = x; yRef = y; }
virtual void accept( GamePiece &piece )
{ piece.visitCase(*this); }
};
/*
* La classe Column permet de creer l'operateur [Column][Row] pour la classe
* ChessBoard.
*/
class Column : public IsvDlink
{
public:
Column();
virtual ~Column() {}
ChessCase &operator[](int i)
{ return *dynamic_cast<ChessCase *>(ChessCases[i]); }
virtual void print( ostream &os, int y = -1 );
virtual void accept( GamePiece &piece )
{ piece.visitCol(*this); }
protected:
friend class ChessBoard;
/*
* ChessCases est alloue dynamiquement, ce qui permet eventuellement de
* remplacer ChessCases par des objets d'une classe derivee de ChessCase.
*/
// ChessCase *ChessCases;
/*
* Une liste a du etre utilisee pour contenir les cases car un pointeur
* de classe ne peut avoir une reference correcte sur une chaine d'objets
* d'une classe derivee.
*/
IDList ChessCases;
/*
* Ce constructeur doit etre utilise par les classes derivee de Column
* qui doivent assigner une des objets d'un classe derivee de ChessCase
* a ChessCases.
*/
Column(int) {}
virtual void initCases( int x, ChessBoard *cb );
};
class ChessBoard
{
public:
/*
* Il est important d'appeler initColumns() apres l'appel du constructeur
* Cela ne peut pas etre fait a l'interieur du constructeur car l'appel
* de fonctions virtuelles a l'interieur de constructeur est deconseille.
*/
ChessBoard();
virtual ~ChessBoard() {}
Column &operator[](int i)
{ return *dynamic_cast<Column *>(columns[i]); }
virtual void initColumns( void );
virtual void print( ostream &os );
/******************************************************************************
*
* Nom : accept
*
* Utilite : Recoit une piece.
*
* Parametres:
* piece (GamePiece &) Piece a deplacer.
*
* Valeur de retour: Aucune.
*
****************************************************************************/
virtual void accept( GamePiece &piece )
{ piece.visitBoard(*this); }
protected:
/*
* columns est alloue dynamiquement, ce qui permet eventuellement de
* remplacer columns par des objets d'une classe derivee de Column.
*/
// Column *columns;
/*
* Une liste a du etre utilisee pour contenir les cases car un pointeur
* de classe ne peut avoir une reference correcte sur une chaine d'objets
* d'une classe derivee.
*/
IDList columns;
/*
* Ce constructeur doit etre utilise par les classes derivee de ChessBoard
* qui doivent assigner des objets d'un classe derivee de Column
* a columns.
*/
ChessBoard(int) {}
};
ostream &operator <<(
ostream &os,
ChessBoard &s
);
ostream &operator <<(
ostream &os,
ChessCase &s
);
#endif /* _CHESS_H_ */
|