En mathématiques lorsqu'une quantité apparaît plusieurs fois ainsi dans $x(x+1) -2(x+1)$, l'expression $x+1$ apparaît deux fois
On factorise $x+1$ et on obtient $x(x+1) -2(x+1) = (x+1)(x-2)$
De même dans un programme lorsqu'un groupe d'instructions apparaît plusieurs fois, comme dans le programme suivant (entouré en rouge), on va le mettre en commun en définissant une fonction
Puisque les instructions que l'on veut mettre en commun servent à calculer le milieu de deux points connaissant les coordonnées des deux points(x1,y1) et (x2,y2) il est naturel de nommer cette fonction milieu
def milieu(x1,y1,x2,y2):
return (x1+x2)/2,(y1+y2)/2
Cette fonction a en entrée quatre nombres, les coordonnées des points et retourne en sortie les coordonnées du milieu
En plus d'éviter les redondances dans un programme, les fonctions rendent un programme plus compréhensible
On obtient donc
Attention, il faut distinguer la définition d'une fonction, ce qu'elle fait, et l'exécution de la fonction
Pour visualiser cela recopier la fonction milieu dans PythonTutor pour vous aider à visualiser le processus
On pourrait factoriser encore le programme en utilisant un objet très utile en Python, les listes, mais ce sera pour un autre TP!
Nous allons simuler un mouvement aléatoire de la tortue ainsi
La tortue quitte l'origine (0,0) et tant qu'elle est à l'intérieur du disque de centre (0,0) et de rayon SEUIL fixé au départ elle avance au hasard toujours d'une même nombre de pixels PAS mais dans une direction aléatoire ainsi
SEUIL <- 100
PAS <- 5
Tant que la tortue est à l'intérieur du disque de centre (0,0) et de rayon SEUIL
i <- tirer un nombre au hasard entre 0 et 35
angle <- i*10
régler la direction de la tortue sur angle
avancer de PAS pixels
Comment traduire "la tortue est à l'intérieur du disque de centre (0,0) et de rayon SEUIL" ?
On a vu en mathématiques une formule permettant de calculer la distance entre deux points repérés, donc une première traduction pourrait être
"la tortue est à l'intérieur du disque de centre (0,0) et de rayon SEUIL" -> "racine_carré(xT*xT + yT*yT) < SEUIL"
On peut économiser le calcul de la racine carrée en traduisant:
"la tortue est à l'intérieur du disque de centre (0,0) et de rayon SEUIL"
par "xT*xT + yT*yT < SEUIL*SEUIL"
d'où l'algorithme:
SEUIL <- 100
PAS <- 5
xT <- abscisse de la tortue
yT <- ordonnée de la tortue
Tant que xT*xT + yT*yT < SEUIL*SEUIL
i <- tirer un nombre au hasard entre 0 et 35
angle <- i*10
régler la direction de la tortue sur angle
avancer de PAS pixels
xT <- abscisse de la tortue
yT <- ordonnée de la tortue
que l'on traduit en python par
from turtle import *
from random import *
SEUIL = 100
PAS = 10
xT = xcor()
yT = ycor()
while xT*xT + yT*yT < SEUIL*SEUIL:
i = randint(0,35)
angle = i*10
setheading(angle)
forward(PAS)
xT = xcor()
yT = ycor()
Modifier le programme :
Pour PAS = 10
Pour PAS = 2
L'algorithme a perdu de sa lisibilité quand on a traduit "la tortue est à l'intérieur du disque de centre (0,0) et de rayon SEUIL" par "xT*xT + yT*yT < SEUIL*SEUIL"
Si quelqu'un lit l'algorithme il ne comprendra pas forcément à quoi sert xT*xT + yT*yT < SEUIL*SEUIL
De quoi a-t-on besoin ?On a juste besoin de savoir si la tortue est à l'intérieur ou à l'extérieur du disque, ce que l'on peut assimiler à un processus (ou fonction ) ayant en entrée les coordonnées de la tortue (xT,yT) et en sortie Vrai ou Faux
D'où le nouvel algorithme où on définit une fonction estDansLeDisque(rayon)
Le sujet de "est" est l'objet principal de notre algorithme, la tortue
fonction estDansLeDisque(x,y,rayon)
'''retourne vrai si le point de coordonnées (x,y) est dans le
disque de centre (0,0) et de rayon rayon'''
retourner x*x + y*y < rayon*rayon
SEUIL <- 100
PAS <- 5
xT <- abscisse de la tortue
yT <- ordonnée de la tortue
Tant que estDansLeDisque(xT,yT,SEUIL)
i <- tirer un nombre au hasard entre 0 et 35
angle <- i*10
régler la direction de la tortue sur angle
avancer de PAS pixels
xT <- abscisse de la tortue
yT <- ordonnée de la tortue
que l'on traduit en python par
from turtle import *
from random import *
#----------------------------------------------------------
def estDansLeDisque(x,y,rayon):
'''retourne vrai si le point de coordonnées (x,y) est dans le
disque de centre (0,0) et de rayon rayon'''
return x*x + y*y < rayon*rayon
#----------------------------------------------------------
SEUIL = 100
PAS = 10
xT = xcor()
yT = ycor()
while estDansLeDisque(xT,yT,SEUIL):
i = randint(0,35)
angle = i*10
setheading(angle)
forward(PAS)
xT = xcor()
yT = ycor()
On peut continuer et retrouver presque la lisibilité du premier algorithme en introduisant deux autres fonctions tracerCercleLimite(rayon) et reglerAleatoirementDirectionTortue()
from turtle import *
from random import *
#----------------------------------------------------------
def tracerCercleLimite(rayon):
goto(0,-rayon)
pendown()
pencolor("red")
circle(rayon)
#----------------------------------------------------------
def estDansLeDisque(x,y,rayon):
'''retourne vrai si le point de coordonnées (x,y) est dans le
disque de centre (0,0) et de rayon rayon'''
return x*x + y*y < rayon*rayon
#----------------------------------------------------------
def reglerAleatoirementDirectionTortue():
i = randint(0,35)
angle = i*10
setheading(angle)
#----------------------------------------------------------
SEUIL = 100
PAS = 10
hideturtle()
speed(0)
penup()
tracerCercleLimite(SEUIL)
pencolor("black")
penup()
goto(0,0)
pendown()
xT = xcor()
yT = ycor()
while estDansLeDisque(xT,yT,SEUIL):
reglerAleatoirementDirectionTortue()
forward(PAS)
xT = xcor()
yT = ycor()
exitonclick()