Skip to content

Tortue Logo

Énoncé

Dans ce premier mini-projet, on se propose d’écrire un programme simulant un mini Logo. Logo est un langage de programmation vous permettant de contrôler une petite tortue représentant la pointe d’un crayon, dessinant une image lors de ses déplacements.

logo de Logo

La tortue obéit à différentes commandes mais nous ne considérerons dans ce TP que les commandes suivantes :

  • avance
  • tourne_droite
  • tourne_gauche
  • leve_crayon
  • baisse_crayon

Votre travail consiste à implémenter toutes les fonctions du module logo.py dont le squelette vous est fourni ici et affiché ci dessous. Comme vous le constatez, le module logo.py utilise le module svg.py que nous avons développé dans le TP précédent. Si vous ne savez pas comment utiliser ce module, cela signifie que vous n'avez pas fait l'exercice à ce sujet lors de la séance précédente et que vous trouverez ici.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""Module tortue logo.

Ce module implémente les primitives graphiques basiques
d'une tortue logo.
"""

import svg


def avance(abscisse, ordonnee, direction, crayon_en_bas, distance):
    """Fait avancer la tortue.

    Fait avancer la tortue dans la direction donnée et de la distance donnée.
    Affiche le segment SVG correspondant sur la sortie standard
    si le crayon est en bas.

    Renvoie la nouvelle position de la tortue sous la forme
    d'un tuple à deux entiers.
    """
    # TODO
    ...


def tourne_droite(direction, angle):
    """
    Fait tourner la tortue à droite.

    Fait tourner la tortue à partir de direction en tournant
    à droite de l'angle donné (en degrés).

    Renvoie la nouvelle direction.
    """
    # TODO
    ...


def tourne_gauche(direction, angle):
    """
    Fait tourner la tortue à droite.

    Fait tourner la tortue à partir de direction en tournant
    à droite de l'angle donné (en degrés).

    Renvoie la nouvelle direction.
    """
    # TODO
    ...

Vous aurez sûrement besoin de fonctions de trigonométrie de base dans ce TP : elles sont fournies par le module math de Python.

Nous vous fournissons le programme principal test_logo.py ici et affiché ci dessous. Une lecture attentive de ce programme de test vous permettra de bien comprendre ce que doit faire chacune des fonctions du module logo.py.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env python3

"""Programme pour tester le module logo."""

import logo
import svg


def main():
    """On crée un dessin a l'aide du module logo."""

    # On démarre notre image SVG
    print(svg.genere_balise_debut_image(100, 100))
    # En Python on peut nommer les arguments quand on appelle une
    # fonction. Cela rend le code beaucoup plus lisible en général.
    print(
        svg.genere_balise_debut_groupe(
            couleur_ligne="black", couleur_remplissage="none", epaisseur_ligne=3
        )
    )

    # Position de la tortue
    abscisse = 0.0
    ordonnee = 0.0
    # Angle du regard de la tortue en degrés
    # par rapport à l'horizontale, la tortue
    # regarde donc vers le haut.
    direction = 90.0
    # Si le crayon de la tortue est en bas,
    # celle-ci doit dessiner un trait quand elle
    # avance, et sinon elle doit juste se déplacer
    crayon_en_bas = False

    # On se déplace sans dessiner
    direction = logo.tourne_droite(direction, 180.0)
    # Ici on fait du tuple unpacking : on récupère d'un coup les 2 éléments du tuple.
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 50.0)
    direction = logo.tourne_gauche(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 50.0)
    direction = logo.tourne_gauche(direction, 90.0)

    # On va dessiner un premier truc
    crayon_en_bas = True
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)
    direction = logo.tourne_droite(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)
    direction = logo.tourne_droite(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)
    direction = logo.tourne_droite(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)

    # On se déplace sans dessiner
    crayon_en_bas = False
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)

    # On dessine un deuxième truc
    crayon_en_bas = True
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)
    direction = logo.tourne_droite(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)
    direction = logo.tourne_droite(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)
    direction = logo.tourne_droite(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)

    # On se déplace sans dessiner
    crayon_en_bas = False
    direction = logo.tourne_droite(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 20.0)
    direction = logo.tourne_gauche(direction, 90.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 10.0)

    # On dessine un troisième truc
    crayon_en_bas = True
    direction = logo.tourne_gauche(direction, 45.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 30.0)
    direction = logo.tourne_gauche(direction, 45.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 30.0)
    direction = logo.tourne_gauche(direction, 45.0)
    abscisse, ordonnee = logo.avance(abscisse, ordonnee, direction, crayon_en_bas, 30.0)

    # On termine l'image SVG
    print(svg.genere_balise_fin_groupe())
    print(svg.genere_balise_fin_image())


