:: Enseignements :: ESIPE :: E3INFO :: 2024-2025 :: Programmation Web avec JavaScript ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) |
Modèle, Vue, MVC, Classe, DOM
|
Le but de cet exercice est de fabriquer un jeu simple de recherche de trésor sur une plage.
Contrairement aux TPs précédent, ici, on va essayer de bien séparer ce que l'on appelle le
modèle (model), les données de l'application et la vue (view),
l'affichage de ces données.
Un des buts de cet exercice est de voir que l'on peut modifier le modèle sans changer la vue
et modifier la vue sans changer le modèle.
Comme pour les TPs précédents, on vous demande de créer le rapport du TP7 dans un fichier
compte-rendu-tp7.html.
Exercice 1 - Treasure Map
Le but de cet exercice est d'écrire une petite application Web qui permet de rechercher
des trésors sur la plage. L'utilisateur est un pirate qui ne se souvient plus exactement
de là où il a enterré ses trésors, surement un des effets du rhum sur la mémoire à long terme.
Pour cet exercice, nous travaillerons dans le fichier
treasure1.html.
-
Dans un premier temps, on va fabriquer une classe TreasureMap qui correspond
au modèle du jeu. Un modèle stocke les données du jeu, indépendamment de l'affichage.
Pour notre jeu, la plage est une grille avec une largeur (width) et une hauteur (height).
Chaque case de la grille (grid) peut contenir soit du sable, soit un trésor
Quelle est le type des valeurs width, height et grid ?
Note: on est en JavaScript ici, pas en C, on ne représente par une valeur vrai ou faux par
un entier !
Déclarer une classe TreasureMap qui contient les champs dont vous avez besoin.
Créer les méthodes dont vous avez besoin.
Créer un objet/une instance de cette classe.
Vérifier en utilisant la console de votre navigateur, pour un TreasureMap
de taille 6, 4 que vous êtes capable d'afficher
la largeur et la hauteur ainsi que si la case (3, 2) contient ou non un trésor
(en utilisant les méthodes pas les champs !)
Attention à planter (avec throw new Error()) si les index sont pas
dans les bornes !
Rappel: pour créer un tableau dynamique en JavaScript, on créé un tableau vide ([])
et on ajoute les valeurs avec push.
-
En fait, le modèle n'est pas complet, lors du jeu, tant qu'un pirate n'a pas creusé
un trou, il ne sait pas si un trésor est présent ou pas. Il faut donc, pour chaque case,
un état supplémentaire qui indique si la case a été creusé ou non.
Pour cela, on se propose de créer une classe Cell qui représente une case
de la grille avec les propriétés, il y a un trésor ou pas (treasure),
la case a été creusé ou pas (dug).
Créer la classe Cell avec ses champs et méthodes et modifier la classe
TreasureMap en conséquence.
Comme précédemment, vérifier sur la console que vous êtes capable de faire les opérations
nécessaires.
-
On s'intéresse maintenant à la vue, c-a-dire la partie affichage.
Pour cela, on va créer une fonction render qui prend en paramètre la vue (un TreasureMap)
et renvoie un objet DOM correspondant à l'affichage.
Dans notre jeu, on veut représenter la plage sous forme d'une table HTML, avec un TD pour chaque
case de la grille.
Écrire la fonction render qui fait deux boucles imbriquées pour créer les cases
de la table HTML.
Pour la tester, remplacer (en écrivant du JS) la table HTML nommé view
par le résultat de la fonction render.
Note: contrairement à Java qui oblige les fonctions à être rangées dans des classes, ce n'est pas la case
en JavaScript, donc la fonction render ne doit pas être rangée dans une classe.
Rappel: document.createElement(tagname) permet de créer un élément du DOM dynamiquement,
node.appendChild(child) permet d'ajouter le noeud child,
node.parentElement permet d'obtenir le nœud parent et
parentNode.replaceChild(newNode, oldNode) permet de remplacer un noeud par un autre.
Rappel2: Les tables en HTML ont des lignes créées avec l'élément TR.
Rappel3: Pour indiquer la classe, il existe une propriété "className" sur le nœud.
-
On souhaite maintenant détecter les cliques sur les cases, et afficher, dans un premier temps,
sur la console la ligne et la colonne de la case qui a été cliqué.
Modifier la fonction render en conséquence.
Rappel: en DOM, cell.onclick = ... enregistre une fonction qui va être appelée suite
à un clic de la souris.
-
On peut observer un problème si pour les variables de boucle, on utilise 'var' au lieu de 'let'.
Faite la modification et expliquer pourquoi le code ne marche pas correctement.
Note: Une fois que vous avez vu et expliquez le problème, revenez à un code avec des 'let'.
-
Modifier votre programme pour que lors d'un clic, le modèle soit changer pour indiquer
que l'utilisateur creuse cette case.
Puis appeler la fonction render pour redessiner la vue et remplacer l'ancienne table
par la nouvelle table.
Il faut aussi changer render pour que la classe CSS des TD reflète le fait que
la case a été creusée et que la case contient un trésor ou pas.
Si tous se passe bien, on devrait commencer à pouvoir jouer au jeu :)
Rappel: document.getElementById() cherche un élément par son "id",
si le nœud ne défini par d'id, il ne sera pas trouvé !
Exercice 2 - Treasure Map (2)
On veut maintenant améliorer le jeu, aussi bien au niveau du modèle que de la vue.
On va utiliser pour cela le fichier
treasure2.html.
A part la première question, les changements proposés par cet exercice sont indépendants les uns des autres.
-
On peut remarquer que le CSS a changé entre "treasure1.html" et "treasure2.html",
on souhaite maintenant remplacer les éléments TABLE, TR et TD par des DIV
pour que la grille fluide s'adapte à la taille de la page en utilisant les principes du
Responsive Design. .
Faite les changements correspondant dans la fonction render pour que la vue soit changée
pour utiliser des DIVs et avoir une interface graphique plus responsive.
-
Au lieu d'avoir 2 booléen, on voudrait changer l'implantation du modèle pour avoir
un seul entier qui peut valoir une des 4 constantes suivantes:
SAND_EMPTY, SAND_TREASURE, DUG_EMPTY et DUG_TREASURE.
Ces 4 valeurs peuvent être définies comme constante entière de telle façon à ce que lorsque
l'on creuse, on additionne toujours la même valeur. L'idée est que si l'on creuse,
alors SAND_EMPTY devient DUG_EMPTY et SAND_TREASURE devient
DUG_TREASURE
Modifier le modèle (la classe Cell) pour utiliser ce nouvel encodage.
Normalement, si vous avez bien designé les méthodes de Cell,
vous ne devriez pas avoir à ajouter/supprimer des méthodes, juste changer l'implantation
de celles-ci.
-
Pour améliorer (un peu) la qualité visuelle, on peut utiliser les fichiers suivants
L'idée est d'utiliser la tuile sand au début du jeu pour chaque case et lorsqu'un
utilisateur clique sur une case, changer la case pour utiliser la tuile sand-chest
ou sand-hole en fonction de s'il y a un trésor ou pas.
Les tuiles sont sûrement trop grandes, à vous de jouer avec le CSS pour les mettre à la bonne taille.
Il vous faudra peut-être aussi jouer avec les bordures pour que l'utilisateur voie les séparations
entre les cases.
Rappel: Image correspond à une image et le champ src permet d'indiquer
le contenu de l'image.
Rappel 2: au lieu de changer le contenu de l'image, vous pouvez sinon changer la classe CSS d'une cellule
et avoir 3 classes, une pour chaque image.
-
Faite en sorte que le trésor soit créer de façon aléatoire (pseudo-aléatoire) en utilisant
Math.floor() et Math.random() comme vu en cours.
-
Pour les plus balèzes, modifier le DOM/CSS pour utiliser des flexbox à la place des attributs float
et clear, histoire que votre code soit un peu plus moderne.
© Université de Marne-la-Vallée