Les Bugs en boucles¶
L’objectif de ce TP est :
Déterminer des structures de boucles (itératives) et les implémenter.
Produire le comportement attendu du/des Bug(s).
Structures de contrôle de type boucles¶
Les structures de contrôle de type boucles permettent d’exprimer des traitements répétitifs. En Java, les boucles sont au nombre de trois: la boucle while, la boucle do…while et la boucle for.
la boucle while¶
La boucle while permet de répéter une séquence d’instructions tant qu’une certaine condition est vérifiée :
while (condition) { // bloc d'instructions }
Lors de l’exécution du programme, si la condition est vérifiée (vraie), alors le bloc d’instructions est exécuté. Ce traitement est ensuite répété tant que la condition reste vérifiée. Si la condition n’est pas vérifiée dès le départ, le bloc d’instructions n’est pas exécuté.
La boucle while permet de traduire la structure tant que du langage algorithmique.
La boucle do…while¶
Comme la boucle while, la boucle do…while permet de répéter une séquence d’instructions tant qu’une certaine condition est vérifiée.
do { // bloc d'instructions } while (condition);
Lors de l’exécution du programme, le bloc d’instructions est exécuté. Ensuite, si la condition est vérifiée (vraie), alors ce traitement est répété. La différence avec la boucle while est que le bloc d’expression est exécuté au moins une fois.
La boucle do…while permet de traduire la structure répéter du langage algorithmique.
La boucle for¶
La boucle for est un cas particulier de la boucle while. La boucle for suivante :
for (expression A ; expression B ; expression C) { // bloc d'instructions }
est équivalente à la boucle while :
expression A; while (expression B) { // bloc d'instructions expression C; }
Ainsi, expression A correspond à l’initialisation de la boucle, expression B correspond à la condition de la boucle, et expression C correspond à une instruction exécutée après chaque itération de la boucle.
La boucle for est généralement utilisée pour faire varier un compteur entre deux bornes définies. Par exemple, pour afficher les nombres entiers entre -10 et +10, on utilisera :
for (int i = -10 ; i <= 10 ; i++) { System.out.println(i); }
La boucle for permet ainsi de traduire la structure pour du langage algorithmique.
Défi n°1 : chacun sa marche¶
État initial
|
Résultat attendu
|
|
|
À faire
Récupérer
l'archive du programme, l’enregistrer dans le dossier du TP puis la décompresser.Le programme comprend les mêmes classes et fichiers que pour les TPs précédents. Se reporter à l’énoncé du TP Le monde des Bugs pour les détails et pour la référence de l’API.
Positionner les variables et constantes du fichier Main.java :
final int N_BUGS=7; final int Y_BUGS=0; final int HAUTEUR = 7; final int LARGEUR = 7; final int TAILLE_CASE = 80; boolean readMaze = true ;
Récupérer
la définition des murs, l’enregistrer dans le dossier du TP.Compiler le programme tel qu’il est fourni pour vérifier qu’il n’y a pas d’erreur et que l’état initial est bien celui reproduit ci-dessus.
Écrire un programme (méthode enRoute()) qui produise le résultat escompté. Seule la méthode avance() (sans paramètre) sera employée pour faire progresser les Bugs.
Correction
Défi n°2 : chacun son biscuit¶
Cet exercice est très semblable au précédent.
État initial
|
Résultat attendu
|
|
|
À faire
Modifier le fichier mazeData pour placer les 7 biscuits aux bons emplacements.
Modifier le programme pour que chaque Bug ramasse son biscuit. Seule la méthode avance() (sans paramètre) sera employée pour faire progresser les Bugs.
Correction
Défi n°3 : chacun chez soi¶
Il s’agit d’une variante de l’exercice précédent où chaque Bug doit revenir à sa position d’origine après avoir ramassé le biscuit qui lui était promis. Des solutions particulières mais non génériques s’offrent à vous pour réaliser cela. Toutefois, on vous demande d’opter pour une technique générique transposable à beaucoup d’autres situations : mémoriser le parcours.
Malgré tout, le déplacement des Bugs est encore simple et la mémorisation se résume ici à compter le nombre de pas efféctués jusque’au biscuit.
À faire
Déclarer une variable
nbPasFaits, locale à la méthode enRoute(). Elle servira à mémoriser, à chaque itération, le nombre de pas qu’un Bug a déja effectués en direction du biscuit.Modifier le programme pour incrémenter convenablement la variable
nbPasFaitset l’utiliser pour revenir en position initiale. Aucun Bug ne devra se cogner au mur, et seule la méthode avance() (sans paramètre) sera employée pour faire progresser les Bugs.
Correction
Défi n°4 : la course au biscuit¶
La course au biscuit consiste pour chaque Bug à courir droit devant lui en ramassant les biscuits qu’il trouve. Lorsqu’il a amassé quatre biscuits, il fait demi tour et revient au plus vite à son point de départ. Si un Bug parcourt toute la piste sans parvenir à trouver quatre biscuits, il revient tout de même, bredouille, à la case de départ.
À faire
Récupérer le fichier
mazeData.txtcontenant les positions des biscuits dans la grille.Ajuster les paramètres de la classe Main pour générer une grille de 8x15 cases.
Compiler puis exécuter le programme pour vérifier l’état initial.
Concevoir l’algorithme sur feuille, puis l’implémenter dans la méthode enRoute().
Correction
Défi n°5 : Les Bugs fêtent Divali¶
Chaque année, à l’occasion de la fête de Divali (la fête des lumières), on peut voir des hommes marcher sur des braises. Les Bugs Belfortains, en vacances à l’île Maurice, veulent s’y essayer, mais sans récompense point de motivation pour nos Bugs (pas comme les étudiants), alors on a placé des biscuits sur la piste de braises.
Chaque Bug doit, comme pour le défi précédent, ramasser quatre biscuits puis revenir à sa case départ. Seulement, marcher sur des braises, ça brule ! Et à force de se bruler, la force risque de quitter nos Bugs. Chaque fois qu’un Bug passe sur une case très chaude (peinte en jaune), il perd un point de vitalité. Lorsqu’il doit ramasser un biscuit placé sur une case chaude, il en perd deux car cela le ralentit. Enfin, lorsqu’un Bug a perdu tous ses points de vitalité, il grille et stoppe tout net sa progression.
À faire
Récupérer le fichier
mazeData.txtcontenant les positions des biscuits dans la grille.Ajuster les paramètres de la classe Main pour générer une grille de 8x15 cases.
Déclarer le tableau des cases chaudes au début de la méthode Main() comme ceci (le copier/coller est vivement recommandé) :
final int[][] casesColorees = { {14,0},{14,1},{14,2},{14,3},{14,4},{14,5},{14,6},{14,7}, {13,0},{13,1},{13,6},{13,7}, {12,1},{12,6}, {11,1},{11,2},{11,5},{11,6}, {10,0},{10,1},{10,2},{10,3},{10,4},{10,5},{10,6},{10,7}, {9,1},{9,6}, {8,0},{8,1},{8,2},{8,3},{8,4},{8,5},{8,6},{8,7}, {5,2},{5,6}, {4,1},{4,6}, {3,1},{3,3},{3,5},{3,7}, {2,4}, {1,6} };
Compiler puis exécuter le programme pour vérifier l’état initial.
Concevoir l’algorithme sur feuille, puis l’implémenter dans la méthode enRoute(). On considérera ici que sur le chemin du retour, lorsque le Bug revient à sa case de départ, les braises sont refroidies et qu’il ne se brule donc plus. Les illustrations ci-dessus correspodent à cette situation.
Modifer le programme pour considérer cette fois que les braises sont toujours chaudes lors du retour.
Indication
Dans l’exemple, chaque Bug s’est vu attribué 9 points de vie au départ de la course.
Note
Pour comparer deux objets Java, on utilise la méthode equals(), implémentée pour la plupart des classes. Ainsi, pour comparer la couleur du sol avec la couleur de référence (ici le jaune), on écrira un test comme celui-ci :
if( getCouleurSol().equals(StdDraw.YELLOW) ){ ... }
Correction en version braises refroidies au retour
Défi n°6 : Un Bug au JO¶
L’un de vos Bugs s’est découvert une passion pour la course à pieds. Il espère parvenir à se qualifier pour les prochains jeux bugolympiques et s’en donne les moyens : Il s’entraine chaque jour sur la piste d’athlétisme et suit rigoureusement le programme que lui a établi son coach. Chaque matin, le Bug doit faire exactement dix tours de la piste carrée reproduite ci-dessous, dans le sens conventionnel c’est à dire anti-horaire. Mais au fil des tours, ses pointes usent la piste et cette dernière se dégrade rapidement. On constate la dégradation par son changement de couleur tour après tour.
État initial
|
Résultat attendu
|
|
|
À faire
Récupérer le fichier
mazeData.txtdéfinissant la piste.Ajuster les paramètres de la classe Main pour générer une grille de 11x11 cases ainsi qu’un seul Bug.
Concevoir l’algorithme de progression du Bug en n’employant que les méthodes
avance() sans paramètre
gauche()
Penser à définir des constantes pour ne pas devoir employer de valeurs littérales dans les boucles.
Implémenter l’algorithme et en vérifier la bonne marche. Le Bug pourra envoyer un message à chaque passage sur la ligne.
Compléter votre conception en ajoutant la gestion de la couleur de la piste. Lors du premier tour, elle doit être blanche (code RVB = [255,255,255]) pour se griser tour après tour et devenir gris foncé lors du dernier tour (code RVB = [128,128,128]). Toutes les couleurs adoptées seront définies par un seul paramètre
coefCouleurappliqué aux trois canaux (code RVB [coefCouleur, coefCouleur, coefCouleur]).La définition de la couleur en Java peut alors se faire ainsi
import java.awt.*; // à placer tout au début du fichier endehors de la classe Color couleurPiste = new Color(coefCouleur,coefCouleur,coefCouleur) ;
Indication
On peut se donner une loi de variation affine commune aux trois canaux de couleur et prenant la valeur 255 pour
tour=0et la valeur 128 pourtour=10. L’expression correspondante est donc une équation de droite que vous devez déterminer après l’avoir esquissée au brouillon pour \(tour \in [0 ; 10[\).
Correction
Défi n°7 : Un Bug au JO (suite)¶
Courir sur la piste, c’est lassant. Alors votre Bug a décidé de vaier un peu et d’aller en forêt. Seulement avec les obstacles et les etangs, ce n’est pas facile non plus. Il a tout de même réussi à déterminer un tour composé de quatre cotés identiques et reproduit ci-dessous (résultat attendu) .
Comme l’effort est plus intense, il décide de limiter son entrainement à sept tours de ce parcours. Malgré tout, l’herbe s’abime elle aussi et noircit un peu plus à chaque passage.
État initial
|
Résultat attendu
|
|
|
À faire
Ajuster les paramètres de la classe Main pour générer une grille de 15x15 cases ainsi qu’un seul Bug.
Concevoir l’algorithme de progression du Bug en n’employant que les méthodes
avance() sans paramètre
gauche()
On pourra cette fois tolérer des valeurs littérales pour les nombres de pas de chaque segment.
Implémenter l’algorithme et en vérifier la bonne marche. Le Bug pourra envoyer un message à chaque passage sur la ligne. La liste des cases étangs peintes en bleu se définit ainsi
final int[][] casesColorees = { {14,0},{14,1},{14,7},{14,13},{14,14}, {13,0},{13,6},{13,7},{13,8},{13,14}, {12,3},{12,7},{12,11}, {11,2},{11,3},{11,11},{11,12}, {10,2},{10,7},{10,12}, {9,6},{9,7},{9,8}, {8,1},{8,5},{8,6},{8,8},{8,9},{8,13}, {7,0},{7,1},{7,2},{7,4},{7,5},{7,9},{7,10},{7,12},{7,13},{7,14}, {6,1},{6,5},{6,6},{6,8},{6,9},{6,13}, {5,6},{5,7},{5,8}, {4,2},{4,7},{4,12}, {3,2},{3,3},{3,11},{3,12}, {2,3},{2,7},{2,11}, {1,0},{1,6},{1,7},{1,8},{1,14}, {0,0},{0,1},{0,7},{0,13},{0,14} };
Pour fixer la couleur de fond (vert) vous positionnez la constante
COULEUR_FONDconvenablement dans la classe Main.
Compléter votre conception en ajoutant la gestion de la couleur de l’herbe. Lors du premier tour, elle doit être verte (code RVB = [0,255,0]) pour se noircir tour après tour et devenir vert foncé lors du dernier tour (code RVB = [0,128,0]).
Correction
Défi n°8 : Les Bugs perdus¶
Un Bug est perdu dans un étrange labyrinthe et il a besoin de vous pour trouver la sortie (représentée par les cases oranges). Vous ne pouvez pas donner le chemin tout simplement avec quelque chose comme droite();avance();avance(); parce qu’il faut pouvoir secourir tout Bug quelle que soit sa position de départ. La bonne nouvelle est que le chemin vers la sortie est en quelque sorte écrit au sol : En effet, ce labyrinthe est composé de plusieurs corridors, avec des biscuits par terre. À chaque embranchement, il faut prendre
à gauche si le corridor qu’on vient de parcourir contient 3 biscuits ou plus,
à droite s’il contient 2 biscuits ou moins.
Vous devez compter exactement 5 cases par couloir. Les cases aux intersections doivent être comptées comme les dernières de leur couloir, pas comme les premières après avoir tourné. La forme générale de votre code doit donc être quelque chose comme
TANT QUE la sortie n'est pas ateinte FAIRE prendre le prochain couloir pour décider s'il faut tourner à gauche ou à droite au prochain embranchement. FIN_TANTQUE
Vous pouvez déterminer si vous avez rejoint la sortie (indiquée en orange) avec la méthode isSortieTrouvee() fournie. Pour prendre un couloir, il suffit de courir d’une intersection à l’autre tout en comptant les biscuits en chemin. Ce qui complique un peu, c’est qu’au début du couloir, vous vous trouvez bien entendu à une intersection, mais vous souhaitez avancer quand même. Le plus simple pour cela est alors d’utiliser une boucle do / while à la place d’une boucle while pour se déplacer d’une intersection à l’autre. Une autre petite difficulté est la gestion des couloirs qui débouchent sur un bord ou dans un coin. Dans ces cas, il est parfois impossible de pouvoir avancer dans la direction déterminée par le nombre de biscuits trouvés. La stratégie à adopter sera alors la suivante :
SI direction D interdite ALORS choisir la direction "tout droit" SI direction interdite ALORS choisir la direction opposée à D FIN_SI FIN_SI
État initial
|
Résultat attendu
|
|
|
À faire
Ajuster les valeurs des constantes dans la classe Main comme ci-dessous
final int N_BUGS=1; final int Y_BUGS=1; final int HAUTEUR = 18; final int LARGEUR = 23; final int TAILLE_CASE = 30; final Color COULEUR_PP = StdDraw.ORANGE ;
Définir les deux cases à colorier pour la sortie avec
final int[][] casesColorees = { {16,22},{16,21} };
Copier le code de la méthode isSortieTrouvee() dans la classe Bug
/** * indique si on est sur la sortie, * cad si la case est de couleur ORANGE * @return vrai si on est sur la sortie */ public boolean isSortieTrouvee(){ return getCouleurSol().equals(StdDraw.ORANGE); }
Récupérer le fichier
mazeData.txtdéfinissant la piste et les positions des biscuits.Compiler puis vérifier que l’état initial correspond bien à ce qui est attendu.
Concevoir au brouillon l’algorithme de résolution de ce labyrinthe aux régles particulières; puis l’implémenter en java dans la méthode enRoute(). Il peut-être intéressant pour la mise au point de permettre au Bug de donner des informations sur sa progression, comme par exemple
Bug 0 dit : 3 biscuits ==> à gauche Bug 0 dit : 5 biscuits ==> à gauche Bug 0 dit : 2 biscuits ==> à droite Bug 0 dit : 1 biscuits ==> à droite Bug 0 dit : 2 biscuits ==> à droite Bug 0 dit : 5 biscuits ==> à gauche Bug 0 dit : 3 biscuits ==> à gauche Bug 0 dit : 1 biscuits ==> à droite Bug 0 dit : 2 biscuits ==> à droite Bug 0 dit : 1 biscuits ==> à droite Bug 0 dit : 4 biscuits ==> à gauche Bug 0 dit : 2 biscuits ==> à droite Bug 0 dit : 3 biscuits ==> à gauche Bug 0 dit : 1 biscuits ==> à droite Bug 0 dit : 3 biscuits ==> à gauche Bug 0 dit : 3 biscuits ==> à gauche Bug 0 dit : 3 biscuits ==> à gauche Bug 0 dit : 1 biscuits ==> à droite Bug 0 dit : 3 biscuits ==> à gauche Bug 0 dit : 2 biscuits ==> à droite Bug 0 dit : 2 biscuits ==> à droite Bug 0 dit : 2 biscuits ==> à droite Bug 0 dit : 4 biscuits ==> à gauche Bug 0 dit : 3 biscuits ==> à gauche Bug 0 dit : 2 biscuits ==> à droite Bug 0 dit : Youpi !
Correction













