python projet rue

Identification

Infoforall

38 - Projet Rue


Aujourd'hui, on dessine. Mais pas n'importe comment.

Au minimum :

Et si vous êtes ambitieux :

Image tirée du module de Sofian, Alexandre et Leo

Et vous voulez un peu plus de verdure par exemple :

Image tirée du module de Matt, Imrane, Samy et Yassin

Prérequis :

  • la création et l'utilisation des modules
  • un peu de Turle pour le programme 1
  • beaucoup de Python (fonctions, dictionnaires ou objets...) pour le programme 2
  • gestion des fichiers-texte, des strings et des tableaux pour le programme 3
  • les bonnes pratiques de programmation

Logiciel nécessaire pour l'activité : Python 3 : Thonny, IDLE ...

Evaluation ✎ : le projet (déroulé, documentation, revues de projet et état final)

1 - Idée générale

Voici l'idée général du projet :

  1. On aura d'abord un premier programme comportant des fonctions capables de dessiner des formes simples. Elles utiliseront le module Turtle à l'interne.
  2. Le Programme 1 dessine des formes simples en utilisant

    Le module Turtle

  3. Un deuxième programme devra être capable de dessiner une rue comportant plusieurs immeubles. Aucune ligne de Turtle à l'intérieur de ce programme, juste des appels aux fonctions du premier programme.
  4. Le Programme 2 dessine des immeubles en utilisant

    le Programme 1 qui dessine des formes simples en utilisant

    Le module Turtle

  5. Votre troisième programme devra lire un fichier-texte contenant une description codifiée de la rue et devra la tracer en utilisant... le programme 2.
  6. Le Programme 3 lit un fichier-texte et l'interprète visuellement en utilisant

    Le Programme 2 qui dessine des immeubles en utilisant

    le Programme 1 qui dessine des formes simples en utilisant

    Le module Turtle

    Exemple de texte interprétable et qui pourrait donner le dessin ci-dessus :

    rue 4 immeubles facade rouge - 2 étages - porte au milieu - toit pointu noir facade rouge - 1 étage - porte à gauche - toit pointu noir facade verte - 4 étages - porte à droite - toit pointu noir facade violet - 3 étages - porte au milieu - toit pointu noir
    rue 4 immeubles aléatoire

    Attention, le choix de la syntaxe est totalement libre. C'est une occasion unique de créer votre langage.

Mais d'ailleurs... comment dessine Turtle ? A qui fait-il appel ?

2 - Quelques précisions

Pour être certain de partir tous dans la même direction au début, et gagner un peu de temps de coordination, voici quelques choix imposés.

On devra pouvoir créer la rue de façon aléatoire. Elle devra alors comporter au minimum 4 immeubles différents.

Chaque immeuble aura les caractéristiques suivantes :

  • Des immeubles d'une largeur de 140 pixels,
  • Chaque étage fait 80 pixels,
  • Entre 1 à 5 étages pour un immeuble
  • Chaque fenêtre fait 30 px sur 30 px
  • Une porte unique au rez-de-chaussée de 30 px sur 50px
  • Deux variations du toit
  • Plusieurs couleurs disponibles
  • Il est possible que certaines fenêtres soient des portes-fenêtres de 30 px sur 50 px

Pour simplifier les explications, je considère que votre projet comporte ces 4 fichiers, placés simplement dans le même répertoire. Bien entendu, vous êtes libres de créer un vrai package.

📁 activite_module

📄 formes.py

📄 rue.py

📄 interpreteur.py

📄 ma_rue.txt

Le projet que vous rendrez devra donc comporter au moins 4 fichiers.

Crédits : ce projet est une idée originale du site Ostralo.net.

3 - Fichiers fournis et travail à faire

Voici le squelette de formes.py, le programme 1 : celui qui devra contenir des fonctions permettant de dessiner des formes géométriques basiques : carré, rectangle, disque, cercle, triangle...

