Vous êtes sur la page 1sur 16

Mini-Projet ABALONE

Rapport écrit
Groupe B4

Laurent FRADIN laurent.fradin@ens2m.org

Arnaud LEUNG-TACK arnaud.leungtack@ens2m.org

Rédigé le 18/06/10

Sommaire

1) Introduction

2) Analyse du problème, cahier des charges


1) Capture des besoins
2) Initialisation du plateau : définition des types plateau, élement_plateau
3) Visionnage des coups joués : définition des types séquence, coup_joué
4) Spécification des sous-programmes principaux

3) Implantation
1) Définition précise des types plateau, element_plateau
2) Définition précise des types sequence, coup_joue
3) Explication détaillée de l’initialisation du plateau
4) Schéma explicatif du sous-programme PointerCase
5) Ecriture en pseudo-langage du sous-programme Deplacement
6) Explications détaillées des sous-programmes permettant de gérer
l’interface console

4) Conclusion

5) Liste de tous les sous-programmes utilisés dans le projet


Abalone
I. Introduction
Le but de ce mini-projet est de créer une interface de jeu
afin que 2 joueurs puissent s’affronter sur Abalone et une fois la
partie la partie terminée, de pouvoir visionner chacun des coups
joués par les 2 joueurs. Une des difficultés consiste à traduire en
langage C++ les différentes cases et le déplacement des boules sur
le plateau. En effet, le plateau d’Abalone a la forme particulière
d’un hexagone et les abscisses des cases sont alors repérées en
diagonale comme sur le schéma ci-contre.

A cela s’ajoutent les différentes règles d’Abalone (Sumito, Pac, mouvement en ligne…) qui
restreignent les choix de déplacement des boules. Le joueur noir commence toujours la partie et la
partie s’arrête dès qu’un joueur a réussi à éjecter 6 boules adverses.

Nous avons choisi la 1ère représentation de programmation conseillée dans le sujet, c’est-à-
dire représenter toutes les cases du plateau sous forme d’une liste chaînée. Ainsi chaque case
comporte 6 pointeurs afin de pouvoir accéder aux cases adjacentes. Les bords du plateau sont
représentés par un pointeur NULL. L’accès au plateau se fait via le pointeur de tête positionné en A1.
Enfin, le joueur pourra déplacer la boule en cliquant sur celle-ci puis sur la position finale de la boule.

II. Analyse du problème, cahier des charges


1) Capture des besoins

Lorsque nous nous sommes engagés sur la représentation de toutes les cases du
plateau, la 1ère question a été de se demander de quels sous-programmes nous aurions
besoin afin de relier toutes les cases du plateau entre elles pour créer un plateau vide. Le
plateau étant de forme hexagonale, il fallait trouver un moyen de rentrer toutes les cases
dans une liste chaînée sans alourdir le programme. Nous avons donc créé les sous
programmes CreerLigneVide, AjouterLignePlateau et CréerPlateauVide décrits dans la partie
Implantation.

Après avoir placé les boules dans l’état initial du jeu, nous nous sommes intéressés
aux différentes conditions de déplacement imposées par les règles du jeu :
 Le joueur doit cliquer sur une boule de sa couleur

 La case d’arrivée doit être adjacente à la case de départ

 Le joueur ne peut déplacer que 3 boules au maximum

 La règle du Sumito impose d’être en supériorité numérique lorsqu’un joueur


pousse les boules adverses

 En cas d’égalité numérique (Pac), le mouvement est impossible

Ces conditions de déplacement ont été écrites via 4 sous-programmes : CaseAdjacente,


PresenceBouleCouleur, NombreMax et Sumito.

Nous avons ensuite implanté ces conditions dans un sous-programme Déplacement


qui modifie le plateau selon le déplacement imposé.

La règle du jeu impose de plus que chaque joueur ne peut effectuer qu’un
mouvement par tour. Les déplacements du joueur noir puis du joueur blanc ont donc été
insérés dans une boucle qui s’arrête lorsque la condition de victoire a été validée. Le sous-
programme CompteurBoulesEjectees permet de savoir le nombre de boules éjectées pour
chacun des joueurs. Il est ensuite utilisé par le sous-programme Victoire qui permet de
terminer la partie lorsque 6 boules d’une même couleur ont été éjectées.

