Forum des exercices du projet Zuul

Exercice 7.18.5

  
 
Avatar anonfirstname2 anonlastname2
Exercice 7.18.5
par anonfirstname2 anonlastname2, samedi 6 mars 2021, 21:09
 

Cet exercice est considéré OPTIONNEL tant que vous n'arrivez pas à l'exercice 7.46. Pour l'instant, passez à l'exercice suivant.

Les objets Room du jeu ne sont accessibles que dans createRooms.
Pour y avoir accès depuis n'importe quelle méthode ou classe (notamment au 7.46), créer un tableau (ou une ArrayList ou une HashMap *) contenant toutes les Room (numérotées ou associées à leur nom). Il suffira alors de le (ou la) passer en paramètre, en cas de besoin (notamment au 7.46).

Réfléchissez à l'endroit où vous allez créer ce tableau/liste/hashmap * : vous devrez lui ajouter toutes vos pièces, encore faut-il y avoir accès ...

* Pour le choix entre les trois, lisez les échanges sur le forum ci-dessous.

Avatar Nicolas BARTHELEMY
Re: Exercice 7.18.5
par Nicolas BARTHELEMY, dimanche 27 novembre 2016, 19:34
 

Bonjour,

Je ne vois pas dans quelle classe créer la HashMap ?

Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, dimanche 27 novembre 2016, 19:34
 

Cela ne peut être que là où vous avez accès aux Rooms créées, en l'occurence là où vous les avez créées.

Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, lundi 13 mars 2017, 22:47
 

Un étudiant a écrit :

Bonjour,

J'ai un problème concernant la fonction HashMap
En effet, j'ai voulu créer une HashMap liant à chaque nom de room (tel que "entrance") la room qui lui correpondait.
Pour cela, j'ai crée la Hashmap de cette façon : 

          private HashMap<String, Room> aRoom;

ainsi qu'un tableau de Room de cette façon : 

          private Room[] aAllRooms = new Room[14]; // j'ai 14 rooms

J'ai rangé mes rooms dans ce dernier dans la procédure createRooms, puis j'ai configuré leurs sorties. Jusque là je n'avais pas de problème

Cependant, le problème arrive lorsque j'essaye d'initialiser la map. En effet, lorsque j'associe un String à une Room de cette façon : 

          aRoom.put("entrance", aAllRooms[0]);

le programme compile bien, mais lorsque je lance le jeu, il s'arrête tous de suite en me renvoyant à la ligne ci-dessus avec comme message d'erreur
"java.lang.NullPointerException: null"
Cependant je ne vois pas ce qui est vide (null) : le tableau aAllRooms[] est plein car je m'en suis servi pour configurer les Exits, et je suis en train de remplir aRoom qui a été initialisé.

Cherchant à contourner le problème, j'ai trouvé sur Internet (oui je sais ...) un guide qui rajoutais "naturellement", dans la déclaration de sa HashMap, "= new HashMap();", ce qui donnait pour moi :

          private HashMap<String, Room> aRoom = new HashMap();

Ce qui a réglé mon problème, ou presque, car au moment de la compilation j'ai eu droit au message d'alerte suivant : 

"Warnings from last compilation
D:\******\Documents\ESIEE\A3P\Catchim\Game.java uses unchecked or unsafe operations.
Recompile with -Xlint unchecked for details."

Après avoir cliqué Ok, je peux créer mon jeu, qui marche.

Que dois-je faire ? Y a-t-il une autre solution ? Sinon, comment régler cette erreur ? 

Merci d'avance !

Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, lundi 13 mars 2017, 23:12
 

1) "J'ai un problème concernant la fonction HashMap"
HashMap n'est pas une fonction, mais une classe.

2) "Pour cela, j'ai crée la Hashmap de cette façon ... ainsi qu'un tableau de Room de cette façon ..."
Pourquoi créer les deux ? Comme dit dans l'énoncé, vous pouvez employer l'une ou l'autre de ces 2 solutions.

3) private HashMap<String,Room> aRoom; :
Très mauvais nom pour une variable qui va désigner plusieurs objets !  aRooms serait déjà mieux ...

4) L'instruction aRoom.put("entrance", aAllRooms[0]); provoque une NullPointerException.
    "Cependant je ne vois pas ce qui est vide (null)"
Comme expliqué dans le cours et dans l'atelier de débogage, la première chose qui peut valoir null ici, c'est aRoom !
C'est pour cela que vous n'avez pas le droit d'appeler la méthode put.
Il faut donc initialiser aRoom (comme n'importe quel attribut) en créant l'objet HashMap que vous n'avez pas créé, mais pour lequel vous avez simplement déclaré (et non initialisé) une référence.

5) "Cherchant à contourner le problème, j'ai trouvé sur Internet (oui je sais ...) un guide qui rajoutais "naturellement", dans la déclaration de sa HashMap, "= new HashMap();""
Effectivement, il vaut mieux appliquer les solutions expliquées en cours que n'importe quoi trouvé sur internet.
Que voulez-vous dire par "naturellement" ? Nous n'avons JAMAIS initialisé un attribut lors de sa déclaration et nous avons toujours expliqué que l'initialisation d'un attribut se passait dans le constructeur.
Dans le cas présent, vu que le constructeur délègue la majeure partie de son travail à la procédure createRooms, cela nous fait une 2ème place possible pour l'initialisation de aRoom.

6) "Warnings from last compilation ... uses unchecked or unsafe operations."
C'est parce que vous créez une HashMap sans préciser le type des clés et le type des valeurs entre < et >.

