Accueil
Mes tutoriels sur la programmation

Tutoriel Python - sommaire


Vous pouvez me contacter via Facebook (questions, critiques constructives) : page Facebook relative à mon site

Python : le module turtle ("tortue en français") pour la géométrie

Python propose un module "turtle" qui permet de dessiner des figures géométriques dans une fenêtre.
Mais avant d'aborder ce module nous allons faire une petite digression : personnaliser l'IDLE.

Personnaliser IDLE

Si vous êtes comme moi, vous trouvez que la taille de police dans l'éditeur est trop petite. Donc nous allons personnaliser l'IDLE.
Commande : Options / Configurer IDLE
Puis vous cliquez sur l'onglet "Fonts/Tabs" , déroulez la liste "size" et sélectionnez 12
Vous pouvez aussi cliquer sur l'onglet "highlights" (coloration) pour changer la couleur de texte des commentaires.

Exemple de programme Python reposant sur le module turtle

Abordons maintenant la géométrie dans Python.

Le code du programme

#nom prog. : tortue_exemple.py
from turtle import *
speed(1)
forward(200)    
left(90)
forward(100)
right(90)
forward(100)
left(90)
forward(100)
left(90)
forward(300)
mainloop()

Il faut importer le module turtle.
Il faut préciser la vitesse de traçage avec la fonction speed(). Ici vitesse très lente car le paramètre vaut 1.
Ensuite vous retrouvez toujours les mêmes types de commandes : forward(pas), left(angle) , right(angle).
Ne pas oubliez de terminer le programme avec l'instruction mainloop() pour redonner la main à l'utilisateur.

Le rendu du code

Première chose : le graphique ne s'affiche pas dans la fenêtre "Shell" comme pour un programme normal, mais dans une autre fenêtre : "Python turtle graphics".

Le graphique obtenu : tutoriel python

Question : Pour le chemin devienne un polygone (une forme fermée), il faudrait combien de commandes en plus ?
Réponse : deux (un virage à gauche de 90° et un déplacement de 200).

Dessiner un carré

Un carré est un polygone régulier de 4 côtés égaux et 4 angles égaux (angles droits)

Le code

#nom programme : tortue_carre.py
#objet : dessiner un carre
from turtle import *
speed(1)
pencolor('red')
c =input('côté du carré ? : ')
c=eval(c)       
#convertir en numérique la saisie
forward(c)
left(90)
forward(c)
left(90)
forward(c)
left(90)
forward(c)
exitonclick()

Par défaut la couleur du trait est noir. Ici je demande qu'il soit rouge avec la fonction pencolor().

Le côté du carré désiré est saisi dans la variable c.
Rappel : toute saisie avec la fonction input() est de type string ; il faut donc convertir le contenu de c en un numérique avec la fonction eval().
Ensuite vous avez 4 fois le même couple d'instructions : forward(c) et left(90)
On aurait pu écrire le code d'une façon beaucoup plus correcte sur un plan algorithmique.

...
for i in range(5) : 			#pour i allant de  0 à 4
	forward(c)
	left(90)

Un carré de plus en plus grand

Tapez le programme suivant :

# nom programme : tortue_carre_bis.py
from turtle import *
pencolor('purple')
speed(5)
for i in range(50):
    forward(20 + (i*10) )
    left(90)
mainloop()

A chaque passage dans la boucle l'argument de la commande forward est plus grand de 10. Donc on dessine une sorte de labyrinthe.

Le rendu : tuto python

Dessiner des polygones réguliers

Objectif

Je veux réaliser un programme très généraliste capable de produire n'importe quel polygone régulier : carré, pentagone, hexagone, octogone, décagone.

Dans tous les cas la somme des "virages à gauche" doit être égale à 360° afin que la tortue revienne à sa position de départ.
Donc pour un carré, chaque "virage à gauche" doit avoir un angle de : 360/4 = 90°
Et pour un pentagone , chaque "virage à gauche" doit avoir un angle de : 360/5 = 72°
etc.

Le code

#nom prog. : tortue_polygone.py
#objet : dessiner un polygone régulier de n côtés (4 ou 5 ou 6 ou 8 ou 10)
from turtle import *
n ="2"
while n not in "456810":         #controle de saisie
    n = input ("nombre de côtés du polygone : 4/5/6/8/10 : ")
cote = input("longueur du côté : " )
n =eval(n) #convertir n en numérique
c=eval(cote)
angle=360 / n 
for i in range(n):
    forward(c)
    left(angle)