Vient ensuite la possibilité de visionner chaque coup joué de la partie précédente.


Pour cela, nous avons créé un fichier texte « sequence » qui enregistre les coordonnées de
départ et d’arrivée de chaque coup joué. A chaque fin de partie, ce fichier est écrasé par les
nouvelles coordonnées des coups joués. L’utilisateur a alors le choix de visionner la partie via
le menu principal. En appuyant sur une touche du clavier, il peut alors voir le coup joué sur le
plateau, le numéro du tour et les coordonnées correspondant au mouvement.

Pendant la dernière partie de la programmation, nous nous sommes concentrés sur


l’interface et la représentation du plateau. Au départ nous avons utilisé par défaut l’invite de
commande afin d’afficher le plateau. Les coordonnées de départ et d’arrivée devaient alors
être rentrées au clavier afin de pouvoir déplacer une boule. L’utilisation des outils Console et
Coord, fournis dans le dossier « outils utiles à la programmation », nous ont permis plutôt
d’ouvrir une fenêtre console et ainsi de cliquer sur la boule à déplacer. Cependant
l’utilisation de ces outils nous a mis face à de nouveaux problèmes :

 Nécessité d’établir une règle de passage des coordonnées du repère de la console à


celles du plateau.

 Nécessité d’établir de nouveaux sous-programmes afin de ne pas faire planter le


programme lorsqu’un joueur ne clique pas sur une case définie.

Il ne restait plus ensuite qu’à créer des menus et modifier l’apparence de l’interface afin que
celle-ci soit ergonomique.
2) Initialisation du plateau : définition des types plateau, element_plateau

Le type plateau correspond au pointeur qui permet d’accéder à toutes les cases du plateau.

Element_plateau correspond à une case du plateau. Elle est définie par ses coordonnées
(abscisse et ordonnée en chiffre), la présence d’une boule noire, blanche ou non et enfin les
6 cases adjacentes. Pour plus de clarté, nous les avons nommées comme des points
cardinaux.
Nord-Ouest Nord-Est

Ouest Est

Sud-Ouest Sud-Est

3) Visionnage des coups joués : définition des types séquence, coup_joue

Le type sequence correspond au pointeur qui permet d’accéder à tous les coups joués de la
partie précédente.

Le type coup_joue correspond à un coup joué contenu dans la séquence. Il est défini par les
coordonnées de départ et d’arrivée (abscisse et ordonnée en chiffre) et le coup joué suivant.

4) Spécification des sous-programmes principaux

/* Initialisation du plateau */

plateau CreerPointeurVide (void);


//Crée le pointeur de tête

plateau CreerLigneVide (int longueur, int ord);


//Crée une ligne de cases vides

plateau AjouterLignePlateau (plateau P1, plateau P2, int ligne);


//Ajoute une ligne du plateau à une autre ligne

plateau CreerPlateauVide (void);


//Concatène les lignes et relie les pointeurs afin de créer un
plateau de 9 lignes

void PlacerBoules (plateau &P);


//Modifie les valeurs des cases afin de placer les boules blanches et
noires en début de partie

/* Actions de l'utilisateur */

void Deplacement (int Da, int Do, int Aa, int Ao, plateau &P, int
couleuractif, int couleurpassif, int &r);
//Déplace la boule sur le plateau en fonction du déplacement choisi
par l'utilisateur
/* Fin de partie */

int CompteurBoulesEjectees (int couleur,plateau P);


//Compte le nombre de boules éjectées de même couleur

bool Victoire (plateau P);


//Renvoie vrai si 6 boules d'un joueur ont été éjectées, faux sinon

/* Visionnage des coups joués de la partie précédente */

void Visionnage (sequence S,plateau P, int n);


//Permet de visionner tous les coups joués d'une partie précédente

void EnregistrementSequence (sequence S);


