Table des matières

TD 2 : Allons sur Mars

Dans cette seconde séance, nous allons voir comment encapsuler les objets. L’objectif est de rendre l’utilisation d’un objet et son implémentation aussi indépendantes que possible pour que les modifications d’implémentation n’aient pas (ou peu) d’impact sur les classes l’utilisant. Nous allons également prendre en main un IDE (Environement de Développement Intégré) qui va nous simplifier l’édition de code Java.

Prise en main d’IntelliJ et de Gradle

Suivre le tutoriel de prise en main d’Intellij et de Gradle

Attention Une maîtrise minimale de ces deux outils est supposée acquise par la suite.

Encapsulation

Nous considérons maintenant que la surface de la planète Mars est décomposée en tuiles carrées (quadrillage). Le robot peut seulement se déplacer de tuile en tuile. La position du robot s’exprime donc maintenant sous forme de coordonnées (x,y) de type entier qui représente le numéro de colonne et le numéro de ligne dans le quadrillage. Le fichier Position.java contenu dans l’archive td2-sample.zip fournit une implémentation minimale de la classe Position.

1) Modifiez la visibilité des attributs x et y en private. Constatez alors qu’une erreur de visibilité apparait dans la classe Main.

2) Ajoutez dans la classe Position les méthodes getX() et getY() permettant de récupérer respectivement l’abscisse et l’ordonnée de la position. À noter que ces méthodes ne permettent pas de modifier les attributs, mais fournissent simplement un moyen de récupérer l’information.

3) Modifier la classe Main pour utiliser ces méthodes.

4) Ajouter les méthodes suivantes vues lors du TD précédent.

void translate(int dx, int dy) { ... }
void translate(int delta) { ... } 

Mondialisation Il est important de respecter les standards de codage qui recommandent d’utiliser l’anglais pour permettre au plus grand nombre une relecture aisée du code.

Modificateur d’accès des méthodes

Actuellement, nos méthodes n’ont pas de modificateurs d’accès. L’absence de modificateurs d’accès est en soit un niveau de visibilité, appelé friendly et qui correspond à la visibilité paquetage. Pour faire simple, toutes les classes d’un même répertoire appartiennent au même paquetage. Cependant, il est courant que l’on souhaite rendre disponibles le plus largement possible certaines méthodes. On utilise dans ce cas le modificateur d’accès public.

Retour sur Mars

Nous allons pour la suite de ce TD prendre en main une base de code un peu plus conséquente qui va permettre d’interagir avec notre robot martien. Pour ce faire, téléchargez l’archive suivante : td2-student. Une fois l’archive décompressée le code est exécutable sans erreur. Par la suite les seules classes à modifier sont les classes Main et Robot. Mais il est fortement conseillé de prendre le temps de lire les autres classes.

1) Exécutez le code contenu dans cette archive et repérez graphiquement votre robot.

2) Dans la classe Main après l’instanciation du robot, ajoutez la ligne position.translate(10); puis exécuter à nouveau le code. Que constatez-vous ?

3) Comment peut-on rendre le robot indépendant de la variable position contenu dans la méthode start de la classe Main?

4) Proposez une solution en modifiant le constructeur de Robot.

5) Remplacez maintenant la ligne position.translate(10); par robot.getPosition().translate(10); puis exécuter à nouveau le code. Que constatez-vous ?

6) Faites les modifications nécessaires dans la classe Robot.

7) La classe SpriteRobot est fournie et ne doit pas être modifiée. Elle est chargée de l’affichage graphique du robot. La classe Robot ne contient que la modélisation du robot, indépendamment de sa représentation graphique. Complétez les méthodes suivantes de la classe Robot.

// Rayon d'action du robot
int range(); 

// Est-ce que le robot peut se déplacer sur la position cible?
boolean canMove(Position target);

// Actions à réaliser lorsque le robot se déplace sur la cible: mise à jour des coordonnées du robot, de son énergie restante, etc.
void move(Position target);

Espace géométrique discret

Contrairement au TD précédent, le calcul de la distance entre deux positions se fait maintenant dans la classe Robot et dans un espace géométrique discret. C’est-à-dire que notre robot ne peut plus se déplacer que de case en case soit horizontalement soit verticalement. Il n’a pas la possibilité de se déplacer en diagonale (c’est un choix qui n’est pas dépendant de l’espace dans lequel il évolue). On dit que le déplacement est en connexité-4.

Pour rappel la méthode distance permet de calculer la distance entre la position actuelle du robot et la cible à atteindre. Attention cette méthode doit maintenant renvoyer un int correspondant au nombre de cases à parcourir pour atteindre la cible.

// Distance entre la position actuelle du robot et la cible
int distance(Position target)

1) Modifiez la méthode distance de la classe Robot pour qu’elle calcule la distance de manhattan.

2) Testez votre code afin que lors d’un clic de la souris sur une tuile de la surface martienne, le robot se déplace s’il dispose de suffisamment d’énergie pour atteindre la cible.

Animation du déplacement

Notre robot est pour le moment capable de se déplacer instantanément, ce qui n’est pas très réaliste! Nous allons réaliser une animation graphique pour visualiser le déplacement entre la position source et la position cible. Nous utilisons pour cela le code de la méthode animateMove de la classe SpriteRobot. Comme vous pouvez le constater, cette méthode utilise la méthode getPathTo de la classe Robot. Cette méthode renvoie un tableau de positions sur lesquelles le robot doit se rendre pour atteindre la cible (hors la position source).

1) Fournissez une implémentation simple de la méthode getPathTo. Le robot se déplace d’abord à l’horizontale, puis à la verticale. Le chemin comporte au plus deux positions.

2) Améliorez le code de votre méthode pour que le déplacement se fasse en escalier.

Pour aller plus loin Essayez d’équilibrer les marches de l’escalier…

3) Que se passe-t-il lors d’un clic de la souris sur une tuile de la surface martienne si le robot est encore en train de se déplacer?

4) Faites en sorte que le robot ne puisse accepter un nouvel ordre de déplacement que lorsqu’il a terminé le déplacement en cours.