Vous êtes sur la page 1sur 32

Haute École de Bruxelles-Brabant

École Supérieure d’Informatique Mars 2018


Bachelor en Informatique .

. DEV2 – Développement 

Projet
Le jeu Diamant
 

1 Présentation 2

2 Le jeu « Diamant » 8

3 Itération 1 9

4 Itération 2 18

5 Itération 3 28

6 Remise du projet 32

7 Le mot de la fin 32

Échéances
Date Étape
18 mars Publication de l’énoncé
Semaine du 26 mars Remise de l’itération 1
Semaine du 23 avril Remise de l’itération 2
Semaine du 7 mai Remise de l’itération 3

Ce document est distribué sous licence Creative Commons Paternité - Partage à l’Identique 2.0 Belgique
(http://creativecommons.org/licenses/by-sa/2.0/be/).
Les autorisations au-delà du champ de cette licence peuvent être obtenues à esi-bru.be - .
Version du document : 15 mars 2018
1 Présentation

Bienvenue dans le projet de développement en Java. Lisez bien et complètement ce


document. Cette lecture peut vous paraitre longue et vous demandera des efforts,
mais ce travail vous tiendra en haleine durant plusieurs semaines.
Ce document ne contient pas uniquement des données relatives à l’exercice. Il vous
renseigne également sur les modalités de remises et vous donne une progression
itérative dans la résolution du travail.

1.1 Le projet

Ce projet vous permettra de mettre en œuvre la plupart des concepts vus pendant
cette première année : programmation orientée objet, utilisation du langage Java,
tests unitaires et documentation d’une application Java.
Nous allons coder une application permettant de gérer le jeu « Diamant » dont les
règles sont présentées dans un document que vous pourrez trouver sur poÉsi.
Il va se dérouler en 4 phases en suivant un mode de développement itératif. Nous
veillerons à ce que chacune de ces phases soient strictement personnelles.
1. L’itération 1 représente une version jouable du jeu, mais avec très peu de règles
implémentées ;
2. L’itération 2 représente une version jouable avec la plupart des règles implé-
mentées ;
3. L’itération 3 représente une version complète du jeu ;
4. Défense du projet où il vous sera demandé de réaliser une petite modification.

1.2 S’inscrire au projet

L’étape préalable au projet est de vous inscrire auprès de votre professeur


de laboratoire qui va vous créer un projet sur le serveur git de l’école. C’est lui
que vous utiliserez pour développer votre application et pour la remettre à votre
professeur.

1.3 Échéances

Comme indiqué en première page, il y a trois échéances importantes.


Vérifiez avec votre professeur les modalités exactes de remises sous peine de voir
votre travail non corrigé.
. Quelle est la date limite précise 1 ?
. Comment le remettre ? En main propre ou pas, avec une petite démo ou pas. . .
1. On entend par date limite, un moment défini par date et heure, pour lequel le travail doit être
remis au professeur, et au-delà duquel le travail ne sera plus accepté. Mais rien ne vous empêche de
remettre votre travail plus tôt.

DEV2 – Projet – page 2


1.4 Défense

Le jour de la défense une ou plusieurs nouvelles fonctionnalités vous seront deman-


dées. Vous devrez modifier votre projet en conséquence.
Ces modifications seront suivies par une défense orale, soutenue par une présentation
sur machine de votre projet. N’oubliez pas que la défense est effectuée à l’école, sur
une machine quelconque du laboratoire et sur linux1. Vous devez être capable de
compiler, modifier, et exécuter votre code en ligne de commande sur linux1 à l’école,
d’y générer la documentation Java ainsi que d’exécuter les tests.

1.5 Consignes importantes

Les professeurs de java ont décidé de vous enseigner à programmer dans l’environ-
nement de développement intégré (EDI) Netbeans. Ceci devrait être pour la plupart
d’entre vous une grande facilité.
Le corollaire de cette facilité seront des exigences plus importantes. Certaines, notées
par ♣, sont rédhibitoires : si l’exigence n’est pas satisfaite, le code n’est pas relu et
la note est zéro.
Ces exigences sont présentées ci-dessous :
. ♣ le code doit être convenablement indenté (Pressez Shift-Alt-F qui indente
automatiquement le code) ;
. ♣ le code doit compiler (aucune erreur ne doit être présente lors de la compi-
lation) ;
. ♣ la Javadoc doit être complète. Chaque méthode de chaque classe doit posséder
une Javadoc ;
. ♣ toutes les méthodes pour lesquelles des tests sont demandés doivent posséder
des tests unitaires ;
. tout écart par rapport à l’énoncé (ajout d’une méthode non privée, modification
du comportement d’une méthode demandée) devra être validé au préalable par
votre professeur qui jugera de sa pertinence ;
. utilisez les éléments de langage les plus appropriés à ce que vous devez faire :
par exemple, un foreach quand c’est possible ;
. tout le développement est en anglais : le code, la Javadoc ; vous pouvez cepen-
dant écrire la documentation complémentaire dans le code ainsi que l’interaction
avec l’utilisateur en français ;
. les méthodes doivent être courtes sauf cas particuliers rares. Vous écrirez donc
les méthodes complémentaires nécessaires pour satisfaire cette condition ;
. le respect attentif des conventions de codage Java 2 ;
. l’orthographe est une des marques de l’attention que vous attachez à votre
travail. Dans cette mesure, elle peut compter et des points vous seront retirés
s’il y a trop de fautes ;
2. Le document qui les décrit est disponible sur poÉSI.

DEV2 – Projet – page 3


Nous vous invitons aussi à faire des sauvegardes fréquentes avec git, et après chaque
modification significative (et pourvu que le code compile sans erreur). Ceci vous as-
sure une backup local, la possibilité de revenir en arrière facilement et nous permettra
le cas échéant de suivre l’évolution de votre travail.
Remarque : lorsque vous codez, ne vous limitez pas à l’implémentation des mé-
thodes demandées. Vous êtes encouragés à écrire des méthodes privées qui sim-
plifient l’écriture de votre code. Il en va de même pour les méthodes toString(),
equals() et hashCode() qui sont à récrire si vous en ressentez l’utilité.

1.6 Évaluation

L’évaluation du projet portera sur ce que vous avez remis. Pour que vos travaux
soient évalués, il faut que les points marqués ♣ soient satisfaits. S’ils ne le sont pas,
nous ne ferons pas l’effort de lire et commenter vos travaux. Par exemple, il faut que
les tests soient présents, c’est-à-dire que des fichiers de tests unitaires pour toutes
les méthodes pour lesquels des tests sont mentionnés existent. Selon la qualité et
la pertinence de ces tests, vous aurez plus ou moins de points. Mais donc zéro dès
qu’un de ces fichiers n’est pas présent.
Pour rappel, le projet compte pour 24% de la cote finale de l’UE DEV2. Chaque
remise sera prise en compte avec la pondération ci-dessous.
Remise 1 5/20
Remise 2 6/20 (+2/20 pour l’amélioration de la remise 1)
Remise 3 5/20 (+2/20 pour l’amélioration de la remise 2)
Si une partie n’est pas remise, l’étudiant peut continuer son projet mais, bien sûr,
il recevra 0 pour cette partie non remise.
La cote est attribuée au terme de la défense orale, faite à l’école, sur une machine
de laboratoire aléatoire et sur linux1. La défense est obligatoire pour recevoir
une cote de projet.
Les professeurs considèrent que tout doit être fait, fonctionnel, maitrisable complète-
ment par vous sur ces environnements (PC de labos et linux1) à l’école. Manquer
à l’un des 2 est synonyme d’échec.

1.7 À propos de collaboration et triche

Contrairement à ce que beaucoup imaginent, la programmation est le plus souvent un


travail de groupe, mené en collaboration étroite au sein d’une équipe qui compte au
minimum de(s) développeur(s) et de(s) utilisateur(s) mais également des analystes,
des graphistes. . . Vous pouvez demander l’avis de vos camarades de classe pour les
travaux préparatoires, la compréhension du projet, la réflexion sur les algorithmes,
l’utilisation des outils, l’interprétation des messages d’erreurs et des comportements
inattendus.

DEV2 – Projet – page 4


Cependant, dans le contexte scolaire, nous devons aussi mener un travail d’évaluation
qui lui est individuel. Il est donc attendu que les étudiants remettent un projet
individuel. Nous ne pouvons pas tolérer de codes copiés. Tout plagiat de code
donnera lieu à l’annulation du projet des 2 étudiants concernés. Ne copiez
donc pas le code d’un autre et ne laissez personne vous copier.
Vous veillerez à la sécurité de votre code source. Ceci comprend la sécurité d’accès
aux ordinateurs sur lesquels est stocké votre projet, la non divulgation de votre mot
de passe. . .

1.8 Méthodologie de développement

Dans cette section, nous discutons brièvement de méthodologies de développement.


La première est liée au cycle de développement qui est dit itératif et la seconde est
le développement dirigé par les tests. Le cycle de développement itératif va vous
imposer de remanier une partie de votre code source. Finalement, nous parlerons de
ce qu’est le refactoring et quelle aide peut apporter NETBEANS 3 .

1.8.1 Cycle de développement itératif

Il existe différents types de cycles de développement entrant dans la réalisation d’un


logiciel. Ces cycles prendront en compte toutes les étapes de la conception d’un
logiciel.
Le cycle itératif est le suivant :
. identification du besoin (quoi) ;
. élaboration (comment) ;
. développement ;
. transition (livraison au client, en l’occurrence votre professeur).
En pratique, nous vous demanderons trois itérations qui représentent chacune une
version du jeu Diamant avec un ensemble de règles plus ou moins complet. Pour
chacune de ces itérations, l’identification du besoin et l’élaboration a été faite par
vos professeurs. Vous êtes en charge du développement et de la présentation à votre
professeur.
3. voir :
. https://fr.wikipedia.org/wiki/Réusinage_de_code ;
. https://fr.wikipedia.org/wiki/Test_driven_development ;
. https://fr.wikipedia.org/wiki/Cycle_de_développement_(logiciel)

DEV2 – Projet – page 5


Veillez donc à :
. tester en utilisant la librairie JUNIT ;
. documenter via une JAVADOC complète pour chacune de vos méthodes et
pour chacune de vos classes ;
. commiter (et pusher) régulièrement votre projet et accompagner ce commit
d’un message explicite sur le travail réalisé.

Pour la première itération, les tests vous sont offerts. Prenez exemple sur ceux-ci,
afin de choisir méthodologiquement le nom de vos méthodes de tests de manière à
retrouver la méthode testée ainsi que la description du cas :
test<NomMéthode><descriptionDuCas>()
Exemple pour une méthode isFree(Coordinates position) qui retourne true si
la position donnée en paramètre est libre, sinon false.
 
1 @Test
2 public void testIsFreeWhenPosIsFree() {
3 ...
4 assertTrue(instance . isFree (position ));
5 }
 

1.8.2 Développement dirigé par les tests

Le test-driven development (TDD) ou en français développement piloté par les tests


est une technique de développement de logiciel qui préconise d’écrire les tests uni-
taires avant d’écrire le code source d’un logiciel.
Les étapes suivantes doivent être respectées :
1. écriture d’un premier test,
2. vérifier qu’il échoue (car le code qu’il teste n’est pas implémenté),
3. écrire le code suffisant pour faire passer le test,
4. vérifier qu’il passe ;
5. améliorer le code.
Par amélioration du code, on entend :
. vérifier le respect des conventions,
. améliorer l’aspect du logiciel,
. optimiser le code...

1.8.3 Refactoring avec NETBEANS

Le refactoring de code est l’opération consistant à retravailler le code source d’un


programme informatique ; sans toutefois y ajouter des fonctionnalités ni en corriger
les bugs ; de façon à en améliorer la lisibilité et par voie de conséquence la mainte-
nance.

DEV2 – Projet – page 6


Dans notre cas, le refactoring sera principalement dû aux modifications induites des
itérations. Il s’agira de :
. modification de la présentation ;
. renommage ;
. relocalisation du code...

Astuce Netbeans
Lorsque vous voulez renommer une variable avec Netbeans :

. placer votre curseur sur la variable ;


. entrer [Ctrl]r ou Clic droit / Refactor / Rename et le nom de la
variable s’encadre en rouge ;
. renommer et ce renommage prendra effet partout.

Lorsque vous voulez renommer une méthode, c’est le même principe


excepté qu’une fenêtre de dialogue s’ouvre.

DEV2 – Projet – page 7


2 Le jeu « Diamant »

Le projet consiste à implémenter le jeu « Diamant » dont vous trouverez les règles
sur poÉsi via le document Diamant.pdf 4 .

2.1 Architecture de l’application

Le patron de conception (design pattern) Modèle-Vue-Contrôleur (MVC) est une


manière de structurer le code adaptée pour la programmation d’applications avec
interaction utilisateur. On y distingue la partie métier (modèle et contrôleur) de la
partie de présentation (vue) de l’application. Le patron modèle-vue-contrôleur (en
abrégé MVC, de l’anglais model-view-controller) est un modèle destiné à répondre
aux besoins des applications interactives en séparant les problématiques liées aux
différents composants au sein de leur architecture respective (voir Wikipedia 5 ).
Ce paradigme regroupe les fonctions nécessaires en trois catégories :
. un modèle (modèle de données) ;
. une vue (interface utilisateur : présentation et interaction avec l’utilisateur) ;
. un contrôleur (logique de contrôle, gestion des événements, synchronisation).

La partie modèle (model) contiendra pour nous les classes qui définissent les
éléments ainsi que la logique principale de l’application. Ces classes seront regroupées
dans un package spécifique : g12345.diamond.model 6 .

La partie vue (view) concerne les classes qui s’occupent de la présentation et de


l’interaction avec l’utilisateur. Elles seront également regroupées dans leur propre
package : g12345.diamond.view.

La partie dynamique du jeu (controller) sera contenue dans le package :


g12345.diamond.controller.
Pour finir, la classe principale chargée de lancer le jeu sera contenue dans le
package g12345.diamond.

4. La version originale de ce document est accessible via https://www.iello.fr/regles/


DIAMANT_regles.pdf
5. http://fr.wikipedia.org/wiki/Modèle-vue-contrôleur
6. Durant ce travail, g12345 représente (évidemment) votre matricule.

DEV2 – Projet – page 8


3 Itération 1

Nous voici à la première itération de notre projet. Cette itération a pour objectif de
fournir une version très simplifiée du jeu Diamant (V0.1). Cette itération permettra :

. l’inscription des joueurs ;


. la découverte de tuiles trésors avec partage lors de l’aller ;
. les départs uniquement sur décision du joueur ;
. une grotte à une seule entrée ;
. une fin de jeu lorsque tous les explorateurs ont quitté la grotte ;
. pas de désignation d’un gagnant.

À la différence du règlement complet, il n’y aura pas de tuile danger et de tuile


relique. De plus, les tuiles trésors seront générées aléatoirement avec un nombre de
rubis compris entre 1 et 15 (bornes comprises).

3.1 Le modèle
Explorer

- pseudonym Cave
- bag : Bag enum
- state : State State
- lastDiscoveredTreasure : Treasure
+ Explorer(pseudonym : String) LEAVING
EXPLORING + Cave()
+ getPseudonym() : String
+ getLastDiscoveredTreasure() : Treasure
+ takeDecisionToLeave()
+ discoverNewTreasure(explorers : Explorer[*])
+ addToBag(nbRubies : Int)
+ getBag() : Bag
+ getState() : State
0

*
1

Treasure
Bag
- nbRubies : Int
- nbRubies : Int
∼ Treasure(rubies : Int)
+ Bag()
+ Treasure()
+ addRubies(nbRubies : Int)
+ getInitNbRubies() + getRubies() : Int
+ getNbRubies() : Int
+ explore(explorers : Explorer[*]) : Int

3.1.1 L’énumération State

Un explorateur sera toujours dans une des situations suivantes :


. en cours d’exploration ;
. sur le chemin de retour au camp suite à une décision volontaire.
Implémentez l’énumération State permettant de représenter ces deux états à l’aide
des valeurs : EXPLORING et LEAVING.
Pensez à documenter votre code et à faire un commit après chaque étape !

DEV2 – Projet – page 9


Astuce Netbeans
Pour créer une énumération avec Netbeans :

. clic droit sur le package et glisser la souris sur new ;


. si « Java Enum » apparait, cliquer dessus et se laisser guider ;

. sinon, cliquer sur « Other » et choisir dans le menu « Java Enum


» et se laisser guider.

3.1.2 La classe Bag

Dans le jeu, les gemmes ramassées dans une grotte sont posées à côté du coffre du
joueur en attendant d’être définitivement gagnées. Ici, nous les placerons dans un
sac représenté par la classe Bag. Cette classe sera donc utilisée pour représenter
l’ensemble des rubis récoltés par les joueurs au cours de l’exploration d’une entrée

DEV2 – Projet – page 10


de la grotte.

Attributs
. private int nbRubies : représente les rubis contenus dans le sac.

Constructeur
. Bag() : lorsqu’il est créé, un sac ne contient aucun rubis.

Méthodes
. addRubies(int nbRubies) : permet d’ajouter plusieurs rubis dans le sac ;
. int getNbRubies() : retourne le nombre de rubis contenus dans le sac.

3.1.3 La classe Explorer

Cette classe va permettre de représenter nos explorateurs. Chacun d’eux sera diffé-
rencié grâce à son pseudonyme.

Attributs
. pseudonym : pseudonyme du joueur ;
. bag : sac du joueur ;
. state : sert à identifier l’état de l’explorateur.

Constructeur Celui-ci prendra en paramètre le pseudonyme du joueur et initia-


lisera les autres attributs. Par défaut, un explorateur est en cours d’exploration.

Méthodes
. Un getter pour chacun des attributs de la classe 7 ;
. addToBag(nbRubies: int) : permet d’ajouter un nombre donné de rubis dans
le sac du joueur ;
. takeDecisionToLeave() : permet d’indiquer que l’explorateur décide de quit-
ter la grotte. Elle change son statut en conséquence.
7. Pour rappel, un clic-droit/Insert Code... vous permettra de générer facilement les méthodes
les plus courantes ;)