//Enregistre les coups joues dans un fichier texte

sequence ChargementSequence ();


//Crée une séquence à partir d'un fichier texte

III. Implantation
1) Définition précise des types plateau, element_plateau

/* Définition du plateau comme une collection de cases (element_plateau)


*/
typedef struct element_plateau* plateau;
typedef struct element_plateau {
int abscisse; //retourne les
coordonnées de la case
int ordonnee;
int valeur; //=0 si pas de
boule;=1 si présence d'une boule noire;=2 si présence d'une boule
blanche
plateau O,NO,NE,E,SE,SO; //pointeurs sur les 6 cases adjacentes
} element_plateau;

2) Définition précise des types sequence, coup_joue

/* Définition de la séquence des coups joués comme une liste chaînée */


typedef struct coup_joue* sequence;
typedef struct coup_joue {
int Da; // abscisse de départ
int Do; // ordonnée de départ
int Aa; // abscisse d'arrivée
int Ao; // ordonnée d'arrivée
sequence suivante;
} coup_joue;
3) Explication détaillée de l’initialisation du plateau

L’initialisation du plateau a été la partie la plus difficile de la programmation car elle fait
intervenir de nombreux pointeurs. Nous allons expliquer ci-dessous le raisonnement effectué
pour créer le plateau avec les boules à l’état initial.

La 1ère étape a été d’imaginer un processus itératif permettant de relier le plus de cases
possibles entre elles grâce aux 6 pointeurs adjacents. Nous avons alors remarqué que chaque
ligne du plateau avait les mêmes caractéristiques mises à part leur longueur qui varie suivant
l’ordonnée. En effet chaque ligne commence par une case dont le pointeur Ouest est NULL et
se termine par une case dont le pointeur Est est NULL. Entre ces 2 cases, toutes les cases
sont reliées par le fait que le pointeur Est correspond au pointeur Ouest de la case adjacente
droite et le pointeur Ouest correspond au pointeur Est de la case adjacente gauche.

Est= Ouest Est= Ouest

Cela à conduit à créer le sous-programme CreerLigneVide :

plateau CreerLigneVide (int longueur, int ord) //longueur=nombre de cases


de la ligne,ord=ordonnee
{ //
plateau P, courant,courant2; // P pointeur de tête
int i;
P=CreerPointeurVide ();
P=new element_plateau;
courant=P;
courant2=P;

Le pointeur courant sert à se déplacer sur la ligne à partir du pointeur P. Le pointeur courant2
va servir à relier les pointeurs Est et Ouest entre eux. On crée ensuite chaque case de la ligne
en définissant leurs coordonnées, leur valeur à 0, et les pointeurs Est, Nord-Est, Nord-Ouest.

for (i=1;i<=longueur;i++) {
(*courant).E=new element_plateau;
(*courant).abscisse=i;
(*courant).ordonnee=ord;
(*courant).valeur=0;
(*courant).NO=new element_plateau;
(*courant).NE=new element_plateau;
(*courant).NO=NULL;
(*courant).NE=NULL;
Les cases des lignes 1 et 9 sont des cas particuliers car elles se trouvent sur le bord du plateau.
On peut donc mettre certains de leurs pointeurs comme renvoyant sur NULL.

if (ord==1) {
(*courant).SO=new element_plateau;
(*courant).SO=NULL;
(*courant).SE=new element_plateau;
(*courant).SE=NULL;
}
if (ord==9) {
(*courant).abscisse=4+i;
(*courant).NO=new element_plateau;
(*courant).NO=NULL;
(*courant).NE=new element_plateau;
(*courant).NE=NULL;
}

On traite ensuite les cases sur le bord du plateau suivant leur ordonnée (inférieure à 5, égale
à 5 puis supérieure à 5). De même, certains de leurs pointeurs renvoient sur NULL.

if (ord<5){
if (i==1) {
(*courant).O=new element_plateau;
(*courant).O=NULL;
(*courant).SO=new element_plateau;
(*courant).SO=NULL;
}
if (i==longueur) {
(*courant).SE=new element_plateau;
(*courant).SE=NULL;
(*courant).E=NULL;
}
}
if (ord==5) {
if (i==1) {
(*courant).O=new element_plateau;
(*courant).O=NULL;
(*courant).SO=new element_plateau;
(*courant).SO=NULL;
(*courant).NO=new element_plateau;
(*courant).NO=NULL;
}
if (i==longueur) {
(*courant).SE=new element_plateau;
(*courant).SE=NULL;
(*courant).E=new element_plateau;
(*courant).E=NULL;
(*courant).NE=new element_plateau;
(*courant).NE=NULL;
}
}
if (ord>5) {
(*courant).abscisse=i+ord-5;
if (i==1) {
(*courant).O=new element_plateau;
(*courant).O=NULL;
(*courant).NO=new element_plateau;
(*courant).NO=NULL;
}
if (i==longueur) {
(*courant).NE=new element_plateau;
(*courant).NE=NULL;
(*courant).E=new element_plateau;
(*courant).E=NULL;
}
}

Il ne reste plus qu’à relier les cases avec les pointeurs Est et Ouest.

courant=(*courant).E;
if (courant!=NULL) {
(*courant).O=courant2;
courant2=(*courant2).E;
}
}
return P;
}