exitonclick()

Il y a un contrôle de saisie basé sur l'opérateur "not in … " : tant que n n'est pas inclus dans la chaine "456810" on peut répéter la saisie.
Pour qu'il y ait au moins un passage dans la boucle, il faut une valeur initiale à n , valeur non comprise dans la chaine "456810".
Le programme est très court grâce à une structure "for i in range(n):".
À la place de mainloop() on peut utiliser l'instruction exitonclick() : si clic sur le graphique, l'utilisateur reprend la main.

Dessiner des cercles et arcs de cercles

Il faut utiliser la fonction cercle(rayon, [angle]).
Le seul argument obligatoire est le rayon.

Exemple : un cercle de plus en plus grand

Tapez le programme suivant :

# nom programme : cercles.py
from turtle import *
pencolor('orange')
speed("slow")
for i in range(30):
  circle(i +20)
exitonclick()

L'argument de la fonction speed() peut être un entier (entre 0 et 10) mais aussi une chaine : "fast", "normal", "slow", …
Remarque : la tortue tourne à gauche. Si vous voulez qu'elle tourne à droite la valeur du rayon doit être négative.

Dessiner un stade

Stade : un rectangle avec à chaque extrémité deux demi-cercles.

Tapez le programme suivant :

from turtle import *
speed('slow')
pencolor('navy')
pensize(3)
forward(500)
circle(100,180)
forward(500)
circle(100,180)
mainloop()

Remplir une surface

Vous pouvez souhaitez que la forme dessinée soit remplie d'une certaine couleur.
Reprenons le programme "tortue_polygone.py" et améliorons le !
Pour réouvrir un programme récemment fermé, vous pouvez dans l'IDLE produire la commande par menu : File/Recent Files...
Sélectionnez tout le code, faites une copie (commande : Edit/copy), créez un nouveau fichier (commande : File/New File) et collez.

La nouvelle version

#nom prog. : tortue_polygone_plus.py
#objet : dessiner un polygone régulier de n côtés (4 ou 6 ou 8 ou 10)

from turtle import *
speed('slow')
pencolor('purple')
pensize(5)
fillcolor('lime')
bgcolor('pink')

n ="2"
while n not in "456810":        #controle de saisie
    n = input ("nombre de côtés du polygone : 4/5/6/8/10 : ")

cote = input("longueur du côté : " )
n =eval(n) #convertir n en numérique
c=eval(cote)
angle=360 / n

begin_fill()
for i in range(n):
    forward(c)
    left(angle)
end_fill()       
exitonclick()

Analyse du code

Le programme devient conséquent.

Le rendu

Le graphique obtenu après avoir saisi 5 et 200 : tuto python

Joli !

Connaitre la position de la tortue

Code à saisir

# nom programme : tortue_infos py
from turtle import *
for i in range(4):  #boucle effectuée 4 fois (0 à 3)
    print ("position tortue : ", position())
    forward(200)
    left(90)
print ("position tortue : ", position())  

Rendu dans la fenêtre shell

position tortue :  (0.00,0.00)
position tortue :  (200.00,0.00)
position tortue :  (200.00,200.00)
position tortue :  (0.00,200.00)
position tortue :  (-0.00,0.00)

En parenthèse la valeur de l'abscisse puis celle de l'ordonnée de chaque angle.

Analyse

La fonction position() retourne les coordonnées x et y de la tortue à un stade donné.
Ce programme s'éxécute dans deux fenêtre : un carré est dessiné dans la fenêtre "graphique" et les affichages se font dans la fenêtre "shell".

On devine que la fenêtre graphique est un repère cartésien (dont les axes sont masqués).
Au départ la tortue est à l'origine du repère cartésien (x=0, y=0)

Donc comme l'origine du repère cartésien est le centre de la fenêtre graphique, l'abscisse et l'ordonnée de la tortue peuvent être des valeurs négatives ...

Autre technique pour dessiner

Plutôt que d'utiliser les fonctions forward(), left(), right() nous utilisons la fonction goto(x,y).

Premier exemple

# nom programme : tortue_goto.py
from turtle import *
speed('slow')

goto(-300,-300)
goto(300,-300)
goto(300,300)
goto(-300,300)
goto(0,0)

mainloop()

Vous notez que parfois les valeurs de x et y sont négatives.

Capture de la fenêtre "graphique" ci-dessous : tuto python

Remarque

Sans qu'on le demande, on a un segment de l'origine jusqu'au premier angle (-300, -300).

La solution