DEV2 – Projet – page 11


Astuce Netbeans
Netbeans a un raccourci incontournable ; [Alt][Insert]. Également ac-
cessible par un clic droit — c’est un menu contextuel — dans le block de
la classe. Ce menu propose l’ajout — en fonction du contexte — d’un
constructeur, de getters et setters. . .

Pour peu qu’un attribut existe, ce menu contextuel peut ajouter un


constructeur en un clic et les getter et setter en un autre clic.

Imaginons maintenant qu’aucun attribut n’existe et que l’on veuille


ajouter un attribut, son getter, son setter. Ce menu contextuel propose
Add property. . .. Dès lors que le curseur est dans le block de la classe :

. [Alt][Insert] et choisir Add property. . . ;


. dans la fenêtre qui s’ouvre, indiquer
. le nom de la propriété ;
. son type ;
. ce qu’il faut générer (par défaut, Netbeans génèrera ; getter,
setter) ;
. fixer la visibilité de l’attribut (par défaut, private)
. cliquer sur OK et tout est là.

DEV2 – Projet – page 12


Astuce Netbeans
Java recommande un ordre bien précis pour les éléments d’une classe :
les attributs puis les constructeurs et, enfin, les méthodes. L’outil d’in-
sertion de code de Netbeans aboutit régulièrement à un code qui ne
respecte pas ces règles. Si on active la bonne option, Netbeans peut
vous indiquer si l’ordre n’est pas respecté et réordonner les éléments
pour vous. Pour cela,