Il faut maintenant relier chaque ligne entre elles. On va alors les concaténer en remarquant
que les pointeurs Nord-Ouest, Nord-Est, Sud-Est, Sud-Ouest s’agencent entre 2 lignes comme le
schéma ci-dessous :

Nord-Ouest=Sud-Est Nord-Est=Sud-Ouest

Ce qui nous amène au sous-programme AjouterLignePlateau :

plateau AjouterLignePlateau(plateau P1, plateau P2,int ligne) //


Explication en détail du sous-programme dans le rapport
{
plateau courant, courant2 , fixe;
courant=P1;
courant2=P2;
fixe=P1;
Le pointeur courant se déplace sur la ligne inférieure tandis que le pointeur courant2 se
déplace sur la ligne supérieure. Les conditions de reliement changent si on relie les lignes de
1 à 5…

if (ligne<=5){
while ((*courant).NO!=NULL) {
courant=(*courant).NO;
}
while((*courant2).E!=NULL) {
(*courant).NO=courant2;
(*courant2).SE=courant;
courant2=(*courant2).E;
(*courant2).SO=courant;
(*courant).NE=courant2;
courant=(*courant).E;
}
}

…ou de 5 à 9 :

else {
while ((*courant).NO!=NULL) {
courant=(*courant).NO;
}
while ((*courant).NE!=NULL) {
courant=(*courant).NE;
}
while((*courant).E!=NULL){
(*courant).NE=courant2;
(*courant2).SO=courant;
courant=(*courant).E;
(*courant2).SE=courant;
(*courant).NO=courant2;
courant2=(*courant2).E;
}
}
return fixe;
}

Nous pouvons alors créer un plateau vide grâce au sous-programme CreerPlateauVide :

plateau CreerPlateauVide(void) // Explication en détail du sous-programme


dans le rapport
{
int k,i,j;
plateau P1, P2;
P1=CreerLigneVide (5,1);
for (j=6;j<=9;j++) {
i=j-4;
P2=CreerLigneVide (j,i);
AjouterLignePlateau(P1, P2,i);
}
for (j=1;j<=4;j++) {
k=9-j;
i=j+5;
P2=CreerLigneVide (k,i);
AjouterLignePlateau(P1, P2,i);
}
return P1;
}
Enfin, pour débuter la partie, il ne reste plus qu’à placer les boules sur le plateau grâce aus
sous-programme PlacerBoules. Ci-dessous un schéma qui résume le mouvement du pointeur pour
placer les boules :

Le plateau est initialisé, il ne reste plus qu’à jouer !

4) Schéma explicatif du sous-programme PointerCase

Afin de placer des pointeurs courant sur des cases précises dans les sous-programmes de
condition et de déplacement, nous avons eu besoin de créer ce sous-programme. Voici
comment le pointeur se déplace à la case désirée :

