neku
Codeur roumain
Voila, un ami devait pour son cours de prog faire un puissance 4 alors les conditions suivantes :
- Utilisation des structures
- Utilisation des classes
- Utilisation de l'héritage des classes
je lui ai donc fait ce petit jeu puissance 4 en C++
Cette source est n'effectue pas le test sur les diagonales (il faut bien qu'il bosse un peu
) mais c'est facilement faisable 
Voila j'espère que ce sera utile à quelqu'un d'autre 
- Utilisation des structures
- Utilisation des classes
- Utilisation de l'héritage des classes
je lui ai donc fait ce petit jeu puissance 4 en C++
Cette source est n'effectue pas le test sur les diagonales (il faut bien qu'il bosse un peu
Code:
#include <iostream>
#include <string>
#include <ctype.h>
using namespace std;
#if defined(_MAC_) || defined(_LINUX_)
//Idem clrscr() Borland
#define clrscr() printf("\033[1;1H"); printf("\033[2J"); printf("\n");
#elif defined(_BORLAND_)
#include <conio.h>
#elif defined(_VISUAL_STUDIO_)
#include <cstdlib>
#define clrscr() system("cls");
#else
#error Ce logiciel ne peut etre compile avec ce compilateur
#endif
#define PRINT(String) cout << String;
#define PRINTCR(String) cout << String << endl;
#define READ(Var) cin >> Var;
#define BOARD_HEIGHT 10
#define BOARD_WIDTH 10
#define EMPTY_TOKEN " "
#define SEPARATOR "|"
#define TOKEN Token->Player->ID
//Retourne FALSE si la chaine n'est pas une chaine contenant que des chiffres
bool IsStringDigit(const string & String) {
bool IsDigit = false;
for (unsigned int Index = 0; Index < (unsigned int)String.size(); Index++) {
IsDigit |= (isdigit(String.c_str()[Index]) == 0);
}
return !IsDigit;
}
typedef struct Player_t {
unsigned int ID;
string Name;
unsigned int Color;
};
typedef struct Token_Position_t {
unsigned int X;
unsigned int Y;
};
typedef struct Token_t {
unsigned int ID;
Player_t* Player;
Token_Position_t Position;
};
class GameBoard {
public:
GameBoard();
~GameBoard();
void InitBoard(void);
void ResetToken(Token_t* Token);
bool SetToken(Token_t* Token);
const Token_t* GetToken(unsigned int ID);
const Token_t* GetToken(const Token_Position_t* Token_Position);
protected:
const Token_t* GetFreeToken(void);
private:
Token_t* Board;
};
GameBoard::GameBoard() {
//Lors de l'instanciation de la classe on aloue l'espace requis pour le plateur de jeu
this->Board = new Token_t[BOARD_HEIGHT * BOARD_WIDTH];
}
GameBoard::~GameBoard() {
//Lors de la destruction on libère l'espace utilisé
delete []this->Board;
}
const Token_t* GameBoard::GetToken(const Token_Position_t* Token_Position) {
for (unsigned int Index = 0; Index < (BOARD_WIDTH * BOARD_HEIGHT); Index++) {
if ((this->Board[Index].Position.X == Token_Position->X) && (this->Board[Index].Position.Y == Token_Position->Y))
return &this->Board[Index];
}
return NULL;
}
const Token_t* GameBoard::GetToken(unsigned int ID) {
if (ID < (BOARD_WIDTH * BOARD_HEIGHT))
return &this->Board[ID];
return NULL;
}
bool GameBoard::SetToken(Token_t* Token) {
if (Token->ID < (BOARD_WIDTH * BOARD_HEIGHT)) {
this->Board[Token->ID] = *Token;
return true;
}
else {
return false;
}
}
const Token_t* GameBoard::GetFreeToken(void) {
for (unsigned int Index = 0; Index < (unsigned int)(BOARD_WIDTH * BOARD_HEIGHT); Index++) {
if (this->Board[Index].Position.X == BOARD_WIDTH && this->Board[Index].Position.Y == BOARD_WIDTH)
return &this->Board[Index];
}
return NULL;
}
void GameBoard::InitBoard(void) {
Token_t* Empty_Token = new Token_t;
this->ResetToken(Empty_Token);
for (unsigned int Index = 0; Index < (unsigned int)(BOARD_HEIGHT * BOARD_WIDTH); Index++) {
Empty_Token->ID = Index;
//this->Board[Index] = *Empty_Token;
this->SetToken(Empty_Token);
}
delete Empty_Token;
}
void GameBoard::ResetToken(Token_t* Token) {
Token->Player = NULL;
//On sort les jeton en dehors du plateau de jeu
Token->Position.X = BOARD_WIDTH;
Token->Position.Y = BOARD_HEIGHT;
}
class Puissance4 : GameBoard {
public:
Puissance4();
~Puissance4();
void NewGame(unsigned int nPlayers);
void EndGame(void);
bool IsGameRunning(void);
void Redraw(void);
void Draw();
bool IsWinner(const Token_t* Token);
const Token_t* PlayerAction(const Player_t* Player);
const Player_t* GetPlayerInfos(unsigned int nPlayer);
protected:
unsigned int GetY(unsigned int X);
void SetPlayersInfos(void);
unsigned int nPlayers;
Player_t* Players;
bool InGame;
};
Puissance4::Puissance4(void) {
this->nPlayers = 0;
this->InGame = false;
}
Puissance4::~Puissance4(void) {
}
void Puissance4::NewGame(unsigned int nPlayers) {
this->InitBoard();
//On reserve l'espace mémoire nécessaire au stockage des données joueur
this->nPlayers = nPlayers;
this->Players = new Player_t[nPlayers];
this->SetPlayersInfos();
this->InGame = true;
}
void Puissance4::EndGame(void) {
//On libère l'espace utilisé par les données joueurs
if (this->Players)
delete []this->Players;
}
void Puissance4::SetPlayersInfos(void) {
for (unsigned int Index = 0; Index < this->nPlayers; Index++) {
this->Players[Index].ID = (Index + 1);
PRINT("Entrez le nom du joueur " << (Index + 1) << " : ");
READ(this->Players[Index].Name);
}
}
const Player_t* Puissance4::GetPlayerInfos(unsigned int nPlayer) {
return (const Player_t*)&this->Players[nPlayer];
}
bool Puissance4::IsGameRunning(void) {
return this->InGame;
}
void Puissance4::Redraw(void) {
//On nettoie l'écran
clrscr();
PRINTCR(" 0 1 2 3 4 5 6 7 8 9 ");
PRINTCR("---------------------");
for (int Y = (BOARD_HEIGHT - 1); Y >= 0; Y--) {
PRINT("|")
for (unsigned int X = 0; X < BOARD_WIDTH; X++) {
bool Found = false;
for (unsigned int Index = 0; Index < (unsigned int)(BOARD_WIDTH * BOARD_HEIGHT); Index++) {
const Token_t* Token = this->GetToken(Index);
if (Token->Player) {
if ((Token->Position.X == X) && (Token->Position.Y == Y)) {
PRINT(TOKEN << SEPARATOR);
Found = true;
break;
}
}
}
if (!Found) PRINT(EMPTY_TOKEN << SEPARATOR);
}
cout << endl;
}
}
//La partie n'a pas connu de vainqueur :/
void Puissance4::Draw() {
this->InGame = false;
PRINTCR("La partie n'a pas connue de vanqueur !");
}
unsigned int Puissance4::GetY(unsigned int X) {
unsigned int nextY = 0;
//On recherche la prochaine place en Y d'une colonne libre
for (unsigned int Index = 0; Index < (unsigned int)(BOARD_WIDTH * BOARD_HEIGHT); Index++) {
const Token_t* Token = this->GetToken(Index);
//Si il s'agit d'un jeton joueur et que le X correspond à celui demandé
if (Token->Player && Token->Position.X == X) {
//Si la position du jeton trouvé + 1 est plus grand que le prochain Y deja trouvé ou 0
if ((Token->Position.Y + 1) > nextY)
nextY = Token->Position.Y + 1;
}
}
return nextY;
}
const Token_t* Puissance4::PlayerAction(const Player_t* Player) {
string Colonne;
const Token_t* Token = this->GetFreeToken();
if (!Token)
return NULL;
Token_t* Temp_Token = new Token_t;
Temp_Token->ID = Token->ID;
do {
do {
PRINT(Player->Name << ", Entrez la colonne ou placer votre jeton (0 - " << (BOARD_WIDTH - 1) << ")");
READ(Colonne);
Temp_Token->Position.X = atoi(Colonne.c_str());
} while ((Temp_Token->Position.X > (BOARD_WIDTH - 1)) || !IsStringDigit(Colonne));
//On recherche si il reste une place dans la colonne
Temp_Token->Position.Y = this->GetY(Temp_Token->Position.X);
} while (Temp_Token->Position.Y > (BOARD_HEIGHT - 1));
Temp_Token->Player = (Player_t*)Player;
this->SetToken(Temp_Token);
delete Temp_Token;
return (const Token_t*)Token;
}
//On est pas fou ... on ne test pas tout les jetons ^^
//On test uniquement le jeton qui vient d'être posé en chercher si d'autre du même joueur sont voisins ou pas ...
bool Puissance4::IsWinner(const Token_t* Token) {
//Faire ici les test sur les token pour savoir si le joueur en a alligné 4 ...
unsigned int H_Aligned = 0;
unsigned int V_Aligned = 0;
unsigned int D1_Aligned = 0;
unsigned int D2_Aligned = 0;
Token_Position_t* Temp_Token_Position = new Token_Position_t;
//Gauche
Temp_Token_Position->Y = Token->Position.Y;
for (int X = Token->Position.X - 1; (X >= 0) && (X >= ((int)Token->Position.X - 3)); X--) {
Temp_Token_Position->X = X;
const Token_t* GToken = this->GetToken((const Token_Position_t*)Temp_Token_Position);
//Si il y a un jeton ...
if (GToken) {
//Si le jeton appartient au même joueur et est différent de celui de départ
if ((GToken->Player == Token->Player) && (GToken->ID != Token->ID))
H_Aligned++;
//Sinon on arrête la boucle car il n'y a plus de contact avec une autre jeton
else
break;
}
//Sinon on arrête la boucle car il n'y a plus de contact avec un autre jeton
else
break;
}
//Droite
for (int X = (int)Token->Position.X + 1; (X <= (BOARD_WIDTH - 1)) && (X <= ((int)Token->Position.X + 3)); X++) {
Temp_Token_Position->X = X;
const Token_t* GToken = this->GetToken((const Token_Position_t*)Temp_Token_Position);
if (GToken) {
if ((GToken->Player == Token->Player) && (GToken->ID != Token->ID))
H_Aligned++;
else
break;
}
else
break;
}
//Bas
Temp_Token_Position->X = Token->Position.X;
for (int Y = (int)Token->Position.Y - 1; (Y >= 0) && (Y >= ((int)Token->Position.Y - 3)); Y--) {
Temp_Token_Position->Y = Y;
const Token_t* GToken = this->GetToken((const Token_Position_t*)Temp_Token_Position);
if (GToken) {
if ((GToken->Player == Token->Player) && (GToken->ID != Token->ID))
V_Aligned++;
else
break;
}
else
break;
}
//Haut
for (int Y = (int)Token->Position.Y + 1; (Y <= (BOARD_HEIGHT - 1)) && (Y <= ((int)Token->Position.Y + 3)); Y++) {
Temp_Token_Position->Y = Y;
const Token_t* GToken = this->GetToken((const Token_Position_t*)Temp_Token_Position);
if (GToken) {
if ((GToken->Player == Token->Player) && (GToken->ID != Token->ID))
V_Aligned++;
else
break;
}
else
break;
}
//TODO : les 4 diagonales ;)
delete Temp_Token_Position;
if (H_Aligned >= 3 || V_Aligned >= 3 || D1_Aligned >= 3 || D2_Aligned >= 3) {
this->InGame = false;
return true;
}
return false;
}
int main (int argc, char const* argv[]) {
Puissance4* Game = new Puissance4;
unsigned int nPlayers = 2;
Game->NewGame(nPlayers);
//On actualise le plateau de jeu
Game->Redraw();
while (Game->IsGameRunning()) {
for (unsigned int Index = 0; (Index < nPlayers) && Game->IsGameRunning(); Index++) {
//On demande au joueur d'entrer le numéro de colonne dans laquelle il désire placer son Token
const Token_t* Token = Game->PlayerAction(Game->GetPlayerInfos(Index));
Game->Redraw();
//Si la fonction n'a pas retourné de Token valide cela signifie qu'il n'y a plus de place sur le plateau
//Et donc la partie n'a pas connue de vanqueur !!!
if (!Token) {
Game->Draw();
}
else {
if (Game->IsWinner(Token))
PRINTCR("Bravo " << Token->Player->Name << ", Tu as gagne la partie !");
}
}
}
Game->EndGame();
delete Game;
return 0;
}