Pour éviter ce segment disgracieux du point d'origine vers le premier point par le programme, il suffit de "soulever le stylo" ...

Code à taper

from turtle import *
speed('slow')
up()
goto(-300,-300)
down()
goto(300,-300)
goto(300,300)
goto(-300,300)
up()
goto(-100,-100)
down()
goto(100,-100)
goto(100,100)
goto(-100,100)
goto(-100,-100)
up()
goto(0,0)
down()
write ("hello !", font=("Arial", 14, "normal"))
mainloop()

Le rendu

tuto python

Nouveautes

Dessiner des triangles

Vous avez vu que dessiner des polynomes réguliers c'est facile. Mais dessiner des triangles demande de faire appel à des notions de géométrie plus avancées ...

Triangle équilatéral

Rappel : un triangle équilatéral est un triangle dont les 3 côtés et les trois angles sont égaux.
Comme la somme des angles d'un triangle est toujours égale à 180°, chaque angle d'un équatéral fait 180/3 = 60°

Le code :

#nom programme : equilateral.py
from turtle import *
speed('slow')
pencolor('red')
fillcolor('lime')
pensize(3)

begin_fill()
forward(200)
left(120)
forward(200)
left(120)
forward(200)
end_fill()

exitonclick()

Le rendu : tuto python

Observez bien ce graphique !
La tortue est orientée vers le bas et la gauche.
Donc si vous rajoutiez "forward(200)" le tracé serait orienté vers la gauche et le bas.

Analyse du code :
Le code laisse dubitatif ...
Chaque angle doit faire 60° et pourtant je programme des "left(120)" ...
L'explication est simple : pour former un angle interne de 60° il faut faire effectuer à la tortue un virage très serré de (180° - 60° = 120°). C'est la notion d'angles supplémentaires (somme de deux angles supplémentaires =180°).

Dessiner une étoile à 6 branches

En fait une étoile à 6 branches ("étoile de David") est faite de deux triangles équilatéraux qui se superposent.

Le rendu : tuto python

Il faut donc dessiner le premier triangle équilatéral puis lever le stylo, déplacer la tortue vers le point (0,100) et dessiner le deuxième triangle.

Extrait du code :

...
#fin premier triangle

up()
home()
goto(0,100)
down()

#début deuxième triangle 
right(60)
...

Remarque :
Nouvelle instruction : home()
Suite au premier triangle, la tortue était dirigée vers la gauche et vers le bas. Il faut qu'elle soit de nouveau disposée à tracer vers la droite avec cette instruction.

Dessiner une étoile à 5 branches

Chaque angle du triangle doit faire 36° (180 / 5).
Donc pour obtenir un angle interne de 36° il faut faire un virage serré à gauche de 144 (180 - 36).

#nom programme : etoile5.py
#objet du programme : dessiner une étoile à 5 branches.

from turtle import *
speed(1)
c = 200
right(36)
for k in range(5):
    forward(200)
    left(144)
home()
exitonclick()

Le rendu : tuto python

Grâce à l'instruction home() la tortue est de nouveau orientée de façon normale et retrouve la position 0,0.
Pensez à cette instruction, si vous devez dans un même graphique enchainer le dessin de plusieurs formes.

Exercice : dessiner un triangle rectangle

Si vous voulez dessiner directement un triangle rectangle ce sera la prise de tête.
En effet vous devriez saisir : le grand côté de l'angle droit puis le petit côté de l'angle droit. Ensuite calculer l'hypothénuse en utilisant le célèbre théorème de Pythagore : le carré de l'hypoténuse est égal à la somme des carrés des côtés de l'angle droit.
Mais c'est pas tout il faut déterminer les deux autres angles. Il faut donc faire de la trigonométrie (branche des mathématiques qui traite des relations entre distances et angles un triangle rectangle).
Avec Python c'est possible, puisque le module math propose toutes les fonctions trigonométriques. Mais c'est vraiment se compliquer la vie, il y a beaucoup plus simple : un triangle rectangle est inscrit dans un rectangle.

Il suffit donc de dessiner un rectangle mais de lever le stylo pour ne pas tracer une longueur et une largeur puis de baisser le stylo pour dessiner une diagonale du rectangle (l'hypothènuse du triangle rectangle).

Le rendu : tuto python

Le code :
Je vous communique la fin du code.
lo : grand côté ; la : petit côté (à saisir)

...
forward(lo)
up()
left(90)
forward(la)
left(90)
forward(lo)
down()
goto(lo,0)
home()
goto(0,la)