rapport écrit abalone

16
Mini-Projet ABALONE Rapport écrit Groupe B4 Laurent FRADIN [email protected] Arnaud LEUNG-TACK [email protected] 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

Upload: laurent-fradin

Post on 26-Jun-2015

261 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Rapport écrit Abalone

Mini-Projet ABALONE Rapport écrit

Groupe B4

Laurent FRADIN [email protected]

Arnaud LEUNG-TACK [email protected]

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

Page 2: Rapport écrit 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 :

Page 3: Rapport écrit Abalone

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.

Page 4: Rapport écrit Abalone

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.

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

Nord-Ouest Nord-Est

Ouest Est

Sud-Ouest Sud-Est

Page 5: Rapport écrit Abalone

/* 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;

Page 6: Rapport écrit Abalone

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.

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;

Est= Ouest Est= Ouest

Page 7: Rapport écrit Abalone

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;

Page 8: Rapport écrit Abalone

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

}

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 :

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;

Page 9: Rapport écrit Abalone

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;

}

Page 10: Rapport écrit Abalone

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.

Page 11: Rapport écrit Abalone

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.

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

Procédure

Deplacement

Entier couleuractif

Plateau P

Entier Da

Entier Do

Entier Aa

Entier Ao

Entier r

Entier couleurpassif

Page 12: Rapport écrit Abalone

| | | | 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.

Page 13: Rapport écrit Abalone

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 :

X

Y 1 2 3 4 5 6 7

9

8

Page 14: Rapport écrit Abalone

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;

}

Page 15: Rapport écrit Abalone

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

Page 16: Rapport écrit Abalone

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