...CORRECTION...

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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
'''Ce fichier permet de dessiner deux formes à l'aide des deux fonctions suivantes + triangle_equilateral(cote, infos, coordonnees) + arc_de_cercle(rayon, angle, infos, coordonnees) Exemples d'utilisation : >>> infos_generales = {'écriture':'blue', 'fond':'#FF88FF', 'épaisseur':5} >>> triangle_equilateral(50, infos_generales, (50,100)) >>> arc_de_cercle(75, 360, infos_generales, (200,-200)) ''' # Importation import turtle as trt import random as rd # Pas de classes # Déclaration des fonctions privées def nouveau_stylo(ecriture, fond, largeur): '''Renvoie la référence d'un stylo configuré :: param ecriture(str) :: la couleur d'écriture ('red', '#FF0000') :: param fond(str) :: la couleur de fond pour ce stylo :: param largeur(int) :: la largeur du trait :: return (Turtle) :: renvoie un objet de la classe Turtle ''' feutre = trt.Turtle() feutre.color(ecriture) feutre.fillcolor(fond) feutre.pensize(largeur) feutre.speed(5) return feutre def deplacer(feutre, x, y): '''Lève le feutre, déplace le feutre et abaisse le feutre :: param feutre(Turtle) :: la référence de l'objet Turtle :: param x(int) :: coordonnée horizontale (abscisse) :: param y(int) :: coordonnée verticale (ordonnée) :: return (None) :: c'est une fonction sans retour .. effet de bord :: modifie l'état de feutre ''' feutre.penup() # On lève la pointe feutre.goto(x, y) # On déplace le crayon feutre.pendown() # On abaisse la pointe def trace_triangle_equilateral(feutre, cote): '''Trace un triangle (equilatéral) à l'aide du crayon feutre :: param ftr(Turtle) :: la référence de l'objet Turtle :: param cote(int) :: la valeur en pixel des côtés :: return (None) :: fonction sans retour .. effet de bord :: modifie l'état de feutre ''' feutre.begin_fill() for x in range(3): feutre.forward(cote) feutre.left(120) feutre.end_fill() feutre.hideturtle() def trace_arc(feutre, rayon, angle): '''Trace un arc de cercle à l'aide du crayon feutre :: param ftr(Turtle) :: la référence de l'objet Turtle :: param rayon(int) :: la valeur en pixel du rayon :: param angle(int) :: l'angle à tracer (360 pour un cercle) :: return (None) :: fonction sans retour .. effet de bord :: modifie l'état de feutre ''' feutre.begin_fill() feutre.circle(rayon, angle) feutre.end_fill() feutre.hideturtle() # Déclarations des fonctions d'interface (aucun paramètre n'est lié au module Turtle) def triangle_equilateral(cote, infos, coordonnees): '''Trace un triangle (equilatéral) à partir des infos et aux bonnees coordonnées :: param cote(int) :: la valeur en pixel des côtés :: param infos(dict) :: un dictionnaire {"écriture":str, "fond":str, "épaisseur":int} :: param coordonnees(tuple (int,int) ) :: un tuple (x,y) ''' ecriture = infos['écriture'] fond = infos['fond'] epaisseur = infos['épaisseur'] x = coordonnees[0] # ou x,y = coordonnees y = coordonnees[1] feutre = nouveau_stylo(ecriture, fond, epaisseur) deplacer(feutre, x, y) trace_triangle_equilateral(feutre, cote) return feutre def arc_de_cercle(rayon, angle, infos, coordonnees): '''Trace un arc de cercle à partir des infos et aux bonnees coordonnées :: param rayon(int) :: la valeur en pixel du rayon :: param angle(int) :: la valeur en ° de l'angle :: param infos(dict) :: un dictionnaire {"écriture":str, "fond":str, "épaisseur":int} :: param coordonnees(tuple (int,int) ) :: un tuple (x,y) ''' ecriture = infos['écriture'] fond = infos['fond'] epaisseur = infos['épaisseur'] x = coordonnees[0] # ou x,y = coordonnees y = coordonnees[1] feutre = nouveau_stylo(ecriture, fond, epaisseur) deplacer(feutre, x, y) trace_arc(feutre, rayon, angle) return feutre # Corps du programme principal if __name__ == '__main__': infos_generales = {'écriture':'blue', 'fond':'#FF88FF', 'épaisseur':5} triangle_equilateral(50, infos_generales, (50,100)) arc_de_cercle(75, 360, infos_generales, (200,-200))

Le squelette de rue.py, le programme qui devra contenir les fonctions permettant de dessiner des immeubles. Attention, beaucoup de choses à rajouter dans celui-ci. Pour l'instant, il trace notamment les 4 "immeubles" au même endroit et les immeubles ne ressemblent pas trop à des immeubles.

...CORRECTION...

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
# Importation from formes import triangle_equilateral # Fonction gestion des données def determiner_immeuble(numero:int) -> dict: caracteristiques = {} caracteristiques['couleur_facade'] = 'red' caracteristiques['numero'] = numero return caracteristiques # Fonctions d'interface graphique def dessiner_facade(informations:dict): facade = {} # pour faire la "traduction" entre les clés de ce module et les clés du module formes facade['écriture'] = 'blue' facade['fond'] = informations['couleur_facade'] facade['épaisseur'] = 5 * informations['numero'] triangle_equilateral(50, facade, (0,0)) def dessiner_porte(informations:dict): pass def dessiner_immeuble(informations:dict): dessiner_facade(informations) dessiner_porte(informations) # à compléter avec d'autres fonctions pour le reste : toit, fenêtres... # Programme principal if __name__ == '__main__': for x in range(4): infos_immeuble = determiner_immeuble(x) dessiner_immeuble(infos_immeuble)

L'intérêt du dictionnaire est évident ici : on pourra envoyer autant de caractéristiques qu'on veut. Au début il n'y aura que le numéro dans la rue, le nombre d'étages et la couleur de la façade par exemple.