. choisissez le menu Tools/Options ;


. cliquez sur Editor et choisissez l’onglet Hints ;
. dans la section Class Structure, cochez l’option Organize Members.

Une fois, cette option cochée, Netbeans affichera une petite ampoule
devant le premier élément mal placé et vous proposera de réorganiser
toute la classe.

DEV2 – Projet – page 13


Rappel : N’oubliez pas de faire passer les tests, de documenter votre code et de
faire des commits/pushs réguliers de votre code source.

3.1.4 Le classe Treasure

Les tuiles trésors (Treasure) ont la particularité de contenir des rubis à partager
équitablement entre les explorateurs qui explorent la salle.

Attributs
. private int rubies : représente le nombre de rubis présents sur la tuile.
. private final int initNbRubies : représente le nombre de rubis présents
lors de sa création.

Constructeur
. Treasure(int rubies) : initialisation des attributs de la classe avec un nombre
de rubis donné.
. Treasure() : Initialisation des attributs de la classe avec un nombre compris
entre 1 et 15 généré aléatoirement.

Méthodes
. Ajoutez un accesseur pour chacun des deux attributs.
. explore(List<Explorer> explorers) : lors de l’exploration d’une tuile tré-
sor, les rubis trouvés par les explorateurs sont partagés entre ceux-ci de manière
équitable. Les rubis non distribués sont laissés sur place.