main()

Ce programme ne doit pas être modifié mais doit obligatoirement être utilisé pour tester votre module logo.py. Comparez le résultat avec celui de vos camarades pour vous convaincre (ou non au contraire) que votre implémentation du module logo.py est correcte.

Pour dessiner des segments dans votre module logo.py, vous utiliserez la fonction suivante que vous devez rajouter à votre module svg.py :

1
2
3
4
5
6
7
8
def genere_segment(dep, arr):
    """
    Retourne la chaîne de caractères correspondant à un élément SVG représentant
    un segment. Ce segment relie les points dep et arr qui sont tous les deux
    des tuples de deux nombres.
    """
    # TODO
    ...

On rappelle que la documentation SVG est accessible sur le site de w3schools.

Il est assez facile de se tromper dans les calculs pour ce TP, n’hésitez pas à interpeller votre enseignant pour qu’il vous explique comment déboguer votre programme.

Correction

Cliquez ici pour révéler la correction.

Voici la correction du module logo.py :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
"""Module tortue logo.

Ce module implémente les primitives graphiques basiques
d'une tortue logo.
"""

from math import cos, sin, pi

import svg


def avance(abscisse, ordonnee, direction, crayon_en_bas, distance):
    """Fait avancer la tortue.

    Fait avancer la tortue dans la direction donnée et de la distance donnée.
    Affiche le segment SVG correspondant sur la sortie standard
    si le crayon est en bas.

    Renvoie la nouvelle position de la tortue sous la forme
    d'un tuple à deux entiers.
    """
    # Il faut que l'on fasse un peu de trigonométrie.
    # On avance suivant un vecteur donné par la direction.
    # Attention : comme la doc nous le rappelle cos et sin
    # prennent des angles en radians.
    vecteur = (cos(direction * pi / 180), sin(direction * pi / 180))
    nouvelle_abscisse = abscisse + vecteur[0] * distance
    nouvelle_ordonnee = ordonnee - vecteur[1] * distance
    nouveau_point = (nouvelle_abscisse, nouvelle_ordonnee)
    # On dessine maintenant
    if crayon_en_bas:
        segment_svg = svg.genere_segment((abscisse, ordonnee), nouveau_point)
        print(segment_svg)

    return nouveau_point


def tourne_droite(direction, angle):
    """
    Fait tourner la tortue à droite.

    Fait tourner la tortue à partir de direction en tournant
    à droite de l'angle donné (en degrés).

    Renvoie la nouvelle direction.
    """
    return direction - angle


def tourne_gauche(direction, angle):
    """
    Fait tourner la tortue à droite.

    Fait tourner la tortue à partir de direction en tournant
    à droite de l'angle donné (en degrés).

    Renvoie la nouvelle direction.
    """
    return direction + angle

Voici la correction de la fonction genere_segmnent :

1
2
3
4
5
6
7
def genere_segment(dep, arr):
    """
    Retourne la chaîne de caractères correspondant à un élément SVG représentant
    un segment. Ce segment relie les points dep et arr qui sont tous les deux
    des tuples de deux nombres.
    """
    return f'<line x1="{dep[0]}" x2="{arr[0]}" y1="{dep[1]}" y2="{arr[1]}" />'

Exercices