Il y a 2 cas majeurs :

 La case demandée se trouve dans la


partie rouge (abscisse inférieure ou
égale à 5), le pointeur se déplace
alors à l’Est jusqu’à l’abscisse
correspondante, puis au Nord-Ouest
jusqu’à l’ordonnée correspondante.

 La case demandée se trouve dans la


partie bleu (abscisse supérieure à 5),
le pointeur se vers l’Est jusqu’à
l’abscisse 5, puis se déplace au Nord-
Est jusqu’à l’abscisse correspondante
et enfin se déplace vers le Nord-
Ouest jusqu’à l’ordonnée correspondante.
5) Ecriture en pseudo-langage du sous-programme Deplacement

Ce sous-programme prend en compte toutes les conditions de déplacement avant


d’autoriser un déplacement par une modification de la position des boules sur le plateau.

L’autorisation de déplacement est représentée par l’entrée/sortie r. En effet, dans le


programme principal, r est initialisée à 1. Lorsqu’un mouvement n’est pas autorisé, le sous-
programme Deplacement modifie la valeur de r par r=0, ce qui se traduit par l’affichage de
« mouvement impossible » et l’obligation de rejouer le tour. Lorsqu’un mouvement remplie
toutes les conditions requises pour autoriser un déplacement, la valeur de r reste ou est
modifié à 1 afin de pouvoir passer au tour du joueur adverse.

Entier couleuractif

Plateau P
Entier Da Procédure
Entier Do

Entier Aa Deplacement
Entier Ao
Entier r
Entier couleurpassif

Procédure Deplacement (entier Da,entier Do,entier Aa,entier Ao,plateau P (E/S),entier


couleuractif,entier couleurpassif, entier r (E/S))
Début
| entier abs,ord;
| abs← Da;
| ord←Do;
| plateau courant;
| courant←PointerCase (Da,Do,P);
| si (CaseAdjacente(Da,Do,Aa,Ao,P)=vrai) et
| (PresenceBouleCouleur(Aa,Ao,P,couleurpassif)=faux) et
| (NombreMax(Da,Do,Aa,Ao,P,couleuractif)=vrai) et
| (Sumito(Da,Do,Aa,Ao,P,couleuractif,couleurpassif)=vrai) et
| (courant →valeur=couleuractif) alors
| | tantque (PresenceBouleCouleur(abs,ord,P,couleuractif)=vrai) et
| | (PointeurDirige(Da,Do,Aa,Ao,courant) ≠NULL) faire
| | | DeplacerPointeurDirection (Da,Do,Aa,Ao,courant,abs,ord);
| | fintantque
| | si courant→valeur=0) alors
| | | r←1;
| | | courant→valeur=couleuractif;
| | | courant←PointerCase (Da,Do,P);
| | | courant→valeur=0;
| | finsi
| | si courant→valeur=couleuractif alors
| | | r←0;
| | finsi
| | si courant→valeur=couleurpassif) alors
| | | tantque (courant→valeur=couleurpassif) et
| | | (PointeurDirige(Da,Do,Aa,Ao,courant) ≠NULL) faire
| | | | DeplacerPointeurDirection (Da,Do,Aa,Ao,courant,abs,ord);
| | | fintantque
| | | si courant→valeur=couleuractif alors
| | | | r←0;
| | | finsi
| | | si courant→valeur=0 alors
| | | | r←1;
| | | | courant→valeur=couleurpassif;
| | | | courant←PointerCase (Da,Do,P);
| | | | courant→valeur=0;
| | | | courant←PointeurDirige (Da,Do,Aa,Ao,courant);
| | | | tantque PresenceBouleCouleur
| | | | courant→abscisse,courant→ordonnee ,P,couleuractif)=vrai faire
| | | | | courant←PointeurDirige (Da,Do,Aa,Ao,courant);
| | | | fintantque
| | | | courant→valeur=couleuractif;
| | | finsi
| | | si courant→valeur=couleurpassif alors
| | | | r←1;
| | | | courant←PointerCase (Da,Do,P);
| | | | courant→valeur=0;
| | | | courant←PointeurDirige (Da,Do,Aa,Ao,courant);
| | | | tantque PresenceBouleCouleur
| | | | (courant→abscisse ,courant→ordonnee,P,couleuractif) =vrai faire
| | | | courant←PointeurDirige (Da,Do,Aa,Ao,courant);
| | | | fintantque
| | | | courant→valeur=couleuractif;
| | | finsi
| | finsi
| sinon
| | r←0;
| finsi
fin