3.1.5 La classe Cave

La classe Cave, permet de gérer une entrée de la grotte.

Attribut
. Treasure lastDiscoveredTreasure : dernière tuile trésor découverte.

Constructeurs
. Cave() : vide.

Méthodes
. Un accesseur pour l’attribut lastDiscoveredTreasure ;
. discoverNewTreasure(List<Explorer> explorers) : fait découvrir aux ex-
plorateurs passés en paramètre une nouvelle salle aux trésors. Les richesses
disposées sur celle-ci sont partagées équitablement.
Allez ! On vous le rappelle encore une fois : vous devez faire des commits réguliers.

DEV2 – Projet – page 14


3.1.6 La classe game

La classe Game est la classe qui assemble tous les éléments du jeu déjà codés. Elle
agit comme une façade 8 c’est-à-dire que c’est uniquement avec cette classe que la
vue va interagir pour faire évoluer le jeu, sans appeler directement les autres classes
du modèle.

Interface L’interface 9 Model définit les méthodes que doit fournir la façade Game.
Elle agit comme une sorte de contrat. Le voici :
 
1 public interface Model {
2 void addExplorer(Explorer explorer);
3 void moveForward();
4 boolean isOver();
5 Cave getCave();
6 List<Explorer> getExplorers();
7 List<Explorer> getExploringExplorers();
8 void handleExplorerDecisionToLeave(Explorer explorer);
9 }
 

Ce code est présent sur poÉsi (vous devrez adapter le nom du package). Nous vous
invitons à lire la javadoc fournie pour comprendre ce que doivent faire les méthodes.
Celles de la forme get... sont là pour permettre à la vue d’interroger l’état du jeu
afin de donner des informations pertinentes à l’utilisateur. Les autres font évoluer le
jeu.

Déclaration Lors de la déclaration de la classe, il est impératif d’indiquer que


celle-ci implémente l’interface Model

Attributs La classe Game() contient au moins les deux attributs suivants :


. List<Explorer> explorers : la liste des explorateurs.
. Cave cave : la grotte du jeu.

Constructeurs
. Game() : Ce constructeur permet de créer le jeu et d’instancier les attributs.
Au début du jeu, il n’y a pas encore d’explorateurs ; ils devront s’inscrire par
la suite.

Méthodes. Vous devez coder toutes les méthodes imposées par l’interface. Faites
bien attention à ce que vos méthodes vérifient et imposent le respect des règles.

8. https://en.wikipedia.org/wiki/Facade_pattern
9. Au sens Java, pas en tant qu’interface utilisateur

DEV2 – Projet – page 15


Astuce Netbeans
Netbeans permet d’écrire rapidement
MyObject mo = new MyObject ( ) ;

Il suffit d’utiliser le raccourci newo. Taper newo suivi de [Tab] et se


laisser guider c’est-à-dire entrer le nom de l’objet dans le rectangle rouge
et, ensuite, entrer la touche [Enter].

Il existe beaucoup d’autres raccourcis que nous vous invitons à décou-


vrir.

3.2 La vue

Remarque. Vous allez à présent coder la vue, le contrôleur et la méthode princi-


pale. Il peut être opportun de les développer en parallèle afin de pouvoir exécuter
rapidement votre jeu et d’y ajouter les étapes les unes après les autres.
La vue doit permettre d’interagir avec l’utilisateur. Elle doit contenir les éléments
suivants :

Attribut
. Scanner in : permet d’obtenir les informations des utilisateurs.
. Model game : instance du jeu à afficher avec lequel l’utilisateur va interagir.

Constructeurs
. View(Model game) : permet d’initialiser les attributs de la classe.

Méthodes
. Explorer askExplorer() : instancie un explorateur sur base d’un pseudonyme
demandé à l’utilisateur.
. boolean isThereNewExplorerToAdd() : permet de demander à l’utilisateur
s’il y a encore un explorateur à ajouter.
. boolean askExplorerChoiceToContinue(Explorer explorer) : permet de
demander, pour chaque explorateur, s’il désire ou non continuer l’exploration.
. void displayGame() : permet d’afficher l’état du jeu. Ceci comprend la der-
nière tuile trésor explorée ainsi que chacun des explorateurs.
. displayEnd() : permet d’afficher à l’utilisateur que le jeu est terminé et d’af-
ficher les explorateurs.

DEV2 – Projet – page 16


3.3 Le contrôleur

C’est dans le contrôleur que la dynamique du jeu doit être écrite.

Attribut
. Model game : l’instance du jeu à piloter
. View view : la vue du jeu.

Constructeur
. Controller(Model game, View view)

Méthodes
. void startGame() : permet de démarrer une partie du jeu.
1. Les explorateurs doivent être ajoutés dans le jeu ;
2. tant que le jeu n’est pas terminé , une nouvelle salle aux trésors est explorée
et les explorateurs présents peuvent décider de rester ou partir ;
3. une fois terminé, la fin du jeu est affichée.

3.4 La méthode principale

La méthode principale doit créer le modèle, la vue et le contrôleur en les liant


ensemble et doit démarrer le jeu.

3.5 V0.1

Félicitations, vous avez développé une version allégée du jeu « Diamant ». Vérifiez
les points suivants :
. Tous les tests passent avec succès ?
. Votre jeu tourne convenablement ?
. Votre code est documenté et lisible ?
Si tous ces points sont vérifiés, vous pouvez envoyer votre projet à votre professeur
pour qu’il puisse faire un retour dans les meilleurs délais.

Astuce Netbeans
[Alt][Shift]F permet de mettre correctement le code en forme.

Si des lignes sont sélectionnées, c’est le bloc qui est reformaté sinon,
c’est toute la classe. Plus d’excuse d’avoir un code mal indenté.

DEV2 – Projet – page 17


4 Itération 2

Maintenant que la première partie est fonctionnelle, nous pouvons ajouter les fonc-
tionnalités une à une. À chaque fois que l’une de ces fonctionnalités est ajoutée, nous
marquerons l’avancée du projet par un tag correspondant à une nouvelle version.
. V0.1.1 - Amélioration de la gestion des erreurs ;
. V0.1.2 - 3 à 8 joueurs ;
. V0.1.3 - Désignation du vainqueur ;
. V 0.1.4 - Gestion du retour des explorateurs ;
. V 0.1.5 - Ajout des 5 entrées dans la grotte ;
. V 0.1.6 - Gestion du paquet de tuiles ;
. V 0.1.7 - Ajout des tuiles danger ;
. V 0.2 - Fuite des explorateurs.
Prêtez toujours une attention particulière à la robustesse de votre code. Veillez à
documenter et à tester (tests unitaires) vos méthodes et classes.

