Reeborg le RefurbishedRobot
transporte en lui quelques
"dés électroniques". Il peut "lancer les dés" et décider quoi faire en se basant
sur le résultat. Une telle décision, basée sur un résultat imprévisible comme
le lancer de dés, est dite aléatoire. Nous allons écrire deux programmes
qui vont éventuellement permettre à Reeborg de sortir d'un labyrinthe
en prenant des décisions aléatoires. Voici l'algorithme de base que va suivre Reeborg :
Notre premier programme va se baser sur les techniques que nous avons vues jusqu'à présent. Nous demandons à Reeborg de vérifier la présence d'un mur en face de lui et de n'avancer que s'il n'y en a aucun. C'est parfois décrit comme l'approche Regarder avant de sauter (Look before you leap - LBYL).
G = RefurbishedRobot()Nous avons mis le délai de temps à sa valeur minimale (donc à la vitesse maximale) car cela peut prendre un moment de trouver la sortie ! Quand Reeborg "lance les dés", 6 résultats différents sont possibles (les nombres de 1 à 6). L'exemple ci-dessous montre un résultat possible.
G.set_delay(0) # avancer aussi vite que possible
while True:
if G.front_is_clear():
G.move()
if G.on_beeper():
G.turn_off()
r = G.roll_dice() # "roll dice" = "lancer les dés"
if r in [1, 2]:
G.turn_left()
elif r in [3, 4]:
G.turn_right()
Pour gérer les conditions inhabituelles, les programmeurs Python utilisent souvent les "Exceptions". Par exemple, si vous essayez de diviser un nombre par zéro, Python va se plaindre de la façon suivante :
>>> x = 1/0
Traceback (most recent call last):
File "<input>", line 1, in ?
ZeroDivisionError: integer division or modulo by zero
Python a répondu en "levant" une "Exception" particulière (ZeroDivisionError) qui a aboutit au message d'erreur (ou Traceback) affiché ci-dessus. Ce processus de "lever" (raise en anglais) des exceptions est une façon pour le programme Python d'alerter l'utilisateur sur des situations qu'il ne sait pas comment gérer. Nous pouvons simuler cela en utilisant le mot-clé Python raise
>>> raise ZeroDivisionError
Traceback (most recent call last):
File "<input>", line 1, in ?
ZeroDivisionError
Quand nous savons qu'une exception particulière risque d'être levée, nous pouvons l'"intercepter" (catch en anglais) et la gérer d'une manière sensée. Voici comment nous pouvons faire cela :
>>> try:
... x = 1/0
... except:
... print "Vous avez essayé de diviser par zéro. Ce n'est pas permis."
...
Vous avez essayé de diviser par zéro. Ce n'est pas permis.
Utilisons cela afin d'écrire un deuxième programme pour faire sortir Reeborg du labyrinthe.
Quand Reeborg rencontre un problème (se cogner contre un mur, essayer de ramasser une sonnette inexistante, etc.), une exception est levée. Normalement elle termine le programme du robot et est "interceptée" par RUR-PLE pour afficher la boîte de dialogue d'erreur appropriée. Si c'est bien cela, nous pouvons écrire notre propre programme pour intercepter cette exception et l'ignorer pour permettre au programme de continuer. C'est ce que nous faisons dans le programme ci-dessous. Cela est parfois décrit comme l'approche Mieux vaut demander le pardon que la permission (Better to ask forgiveness than permission - BAFP).
G = RefurbishedRobot()
G.set_delay(0)
while True:
try:
G.move()
if G.next_to_a_beeper():
G.turn_off()
except HitWallException: # exception "se cogner contre un mur"
pass
r = G.roll_dice(3) # valeurs possibles : 1, 2, 3
if r == 1:
G.turn_left()
elif r == 2:
G.turn_right()
Dans l'exemple ci-dessus, nous avons utilisé des dés d'un genre différent, avec seulement trois résultats possibles. Vous pouvez demander à Reeborg d'utiliser des dés avec n'importe quel nombre de résultats possibles pour concevoir votre propre programme.
Si l'on ne s'attend pas à ce qu'une condition exceptionnelle se produise souvent, la deuxième approche (BAFP) est préférée. Mais si la condition exceptionnelle risque de se produire fréquemment (comme c'est le cas ici), l'approche que nous avons utilisée dans la première solution (LBYL) est recommandée.