Voici une proposition d'organisation pour le début du projet mais attention, le déroulé n'est pas vraiment linéaire : à vous de vous repartir le travail :


  1. Etape 1 : s'approprier formes.py (programme incomplet pour le moment) :
    • Parvenir individuellement à tracer les triangles et les cercles où vous voulez
    • Réfléchir ensemble aux formes générales qui vont être utiles pour faire des dessins quelconques.
    • Définir ensemble les prototypes de ces fonctions : noms, paramètres nécessaires...
    • L'un d'entre vous peut alors être chargé d'implémenter réellement ces fonctions.

  2. Etape 2 : s'approprier rue.py (programme non fonctionnel pour le moment) 
    • Comprendre où se détermine les caractéristiques de l'immeuble
    • Comprendre pourquoi le programme affiche juste des triangles pour le moment
    • Réfléchir ensemble aux caractéristiques essentielles à connaître sur un immeuble pour parvenir à le dessiner à l'écran.
    • L'un d'entre vous peut alors modifier la création des caractéristiques pour qu'elles soient aléatoires en partie
    • L'un d'entre vous peut modifier le programme pour que les coordonnées de l'immeuble soient dépendantes du numéro de l'immeuble.
    • L'un d'entre vous peut utiliser les fonctions de dessin pour commencer à tracer une vraie façade et pas juste un triangle
    • ...

  3. Etape 3 : réaliser entièrement le programme interpreteur.py qui doit lire un fichier-texte (en suivant une syntaxe qu'il vous faudra inventer au préalable) pour parvenir à retrouver les caractéristiques voulues pour la rue (nombre d'immeubles, caractéristiques de chaque immeuble...). Il ne restera ensuite qu'à faire appel aux fonctions du module rue.py pour tracer votre rue.

Comment avancer ensuite ?

Le point crucial est de réaliser rapidement un prototype de dessiner_immeuble() qui trace quelque chose de moche mais qui ressemble à un rectangle. On partir de ce moment, vous aurez valider la communication entre les modules rue et formes.

Pour la suite, rien n'est linéaire.

Une fois le prototype réalisé, il suffira de rajouter les options à travers de nouvelles fonctions ?:

  • une fonction pour tracer une porte ?
  • une fonction pour tracer une fenêtre ?
  • une fonction pour tracer les fenêtres ?
  • une fonction pour tracer le toit ?
  • une fonction pour tracer une antenne ou un pigeon ?
  • ...

Vous êtes plusieurs, il faudra vous répartir les fonctions à réaliser. Sinon, c'est une perte de temps. Pensez à utiliser les quelques techniques de coopération que nous avons abordé en cours.

Pour vous coordonner, il est évident qu'il faut par contre vraiment avoir défini les noms et les paramètres des fonctions avant de vraiment les réaliser.

4 - Notation

Description des 4 critères de réussite :

  1. Réalisation pratique du projet, notamment :
    • Toutes les fonctionnalités sont présentes
    • Respect scrupuleux du cahier des charges
  2. Bonnes pratiques de programmation, notamment :
    • Noms explicites
    • Utilisation limitée et raisonnée des variables globales
    • Fonctions courtes et décomposition en sous-étapes
    • Séparation entre fonctions gérant les données et l'interface graphique.
    • Présence de jeux de tests pour les fonctions gérant les données
  3. Communication (à l'écrit et à l'oral), notamment
    • Documentation des fonctions et des modules
    • Qualité de l'interaction avec l'enseignant
    • Qualité de l'interaction avec les autres membres de l'équipe
  4. Qualité de la revue de projet, notamment :
    • régularité des informations notées
    • description de qui a fait quoi
    • prototypes des fonctions avant implémentation
    • tests permettant de valider la solution avant implémentation si possible, après coup sinon

On attribue une note de 0 à 5 aux critères.

  • 5 si Bien
  • 4 si Assez bien
  • 3 si Moyen
  • 2 si Léger
  • 1 si Insuffisant
  • 0 si Rien

On fait la somme des critères.

Attention : aucun critère ne peut avoir plus que (le plus petit + 2).

  • Réalisation : Bien (5/5)
  • Bonnes pratiques : Assez bien (4/5)
  • Communication : Bien (5/5)
  • Revue de projet : Léger (2/5)

Tous les critères sont limités à 4 à cause de la revue de projet a une note de 2.

Note : 4 + 3 + 4 + 2 = 13/20.


  • Réalisation : Très bien (5/5)
  • Bonnes pratiques : Moyen (3/5)
  • Communication : Très bien (5/5)
  • Revue de projet : Bien (4/5)

Pas de limitation car le plus bas est 3 (moyen).

Note : 5 + 3 + 5 + 4 soit 17/20.

Activité publiée le 06 06 2022
Dernière modification : 06 06 2022
Auteur : ows. h.