4.1 V0.1.1 - Amélioration de la gestion des erreurs

Cette modification a pour but d’améliorer la gestion des exceptions présente et futur.
Nous vous demandons d’ajouter la classe GameException. Cette classe hérite de la
classe RuntimeException.
Dans la classe Model, il est indiqué qu’une exception de type RuntimeException doit
être lancée par la méthode handleExplorerDecisionToLeave si l’appel se fait avec
un explorateur qui ne fait pas partie de l’instance Game courante. Modifiez cela et
indiquez que l’exception lancée doit être de type GameException. Modifiez la classe
Game en conséquence afin de respecter votre interface.

Astuce Netbeans
Netbeans permet de générer très rapidement une exception — une
classe héritant de Exception — et réécrivant deux constructeurs. Pour
ce faire,

. clic droit sur le package et glisser la souris sur new ;


. cliquer sur « Java Exception » et se laisser guider ;

DEV2 – Projet – page 18


Rappel : n’oubliez pas de tester, documenter et faire des commits/pushs réguliers
de votre code source.

4.2 V0.1.2 - 3 à 8 joueurs

Nous allons maintenant limiter le nombre de joueurs afin de respecter les règles du
jeu. Dans celles-ci, le nombre de joueurs doit être compris entre 3 et 8 joueurs.

4.2.1 Modification de la classe Model

Dans la classe Model, ajoutez les trois méthodes suivantes :


. start() - cette méthode ne doit rien faire en particulier pour démarrer une
partie. Elle va vérifier que le nombre d’explorateurs inscrits respecte les règles.
Si le nombre de joueur n’est pas correct, une exception de type GameException
doit être lancée.
. isThereEnoughExplorer() - retourne vrai s’il y a au moins 3 explorateurs.
. isItPossibleToAddExplorer() - retourne vrai s’il est possible d’ajouter un
nouvel explorateur dans la partie.
Toujours dans la classe Model, modifiez la méthode addExplorer() de manière à ce
qu’une exception de type GameException soit lancée s’il n’est plus possible d’ajouter
un nouvel explorateur.
Modifiez la classe Game afin de respecter les modifications que vous avez faites dans
la classe qu’elle implémente.

4.2.2 Modification de la dynamique de jeu

Dans le contrôleur, utilisez les nouveaux éléments disponibles afin de démarrer une
partie avec le bon nombre d’explorateurs. Réfléchissez afin d’éviter de faire des de-

DEV2 – Projet – page 19


mandes inutiles à l’utilisateur.
Rappel : n’oubliez pas de tester, documenter et faire des commits/pushs réguliers
de votre code source.

4.3 V0.1.3 - Désignation du vainqueur

Dans cette section, nous détaillons les modifications nécessaires afin de permettre
la désignation d’un vainqueur. L’explorateur qui gagne une partie est celui ayant
récolté le plus de rubis.

4.3.1 Modification du modèle

Dans la classe Explorer, ajoutez la méthode int getFortune(). Cette méthode


retourne le nombre de rubis contenus dans le sac de l’explorateur.
Dans la classe Model, ajoutez la méthode Explorer getWinner(). Cette méthode
retourne l’explorateur qui possède la plus grosse fortune. Si cette méthode est appelée
avant la fin de la partie, une exception GameException doit être lancée.
Modifiez la classe Game en conséquence.

4.3.2 Modification de la vue

Renommer la méthode displayEnd() en displayWinner() 10 . Changez également


l’implémentation pour afficher le vainqueur plutôt que d’afficher le statut de tout le
monde.
Rappel : n’oubliez pas de tester, documenter et faire des commits/pushs réguliers
de votre code source.

Astuce Netbeans
Parfois il manque des import, parfois il y en a trop parce que l’on utilise
une classe à un moment et, plus tard, on décide de ne plus l’utiliser.
Netbeans peut vérifier la liste des import, ajouter les manquants et sup-
primer les inutiles.
[Ctrl][Shift]I ou Source / Fix import dans le menu.

10. Voir section 1.8.3. Pensez au clic-droit/Refactor/Rename... pour le faire simplement en mini-
misant le risque d’erreur.

DEV2 – Projet – page 20


4.4 V 0.1.4 - Gestion du retour des explorateurs

Cette nouvelle version va ajouter la gestion du retour des explorateurs. En effet,


jusqu’à maintenant, les explorateurs se partagaient le butin lorsqu’ils découvraient
les salles trésors, mais pas lors qu’ils retournaient au camp.
La première chose à faire est de mémoriser les tuiles découvertes sur le chemin.
La seconde est de les faire parcourir lorsqu’un ou plusieurs explorateurs quittent la
grotte.

Attention, le partage des tuiles est ici simplifié par rapport aux règles du jeu. Les
rubis non partagés restent sur la tuile où ils sont apparus.

4.4.1 Modification du modèle

Dans la classe Cave :


. Ajoutez un attribut de class List<Treasure> path et son accesseur. Cet at-
tribut doit être initialisé dans le constructeur et adapté lorsqu’on découvre une
nouvelle salle.
. Ajoutez une méthode returnToCamp(List<Explorer> explorers). Cette mé-
thode permet à tous les explorateurs passés en paramètre d’explorer le chemin
lors de leur retour au camp.

DEV2 – Projet – page 21


Nous devons maintenant différencier les explorateurs qui quittent et ceux qui ont
déjà quitté la grotte. Cette différenciation va permettre d’éviter de leur faire explorer
deux fois la grotte lors de leur retour. Dans l’énumération State, ajoutez le statut
CAMPING. Dans la classe Explorer, ajoutez la méthode reachCamp(). Cette méthode
modifie le statut de l’explorer de LEAVING à CAMPING.
Dans la classe Model, ajoutez la méthode makeExplorersLeave(). Cette méthode
permet à tous les explorateurs le souhaitant 11 de quitter la grotte. Modifiez la classe
Game en conséquence.

4.4.2 Modification de la vue

Dans la vue, ajoutez la méthode turnResumeDisplay(). Cette méthode demande à


la vue d’afficher le chemin de tuiles découvert par les explorateurs ainsi que le statut
des explorateurs qui sont en cours d’exploration.

4.4.3 Modification de la dynamique

Dans l’algorithme de votre contrôleur, après avoir demandé aux explorateurs s’ils
souhaitent quitter, appelez la méthode makeExplorerLeave().

4.4.4 Modification pour compléter les tests

Dans le but de faire des tests unitaires plus complets, ajoutez à la classe Cave,
la méthode addTreasureToPath(Treasure treasure) ; celle-ci ne sera pas appelée
par une classe en dehors des classes de tests. Dès lors, sa visibilité peut être package.
Rappel :
. N’oubliez pas de tester, documenter et faire des commits/pushs réguliers de
votre code source.
. N’oubliez pas d’amender les méthodes toString(), equals() lorsque cela est né-
cessaire.

