Après toutes ces courses, il est temps de faire la fête ! Pour cela, nous allons apprendre à nos buggles à jouer à Dance Revolution, ce jeu très prisé de certains étudiants où le joueur doit bouger sur un tapis prévu à cet effet en fonction des consignes présentées à l'écran en rythme avec la musique. Mais avant cela, nous avons quelques détails à étudier.
[!java|scala|c]Il y a un détail que nous avons omis à propos de la syntaxe des conditionnelles : si une branche ne contient qu'une seule instruction, les accolades sont optionnelles. Ainsi, les deux extraits suivants sont équivalents:
if (condition) { quoiFaireSiLaConditionEstVraie(); } else { quoiFaireSinon(); }
if (condition) quoiFaireSiLaConditionEstVraie(); else quoiFaireSinon();
Vous pouvez faire de même avec les boucles dont le corps se réduit à une seule instruction. Mais attention, ceci peut être dangereux si on enchaîne les if comme dans l'exemple suivant.
if (estSurBiscuit()) if (x == 5) gauche(); else droite(); [!c]avancePas();[/!][!java|scala]avance();[/!]
En fait, ça ne tourne pas à droite quand il n'y a pas un baggle par terre ET que x vaut 5, mais quand la buggle a trouvé un baggle, et que x vaut une autre valeur. Autrement dit, la buggle lit le code précédent comme suit (notez que le else est décalé vers la droite par rapport à précédemment) :
if (estSurBiscuit()) if (x == 5) gauche(); else droite(); [!c]avancePas();[/!][!java|scala]avance();[/!]
La première leçon, c'est que l'indentation est très importante pour que les humains puissent comprendre le code, mais elle ne change pas la signification du code pour la machine. On aurait tout aussi bien pu écrire le code suivant et obtenir le même résultat. Mais attention, si on veut qu'un humain puisse relire le code, l'indentation est quasi indispensable. C'est par exemple le cas si votre code doit être relu par un professeur (pour qu'il le note ou pour lui poser une question), ou si vous comptez réutiliser votre code plus tard, ou même si vous devez debugger votre propre code après l'avoir écrit.
if (estSurBiscuit()) if (x == 5) gauche(); else droite(); [!c]avancePas();[/!][!java|scala]avance();[/!]
La seconde leçon, c'est qu'une branche else se raccroche toujours au if le plus proche. C'est parfois un peu contre-intuitif, et il est préférable d'ajouter plus d'accolades que nécessaire pour lever toute ambiguïté.
[/!]Il arrive que l'on veuille demander à la buggle quelque chose similaire à :
s'il pleut, prend un parapluie; si non, s'il fait chaud, prend une bouteille d'eau; si non, si nous sommes le 14 juillet, prend un drapeau français
Le piège étant que nous voudrions qu'au plus l'une de ces actions soient réalisées. C'est à dire, que s'il pleut un 14 juillet très chaud, on ne veut pas que la buggle sorte avec un parapluie, de l'eau et un drapeau, mais juste avec un parapluie. Le code suivant est donc faux.
[!java|c|scala]if (ilPleut()) prendreParapluie(); if (ilFaitChaud()) prendreDeLEau(); if (sommes14Juillet()) prendreDrapeau();[/!][!python]if ilPleut(): prendreParapluie() if ilFaitChaud(): prendreDeLEau() if sommes14Juillet(): prendreDrapeau()[/!]
En effet, toutes les conditions sont évaluées les unes après les autres, et on risque donc d'aller au défilé un jour de pluie. À la place, il faut donc écrire quelque chose comme ce qui suit pour s'assurer que si l'on trouve une condition vraie, on n'évalue pas les suivants.
[!java|scala|c]if (ilPleut()) { prendreParapluie(); } else { if (ilFaitChaud()) { prendreDeLEau(); } else { if (sommes14Juillet()) { prendreDrapeau(); } } }[/!][!python]if ilPleut(): prendreParapluie() else: if ilFaitChaud(): prendreDeLEau() else: if sommes14Juillet(): prendreDrapeau()[/!]
Une telle cascade de conditionnelles est un peu difficile à lire, et il est
préférable
[!java|scala|c] d'omettre les accolades associées aux else comme
suit. Il y a même certains langages qui introduisent un mot-clé spécial pour
ces else if (mais pas [!thelang]).[/!]
[!python] d'introduire les sous-blocs avec le mot-clé elif
(abréviation de «else if») pour expliciter ces branches «sinon si».[/!]
[!c|java|scala]if (ilPleut()) { prendreParapluie(); } else if (ilFaitChaud()) { prendreDeLEau(); } else if (sommes14Juillet()) { prendreDrapeau(); }[/!][!python]if ilPleut(): prendreDrapeau() elif ilFaitChaud(): prendreDeLEau() elif sommes14Juillet(): prendreDrapeau()[/!]
Les buggles peuvent écrire des choses par terre dans leur monde. Pour ce faire, elles utilisent les quatre méthodes suivantes:
[!c]int[/!][!java]boolean[/!]
estSurMessage()[!scala]:Boolean[/!]
: renvoie
[!c]1[/!][!java|scala]true[/!][!python]True[/!]
si et seulement
s'il y a un message écrit par terre.[!c]char*[/!][!java]String [/!]litMessage()[!scala]: String[/!]
: renvoie le message qu'il y a écrit par terre (s'il y a rien, on obtient
une chaîne vide).[!java|c]void[/!] ecritMessage([!c]char*[/!][!java]String
[/!]msg[!scala]: String[/!])
: écrit le message spécifié en argument
par terre. S'il y a déjà quelque chose écrit par terre, on ajoute le nouveau
message à la fin du précédent.[!java|c]void [/!]clearMessage()
: efface ce qui est écrit par
terre.Indication | Quoi faire | Mnémotechnique |
[!java|c]'R'[/!][!scala|python]"R"[/!] | Tourner à droite et avancer d'une case | Right (signifie «droite» en anglais) |
[!java|c]'L'[/!][!scala|python]"L"[/!] | Tourner à gauche et avancer d'une case | Left (signifie «gauche» en anglais) |
[!java|c]'I'[/!][!scala|python]"I"[/!] | Se retourner (demi-tour) et avancer d'une case | Inverse |
[!java|c]'A'[/!][!scala|python]"A"[/!] | Avancer d'une case | Première lettre de l'alphabet |
[!java|c]'B'[/!][!scala|python]"B"[/!] | Avancer de deux cases | Deuxième lettre de l'alphabet |
[!java|c]'C'[/!][!scala|python]"C"[/!] | Avancer de trois cases | Troisième lettre de l'alphabet |
[!java|c]'Z'[/!][!scala|python]"Z"[/!] | Reculer d'une case | A une lettre de la fin de l'alphabet |
[!java|c]'Y'[/!][!scala|python]"Y"[/!] | Reculer de deux cases | A deux lettres de la fin de l'alphabet |
[!java|c]'X'[/!][!scala|python]"X"[/!] | Reculer de trois cases | A trois lettres de la fin de l'alphabet |
(n'importe quoi d'autre) | Arrêter de danser. |
Vous devez continuer à danser tant qu'il reste des pas de danse à
faire. c-à-d tant qu'on est sur une case décrite dans le tableau. Le plus
simple pour cela est d'utiliser une variable booléenne (fini
)
en condition d'arrêt d'une boucle while. Cette variable est initialisée à la
valeur faux
([!c]0[/!][!java|scala]false[/!][!python]False[/!]
). Si on
trouve une case ne répondant à aucune ligne du tableau, on change la valeur
de cette variable à vrai
([!c]1[/!][!java|scala]true[/!][!python]True[/!]
). Cela arrête
la boucle, et le programme.
Une autre subtilité est qu'il est un peu pénible en Java de déterminer si
deux chaînes de caractères sont identiques. Nous utiliserons donc la méthode
char getIndication[!c]Bdr[/!]()
à la place de
[!java]String[/!][!c]char*[/!] litMessage()
. Cette méthode, qui
n'est connue que des buggles des exercices BDR, renvoie le premier caractère
du message au sol (ou ' ' --une espace-- s'il n'y a rien d'écrit au
sol). Cela nous permet de travailler avec des caractères
(char
), qui sont moins pénibles que les chaînes en [!thelang].
baisseBrosse()
dans votre méthode. Cela demandera à la buggle de poser une brosse par
terre, laissant une trace au sol quand elle avance. Cela devrait vous aider
à suivre sa trajectoire, mais pensez à retirer cette appel lorsque vous
voulez tester si votre solution marche : on vous demande de faire danser les
buggles, pas de dégrader le dance floor.
Quand votre programme fonctionne enfin, passez à l'exercice suivant.