6) Explications détaillées des sous-programmes permettant de gérer l’interface console

Une fois les sous-programmes nécessaires au fonctionnement du jeu terminés, il a fallu


s’attaquer à la représentation « graphique » du plateau pour matérialiser le jeu. Le sous-
programme AfficherPlateau permet d’afficher le plateau dans sa forme hexagonale.

void AfficherPlateau (plateau P)


{
int i,j;
plateau nouveau;
j=1;
cout<<endl<<endl<<endl<<endl;
for (i=9;i>=5;i--) {
nouveau=PointerCase(i-4,i,P);
Espace (i+1);
while (nouveau!=NULL) {
AfficherCase (nouveau);
nouveau=(*nouveau).E;
}
cout<<endl;
}

La première partie de ce sous programme dispose les 5 lignes horizontales du haut du plateau. Pour
la première ligne du haut (i=9), on fait déplacer le pointeur sur la première case de cette ligne, de
coordonnées (5,9), à l’écran on affiche 10 espaces, puis on fait déplacer vers l’Est le pointeur en
affichant à l’écran la valeur de chaque case (voir sous-programme AfficherCase) :

- « . » si la case est vide

- « o » de couleur noire si la case comporte une boule noire

- « o » de couleur blanche si la case comporte une boule blanche

Quand le pointeur est arrivé en bout de ligne on revient à la ligne à l’écran.


On procède de cette même manière pour les autres lignes de 8 à 5 mais en réduisant l’espace par
rapport au bord gauche de l’écran pour avoir la forme trapézoïdale.

for (i=4;i>=1;i--) {
nouveau=PointerCase(1,i,P);
Espace (j+6);
j=j+1;
while (nouveau!=NULL) {
AfficherCase (nouveau);
nouveau=(*nouveau).E;
}
cout<<endl;
}
cout<<endl<<endl<<endl;
}

La deuxième partie dispose les 4 lignes horizontales du bas du plateau. On procède de la même façon
que dans la première partie, en partant de la ligne 4 jusqu’à la ligne 1, sauf qu’on augmente l’espace
à chaque ligne pour avoir la forme trapézoïdale. Ce qui nous donne bien à la fin un hexagone de coté
5.

Cependant, un problème surgit : les coordonnées des cases du plateau ne correspondent pas aux
coordonnées de la console. D’où l’obligation de créer un sous-programme ConversionConsole
reliant les coordonnées acquises dans la console à celles du plateau. Le plateau est affiché à l’écran
dans le repère console tel que le schéma ci-dessous le représente :

1 2 3 4 5 6 7
Y
On constate assez facilement que pour les ordonnées, la relation est :

Ordonnée_plateau = 13 – Ordonnée_console

Mais la règle reliant l’abscisse plateau à l’abscisse console est plus implicite. Remarquons que la
rangée d’abscisse 1 du plateau peut être assimilée à une droite affine dans le repère console
d’équation : Y = X + 2, pour la rangée d’abscisse 2 du plateau : Y = X. On constate que toutes les
droites assimilées aux rangées de 1 à 9 sont parallèles, donc par récurrence on établit une loi
générale pour chaque rangée : Y = X + i, avec i variant de 2 à -14 par pas de 2. D’où le sous-
programme ConversionConsole :

int ConversionConsole (int X, int Y)


{
int abs,i,j;
j=1;
for (i=2;i>=-14;i=i-2) {
if (Y==X+i) {
abs=j;
}
j=j+1;
}
return abs;
}

L’abscisse plateau correspond alors à j, où j est égal au numéro de la ligne rouge sur le dessin du
plateau dans le repère console.