4.5 V 0.1.5 - Ajout des 5 entrées dans la grotte

Dans les règles du jeu, la grotte est constituée de 5 entrées. Ce que nous considérions
jusqu’à maintenant comme une grotte n’est en réalité qu’une seule de ses entrées.
Pour la suite, nous parlons de phase d’exploration ou encore de phase de jeu. Une
phase d’exploration représente la période dans le jeu qui démarre dès qu’une entrée
est ouverte et qui se termine lorsque l’entrée est condamnée. Nous parlons également
de tour. Un tour représente la découverte d’une nouvelle salle aux trésors, de son
partage, et de la prise en considération du choix des joueurs de continuer ou de
stopper l’exploration.
11. Ceux dans l’état LEAVING.

DEV2 – Projet – page 22


4.5.1 Modification du modèle (Cave et CaveEntrance)

La première chose à faire est de renommer la classe Cave en CaveEntrance 12 pour


correspondre davantage à ce que la classe permet de représenter. Nous allons ensuite
ajouter une nouvelle classe Cave pour représenter la grotte et ses 5 entrées.
Dans la classe CaveEntrance, ajoutez un attribut lockedOut de type booléen. Cet
attribut permet de déterminer si une entrée est condamnée. Ajoutez son accesseur
ainsi que la méthode lockOut() qui permet de déclarer l’entrée condamnée.
Définissez la classe Cave de la manière suivante :

Attributs
. private int nbExploredEntrance : représente le nombre d’entrées explorées.
Une entrée est explorée lorsqu’elle est condamnée (locked).
. private CaveEntrance currentEntrance : représente la dernière entrée ou-
verte. Nous ne retiendrons que celle là !

Constructeur
. Cave() : initialise l’attribut nbExploredEntrance à 0.

Méthodes
. ajoutez les accesseurs des attributs nbExploredEntrance et currentEntrance.
. boolean hasNewEntranceToExplore() : retourne vrai si moins de 5 entrées
ont été explorées ;
. openNewEntrance() : permet d’ouvrir une nouvelle entrée de la grotte. Une
exception est lancée si la précédente phase de jeu n’est pas terminée 13 . Une
exception sera aussi lancée s’il y a une tentative d’ouvrir plus de 5 entrées ;
. lockOutCurrentEntrance() : permet de condamner l’entrée courante de la
grotte et d’incrémenter le nombre de grottes explorées. Une exception est lancée
si une phase de jeu n’est pas en cours ;

Attention, suite au refactoring, certaines classes ont été modifiées alors qu’elles
ne le devaient pas.
. Dans Model, la méthode CaveEntrance getCave() doit être renommée en Cave
getCave().
. Dans Game, l’attribut de type CaveEntrance doit être de type Cave ce qui
implique quelques adaptations :
12. Ne le faites pas à la main ; utilisez l’outil de refactorisation de Netbeans
(clic-droit/Refactor/Rename...).
13. C’est-à-dire, s’il y a une entrée qui a été ouverte précédemment et que celle-ci n’a pas été
condamnée.

DEV2 – Projet – page 23


. Dans la méthode moveForward, demandez à l’instance de la grotte, quelle
est l’entrée courante pour la découverte d’une nouvelle tuile trésor.
. Dans makeExplorerLeave(), une modification similaire doit être faite.

4.5.2 Modification du modèle (suite)

Entre chaque phase d’exploration, l’explorateur sera au camp. Modifiez le construc-


teur de la classe Explorer pour que ceux-ci aient le bon statut lors de leur instan-
ciation. Ajoutez également une méthode startExploration() qui va permettre à
un explorateur de démarrer l’exploration.
Dans la classe Model, ajoutez les méthodes suivantes :
. startNewExplorationPhase() : cette méthode ouvre une nouvelle entrée et les
explorateurs rentrent en mode exploration.
. endExplorationPhase() : cette méthode met fin à la phase d’exploration. L’en-
trée courante est condamnée.
Modifiez la classe Game en conséquence.
Avec les modifications faites, l’implémentation de la méthode isOver() ne permet
plus d’identifier une fin de partie, mais plutôt la fin d’une phase. Refactorez la
méthode afin de la renommer en isExplorationPhaseOver().
Il reste essentiel de déterminer la fin de partie, nous allons donc ajouter la méthode
isOver() qui va retourner vrai si la partie n’est pas en phase d’exploration et s’il
n’y a plus d’entrée à explorer.

4.5.3 Modification de la dynamique

Modifiez le contrôleur de manière à considérer la gestion des phases. Remarquez que


la gestion des phases et tours constitue un algorithme de rupture.
Cette modification est conséquente et il est facile d’avoir fait une erreur. Vérifiez que
vos tests unitaires passent toujours. Il est important de signaler que ceux-ci ont été
impactés par les modifications détaillées dans cette section.

4.6 V 0.1.6 - Gestion du paquet de tuiles

Cette itération vise à respecter la règle des 15 tuiles trésors par l’utilisation d’un
paquet de tuiles trésors. Ce paquet de tuiles doit permettre de :
. générer les 15 tuiles trésors ;
. piocher une tuile trésor ;
. réinitialiser les tuiles.

DEV2 – Projet – page 24


4.6.1 Modification du modèle

Nous allons créer la classe Deck afin de représenter notre paquet de tuiles.

Attributs
. List<Treasure> tiles : représentera la liste des tuiles trésors.

Constructeur
. Deck() : permet d’initialiser la liste des tuiles trésors. Intialement, le paquet
contient 15 tuiles trésors de valeur : {1, 2, 3, 4, 5, 5, 7, 7, 9, 11, 11, 13, 14, 15, 17}.

Méthodes
. getTreasure() : permet de retourner une carte au hasard parmi la liste de
tuiles.
. putBack(Treasure treasure) : permet de replacer une carte dans le paquet.
Dans la classe Treasure, ajoutez une méthode restore() qui réinitialise la valeur
du trésor à sa valeur initiale.
Dans la classe Cave, ajoutez un attribut Deck ainsi que son accesseur.
Dans la classe CaveEntrance nous avons besoin d’utiliser le paquet de tuiles de
la grotte. Ajoutez un attribut de classe Cave cave qui permet à toute entrée de
connaitre la grotte à laquelle elle est associée et ainsi, avoir accès au paquet de la dite
grotte. Initialisez cet attribut dans le constructeur. Modifiez l’implémentation de la
méthode discoverNewTile. Celle-ci ne crée plus une carte aux trésors aléatoirement,
mais la pioche dans le paquet de la grotte. Ajoutez également un accesseur pour le
chemin.
Dans la classe Game, modifiez endExlorationPhase() pour replacer les tuiles de
type Treasure après les avoir restaurées.
Rappel : n’oubliez pas de tester, documenter et faire des commits/pushs réguliers
de votre code source.