Avatar Andrea PANCRAZI
Re: Exercice 7.18.5
par Andrea PANCRAZI, dimanche 8 octobre 2017, 15:39
 

Bonjour Monsieur Bureau,

Afin d'anticiper les futures modifications du projet j'aurais aimé savoir quelle solution entre le tableau et la HashMap semble convenir le mieux selon vous bien que vous nous informiez qu'on peut utiliser les deux.

Dans le sens où le tableau (ou la ArrayList) n'aura que des indices d'objets Room pour accéder aux éléments Room de ce dernier tandis que la HashMap peut en revanche fournir la Room (key) correspondante à la String (value) du même nom (pratique selon moi car il n'est besoin de connaître l'indice de la Room ou de faire un test pour y accéder).

J'envisagerais donc de créer une HashMap mais HashMap me pose un problème pour l'instant car je ne sais pas s'il est nécessaire ni même utile de la déclarer en tant qu'attribut de la classe Room, et s'il est préférable de la déclarer en Static ou pas ? Merci d'avance pour votre réponse.

Cordialement, Andrea Pancrazi.


Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, dimanche 8 octobre 2017, 16:59
 

1)
Vous avez vraiment le choix entre tableau, ArrayList et HashMap.
Il est probable que lors d'une utilisation l'un soit plus pratique, et lors d'une autre utilisation, un autre soit plus pratique.
Maintenant, si votre scénario prévoit de pouvoir ajouter des lieux en cours de jeu, le tableau ne convient plus.

2)
Par contre, il n'y a aucune différence de déclaration, initialisation, remplissage, quel que soit votre choix.
Le/la déclarer en attribut ou en local dépendra d'où vous en aurez besoin, et peut toujours se modifier ... en cas de besoin.
Le/la déclarer en static est un peu contradictoire avec le fait de pouvoir créer des objets Game.

Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, jeudi 27 février 2020, 18:24
 

Un étudiant a écrit :

j'ai réussi à mettre la HashMap avec toutes mes Rooms et tout marche correctement
hors je ne comprends pas comment on peut accéder à cette HashMap en dehors de la class game étant donné qu'elle est privée.

Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, jeudi 27 février 2020, 18:26
 

On ne peut pas !  :-)

Si on le veut vraiment, il suffira de créer un accesseur.

Mais ce n'est pas sûr qu'on en aura besoin : une méthode de Game pourra très bien appeler une méthode d'une future classe en lui passant votre HashMap en paramètre, ce qui lui en donnera l'accès.

Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, dimanche 11 octobre 2020, 17:34
 

Un étudiant a écrit :

J'ai l'impression de ne pas avoir réellement fini l'exercice, voilà ce que j'ai fait:

J'ai rajouter un attribut "private HashMap<String, Room> aRooms;" dans la classe Game (en ayant importé java.util.HashMap) puis j'ai rajouté la ligne "aRooms= new HashMap<String, Room>();" dans la procédure createRooms().

Mon jeu fonctionne toujours mais je ne suis pas sûr d'avoir vraiment répondu à l'exercice.

Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, dimanche 11 octobre 2020, 17:36
 

Cette impression est sans doute justifiée par le fait que vous n'avez rien stocké dans cette belle HashMap toute neuve, contrairement à ce que demande l'énoncé ...

Avatar Marc DE VAUGIRAUD
Re: Exercice 7.18.5
par Marc DE VAUGIRAUD, dimanche 8 novembre 2020, 23:22
 

Bonjour monsieur, 


J'avais mis sur ma "ToDoList" qu'il fallait que je tente de revenir à cet exercice pour faire quelque chose mieux que 10 lignes de "this.aRooms.put(...)"

Je pensais donc à ceci :

-Créer un accesseur de aRooms public dans Game
- utiliser cet accesseur dans e constructeur Room(). Ainsi, à chaque création de Room, la Room créée pourrait directement s'ajouter à aRooms. 

Seulement pour faire ainsi, j'ai un soucis : puis-je récupérer le nom de la Room que je suis en train de créer dans Room() ?
Je m'explique : Si je créer une Room : Room rMainEntrance = new Room("u r in Main Entrance"), puis-je récupérer le nom rMainEntrance dans mon constructeur Room() ?

Avatar Bruno LESUEUR
Re: Exercice 7.18.5
par Bruno LESUEUR, lundi 9 novembre 2020, 03:10
 

Vous devrez passer en paramètre du constructeur de Room la référence de Game. Par exemple, 

Room vR1 = new Room(this,"1");

Bien entendu, le setter dans Game, connaissant la Room en train de s'initialiser, n'aura pas grande difficulté à accéder à la description de ladite Room pour effectuer le put dans la HashMap aRooms de Game.

Votre souci est étrange : par essence même, le constructeur de Room a accès à la description de la Room !

La solution que vous voulez développer est, je crois, originale et élégante.

Ecrivez-moi directement si vous ne parvenez pas à la mettre au point.

Avatar Denis BUREAU
Re: Exercice 7.18.5
par Denis BUREAU, lundi 9 novembre 2020, 08:04
 

Je crois comprendre que vous souhaiteriez accéder au nom de la Room, et pas seulement à sa description, ce qui ne sera effectivement pas possible en dehors de createRooms, même avec la solution ci-dessus.

Aussi, je vous propose de prendre les choses dans l'autre sens :

imaginez une fonction qui vous retourne la Room qu'elle viendrait de créer, tout en l'ayant ajouté au passage à this.aRooms, puis remplacez dans createRooms les new par des appels à cette fonction, en lui passant ce fameux nom.