Le dernier sous-programme à utiliser est InterieurPlateau :

bool InterieurPlateau (Coord C) {


bool b;
b= false;
if ((C.X>=10)&&(C.X<=18)&&(C.Y>=4)&&(C.Y<=12) || (C.X==6)&&(C.Y==8)
|| (C.X==7)&&(C.Y>=7)&&(C.Y<=9) || (C.X==8)&&(C.Y>=6)&&(C.Y<=10) ||
(C.X==9)&&(C.Y>=5)&&(C.Y<=11) || (C.X==22)&&(C.Y==8) ||
(C.X==21)&&(C.Y>=7)&&(C.Y<=9) || (C.X==20)&&(C.Y>=6)&&(C.Y<=10) ||
(C.X==19)&&(C.Y>=5)&&(C.Y<=11)) {
if ((C.Y%2==0) && (C.X%2==0)) {
b=true;
}
if ((C.Y%2==1) && (C.X%2==1)) {
b=true;
}
}

return b;
}
Ce sous-programme permet d’éviter au programme de planter lorsqu’un joueur clique sur une case
non-définie comme l’extérieur du plateau ou un espace horizontal entre 2 cases. Les conditions
écrites dans la 1ère boucle « if » délimitent la zone intérieure du plateau dans le repère console. De
plus, on remarque dans le dessin du plateau dans le repère console ci-dessus, que les cases du
plateau (symbolisées par un point sur le schéma) ont soit leur abscisse et leur ordonnée paires ou
soit leur abscisse et ordonnée impaires. On définit donc ces 2 autres conditions dans les 2ème et 3ème
boucles « if » grâce à l’utilisation du modulo. Ainsi, si un joueur clique à l’extérieur du plateau ou
dans un espace vide à l’intérieur du plateau, la fonction renvoie faux, ce qui évite au programme
principal de récupérer des coordonnées inconnues et donc de planter.

IV. Conclusion
Au final, la réalisation de ce projet nous a demandé beaucoup de temps mais nous a apporté
en contrepartie une grande dose d’expérience sur l’utilisation du langage de programmation C++.
Notamment l’initialisation du plateau nous a permis de bien cerner la définition des pointeurs et leur
rôle dans les listes chainées. Ce mini-projet nous semble maintenant réellement complémentaire du
cours et des travaux dirigés étudiés à l’école. Nous aurions cependant souhaité commencer plus tôt
la réalisation de ce projet car il nous a manqué du temps pour achever complètement le jeu Abalone.
Il serait bien en effet de rajouter plus tard les mouvements en flèche, dernière règle du jeu d’Abalone.
Au niveau de l’interface, nous aurions aimé aussi pouvoir agrandir la taille des caractères car les
caractères qui représentent les boules sont trop petits et ne facilitent pas le pointage des boules.
Enfin, une extension possible du jeu que l’on aurait aimé souhaiter faire serait la possibilité de
pouvoir jouer en réseau à Abalone, soit en réseau local ou encore via Internet.

V. Liste de tous les sous-programmes utilisés dans le projet


Abalone
Contenus dans Plateau.h :

*Initialisation du plateau *Conditions de déplacement *Actions de l’utilisateur


CreerPointeurVide CaseAdjacente Deplacement
CreerLigneVide PresenceBouleCouleur
AjouterLignePlateau NombreMax
CreerPlateauVide Sumito
PlacerBoules

*Interface *Sous-programme complémentaires


AfficherCase PointerCase
Espace IncrementerCoordDirection
AfficherPlateau PointeurDirige
ConversionConsole
InterieurPlateau
Contenus dans Sequence.h :

SequenceVide
AjouterEnFin
ParcourirSequence
NombreCoupsJoues
ConvertirChiffreLettre
Visionnage
EnregistrementSequence
ChargementSequence

Contenus dans Console.h :

InitialisationConsole
CouleurtexteConsole
DeplaceCurseur
EffaceConsole

Contenus dans Divers.h :

Init_aleatoire
Aleatoire
Attendre
Effacer_ecran