4.7 V 0.1.7 - Ajout des tuiles danger

Cette itération vise à ajouter les tuiles de type danger. Pour l’instant, nous allons
simplifier les règles et remettre les tuiles dans le paquet à chaque fin de phase.

4.7.1 Modification du modèle

Commençons par définir les différents types par la création d’une énumération
HazardType avec les valeurs : STONE_BALL, GIANT_SPIDERS, SNAKES, BATTERING_RAM
et LAVA_FIELD.
Créez l’interface Tile

DEV2 – Projet – page 25


 
1 public interface Tile {
2 void explore(List<Explorer> explorers);
3 }
 

Modifiez la classe Treasure pour indiquer qu’elle implémente l’interface Tile. Spé-
cifiez que la méthode explore de Treasure est une implémentation de celle de l’in-
terface par l’ajout d’un @Override.
Créez une classe Hazard afin de représenter une salle danger. Elle implémente aussi
l’interface Tile.

Attributs
. HazarType type : le type de danger de la tuile.

Méthodes
. L’accesseur de type.
. explore() : cette méthode ne fait rien.
Il est maintenant temps de modifier l’ensemble du code pour ne plus directement
interagir avec des tuiles Treasure.
. Deck : la liste de Treasure devient une liste de Tile. Renommez getTreasure()
en getTile().
. CaveEntrance : l’attribut Path est composé de Tile. Renommez
. lastDiscoveredTreasure() en lastDiscoveredTile() ;
. discoverNewTreasure en discoverNewTile ;
. addTreasureToPath en addTileToPath ;
. getLastDiscoverTreasure en getLastDiscoveredTile.
. Game : dans endExplorationPhase, getPath() retourne une collection de Tile.
Ajoutez une condition pour restaurer la tuile s’il s’agit d’une instance Treasure.
Maintenant que cette modification est faite, nous allons ajouter les tuiles dangers
dans le jeu. Modifiez la classe Deck de manière à ajouter les tuiles de type Hazard.
Pour rappel, 3 occurrences de chaque type de danger doivent être présentes dans le
paquet de tuiles.
Rappel : n’oubliez pas de tester, documenter et faire des commits/pushs réguliers
de votre code source.

4.8 V 0.2 - Fuite des explorateurs

Nous allons maintenant provoquer la fuite des explorateurs lorsque deux tuiles d’un
même danger auront été découvertes par ceux-ci lors d’une phase d’exploration.

DEV2 – Projet – page 26


4.8.1 Modification du modèle

Dans CaveEntrance,
. ajoutez l’attribut boolean unsafe qui indique si le chemin est toujours sécurisé
ou non.
. modifiez la méthode discoverNewTile(). Quand un danger est pioché, elle
doit vérifier qu’il n’a pas déjà été pioché dans cette entrée de grotte auquel cas
l’entrée est déclarée non sure (unsafe ← true).
Dans Cave,
. ajoutez la méthode isLastEntranceUnsafe() qui retourne vrai si la dernière
entrée est déclarée dangereuse.
Il faut maintenant permettre la fuite des explorateurs. Lors de sa fuite, un explora-
teur perd le contenu de son sac.
. Dans la classe Bag, ajoutez une méthode loseContent() qui va vider le contenu
du sac.
. Dans la classe Explorer, ajoutez la méthode runAway(). Elle vide le sac et lui
fait atteindre le camp.
Dans la classe Game,
. modifiez la méthode moveForward(). Si la grotte est déclarée unsafe après avoir
découvert une nouvelle tuile, les explorateurs en cours d’exploration doivent
prendre la fuite.
. Ajoutez une méthode isExplorationPhaseAborted() qui retourne vrai si l’en-
trée de la grotte en cours d’exploration est déclarée unsafe, faux sinon.

4.8.2 Modification de la vue

Ajoutez une méthode displayRunAway() qui permet d’avertir les utilisateurs que
l’exploration est terminée.

4.8.3 Modification de la dynamique

Modifiez le contrôleur pour appeler la nouvelle méthode de la vue si la phase d’ex-


ploration est interrompue.
Félicitations, vous êtes arrivé à la fin de la deuxième itération. N’oubliez pas que
cette étape est importante puisque celle-ci doit être rendue à votre professeur. Nous
espérons que vous avez apporté une couverture de tests suffisante pour prémunir
d’un maximum de bug.

DEV2 – Projet – page 27


5 Itération 3

Nous allons maintenant entamer la dernière itération du projet. Il nous reste à


implémenter certaines règles ainsi qu’à ajouter une vue qui n’utilise aucune méthode
toString().

. V0.2.1 - Gestion conforme des tuiles danger ;


. V0.2.2 - Gestion des reliques partie 1 ;
. V0.2.3 - Gestion des reliques partie 2 ;
. V0.2.4 - Gestion des reliques partie 3 ;
. V0.2.5 - Partage conforme sur le retour ;
. V0.2.6 - Gestion du coffre ;
. V1 - Gestion de la vue.

5.1 V0.2.1 - Gestion conforme des tuiles danger

Dans les règles du jeu, lorsqu’un danger provoque la fuite des explorateurs, il n’est
pas remis dans le paquet de tuiles à la fin de la phase d’exploration. Nous allons
modifier notre code en vue d’implémenter cette règle.

5.1.1 Modification du modèle

Dans la classe Hazard, ajoutez un attribut booléen exlorersEscapeReason avec


son accesseur. Cet attribut permet d’identifier les tuiles qui provoquent la fuite des
explorateurs. Ajoutez également la méthode escape() qui attribue la valeur true à
cet attribut.
Dans CaveEntrance, lorsqu’une entrée est déclarée non sure, il est nécessaire de
taguer la tuile qui vient d’être découverte comme tuile ayant provoqué la fuite des
explorateurs. Dans la méthode discoverNewTile(), veillez à appelez la méthode
escape() de la classe Hazard.
Dans la méthode endExplorationPhase() de la classe Game, ajoutez une condition
pour ne pas ajouter les tuiles dangers qui sont responsables de la fuite des explora-
teurs.

Attention, dans la classe Deck, lors de la création des tuiles dangers, veillez à ce
que chaque tuile soit une instance distincte des autres.

5.1.2 Modification pour les tests

Ajoutez un accesseur à l’attribut tileList dans la classe Deck. Cette méthode ne


servira que pour les tests et peut donc avoir la visibilité « package ».

DEV2 – Projet – page 28


5.2 V0.2.2 - Gestion des reliques partie 1

Dans cette section, nous allons commencer le développement visant à ajouter les
tuiles reliques. Nous allons nous contenter ici de rendre notre programme plus orienté
objet en ajoutant une énumération pour les types de gemmes présents dans le jeu.

5.2.1 Modification du modèle

Ajoutez l’énumération Gem qui contient les deux éléments DIAMOND et RUBY.

Attribut
. final int value : valeur de la gemme. Le diamant a pour valeur 5 et le rubis
a pour valeur 1.

Méthodes
. L’accesseur de l’attribut.
Dans la classe Bag, remplacez l’attribut nbRubies par l’attribut List<Gem> gems
et ajoutez son accesseur. Modifiez le constructeur de sorte à initialiser ce nouvel
attribut. Modifiez addRubies(int nbRubies) en addGem(Gem gem). Remplacez la
méthode getNbRubies() par la méthode int getValue() qui calcule la valeur to-
tale des gemmes contenues dans le sac. Finalement, modifiez également la méthode
loseContent() afin de vider la liste de gemmes.
Dans la classe Explorer, modifiez la méthode addToBag(int nbRubies) en addTo-
Bag(Gem gem). La gemme passée en paramètre doit être placée dans le sac de l’ex-
plorateur. La méthode getFortune() doit être modifiée pour utiliser la méthode
getValue de Bag.
Dans la classe Treasure, renommer la variable initNbRubies en initNbGems. Rem-
placez l’attribut rubies par l’attribut List<Gem> gems. Modifiez le constructeur
pour qu’il y ait initNbGems rubis dans gems. Ajoutez un accesseur pour gems et sup-
primez celui de rubies. Modifiez également les méthodes restore() et explore(...).

5.3 V0.2.3 - Gestion des reliques partie 2

Dans cette section, nous allons ajouter la gestion des reliques. Chaque relique aura
la même valeur, nous ferons évoluer la valeur des reliques, telle que définie dans les
règles, dans la section suivante.

5.3.1 Modification du modèle

Ajoutez la classe Relic qui implémente l’interface Tile.

DEV2 – Projet – page 29


Méthodes
. boolean canBeTaken(List<Explorer> explorers) qui retourne vrai si la liste
contient un seul explorateur et que celui-ci quitte la grotte, faux sinon.
. Implémentez la méthode de l’interface qu’elle implémente.
Dans la classe Deck, ajoutez 5 tuiles reliques lors de l’initialisation du paquet.
Dans la classe CaveEntrance, la relique doit être enlevée du chemin lorsqu’un ex-
plorateur part seul de la grotte. Modifiez la méthode returnToCamp() à cet effet.
Dans tous les cas, une relique n’est jamais remise dans le paquet de tuiles.

5.4 V0.2.4 - Gestion des reliques partie 3

Dans cette dernière section réservée à l’ajout de la gestion des reliques, nous allons
faire en sorte qu’à partir de la quatrième relique sortant de la grotte, la valeur des
reliques soit de 2 diamants.
Nous allons ajouter un compteur dans la classe Cave afin de connaitre le nombre
de tuiles reliques enlevées par les explorateurs. Ensuite, nous allons ajouter une
méthode dans la classe Relic afin de permettre la modification de sa valeur.

5.4.1 Modification du modèle

Dans la classe Cave, ajoutez l’attribut nbTakenRelics. Veillez à bien l’initiali-


ser dans le constructeur. Ajoutez également son accesseur ainsi que la méthode
incrementNbTakenRelics() qui va incrémenter de 1 le nombre de reliques enle-
vées.
Dans la classe Relic, ajoutez l’attribut valueInDiamonds qui représente la valeur
de la relique en nombre de diamants. Initialement, cette valeur est 1. Ajoutez une
méthode convertGemValue(int nbTakenRelics) qui porte la valeur de la relique
à 2 si nbTakenRelics ≥ 3. Vérifiez que la méthode Explore(...) donne le bon
nombre de diamants à l’explorateur.
Enfin, dans la classe CaveEntrance, convertissez la valeur de la relique avant que
l’explorateur la prenne, suivant le nombre de reliques déjà prises.

5.5 V0.2.5 - Partage conforme sur le retour

Dans les règles du jeu, une fois le partage des rubis d’une salle aux trésors réalisé, le
reste est disposé sur une unique tuile afin de partager l’ensemble du reste des rubis
comme un tout.
Dans notre implémentation, nous allons déposer le reste des rubis sur la première
carte trésor découverte lors de la phase de jeu courante. Pour ce faire, il est nécessaire
de pouvoir déplacer les rubis d’une tuile trésor à une autre.

DEV2 – Projet – page 30


5.5.1 Modification du modèle

Dans la classe Treasure, ajoutez une méthode transferGemsFrom(Treasure o).


Cette méthode déplace les rubis de l’instance o vers la tuile courante.
Dans la classe CaveEntrance, ajoutez les attributs suivants.

Attributs
. boolean treasureFound : permet de savoir si une carte trésor a déjà été dé-
couverte sur le chemin.
. Treasure firstTreasureTile : est la première tuile trésor découverte sur le
chemin.
Dans le constructeur, initialisez l’attribut treasureFound à faux.
Modifiez la méthode discoverNewTile(), pour modifier les nouveaux attributs
lorsque cela est nécessaire.
Ajoutez la méthode makeLastTileExplored(). Si la dernière tuile du chemin est de
type Treasure, les rubis doivent être déplacés vers la première tuile trésor.
Dans la classe Game, modifiez la méthode makeExplorersLeave() afin d’appeler la
méthode makeLastTileExplored() de CaveEntrance avant tout autre chose.

5.6 V0.2.6 - Gestion du coffre

Nous avons jusqu’à maintenant omis le développement d’un élément important des
règles du jeu. Une fois cet ajout réalisé, nous aurons implémenté toutes les règles du
jeu.

5.6.1 Modification du modèle

Dans la classe Bag(), modifiez la visibilité de l’attribut gems pour qu’il soit accessible
dans une classe qui hérite de la classe Bag.
Créez une classe Chest() qui hérite de la classe Bag. Faites en sorte que le construc-
teur de la classe mère soit appelée dans celui de la classe fille et ajoutez la méthode
saveBag(Bag bag) qui fait le transfert des gemmes contenues dans le sac vers le
coffre.
Dans la classe Explorer, ajoutez un attribut Chest chest qui doit être instancié
dans le constructeur. Pour finir, ajoutez dans la méthode reachCamp() le transfert
des gemmes du sac vers le coffre.

5.7 V1 - Gestion de la vue

Modifiez votre vue. Dorénavant, celle-ci ne peut plus comporter d’appel à une mé-
thode toString().

DEV2 – Projet – page 31


6 Remise du projet

La première phase est terminée. Il est temps de nous remettre une version complète
de votre projet. Nous vous conseillons de faire l’expérience de le cloner sur une autre
machine que celle que vous avez utilisée pour développer afin de vous assurer qu’il
est bien complet.
La phase suivante est la défense ; nous vous demanderons de pouvoir expliquer votre
code et d’être en mesure d’y apporter des modifications.

7 Le mot de la fin

Félicitations d’être arrivé au bout de ce projet. Nous espérons que vous vous êtes
bien amusé et que vous avez appris avec intérêt et motivation.

Vos professeurs de java.

DEV2 – Projet – page 32

Vous aimerez peut-être aussi