Aller au contenu

Boucles for

A propos du chapitre

Objectif :

  • Comprendre le principe d'une boucle for
  • Utiliser une boucle for pour factoriser des instructions répétitives
  • Utiliser une boucle for pour executer un nombre variable d'instructions
  • Rénover la grange en lui ajoutant des fenêtres.
  • Des dessins géométriques plus intéressants

example grange example geo

Modalités :

  • Programmation (Basthon)
  • De la réflexion autour du code

Prérequis : "Programmation/Variables"

Difficulté : moyen.

Remarque : Le code commence à être un peu plus touffu. Ne vous laissez pas démonter et demandez de l'aide si besoin !!!

remarque ? c'est OK si on va pas jusqu'au bout ?

Remarque prof : introduire le début (la boucle) aussi !

Introduction : fenêtres ?

Activité : problème de rénovation

Vous avez désormais un projet de rénovation de votre grange, pour la transformer en maison.

La première étape pour la rendre habitable, c'est de lui créer des fenêtres.

Dans le dépliant ci-dessous, vous trouverez une version du code de la grange dans laquelle j'ai ajouté des fenêtres, avec uniquement les outils que je vous ai présenté en Python jusqu'à présent.

Code de la grange modifié
from turtle import *
speed(0)

largeur = 150
hauteur = 100
profondeur = 60

# On se déplace pour centrer la maison

left(180)
forward(largeur/2)
left(90)
forward(hauteur / 2 + profondeur / 2)
#on oublie pas de se réorienter correctement
left(90)

#face avant
fillcolor("hsl(33 42.5% 85.8%)")
color("hsl(33 42.5% 85.8%)")

begin_fill()
forward(largeur)
left(90)
forward(hauteur)
left(90)
forward(largeur)
left(90)
forward(hauteur)
end_fill()

#on se positionnne pour le dessus
penup()
left(180)
forward(hauteur)
right(90)
forward(40)
pendown()

#dessus
color("hsl(0 80.7% 63.5%)")
fillcolor("hsl(0 80.7% 63.5%)")

begin_fill()
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
left(90)
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
end_fill()

#pan gauche
color("hsl(0 80.4% 69.6%)")
fillcolor("hsl(0 80.4% 69.6%)")

begin_fill()
right(45)
forward(60)
right(135)
forward(profondeur)
right(45)
forward(60)
right(135)
forward(profondeur)
end_fill()

#on se positionne pour le pan droit

penup()
left(90)
forward(largeur - 40 * 2)
pendown()

#on dessine le pan droit
color("hsl(0 80.7% 56.8%)")
fillcolor("hsl(0 80.7% 56.8%)")

begin_fill()
right(45)
forward(60)
left(135)
forward(profondeur)
left(45)
forward(60)
left(135)
forward(profondeur)
end_fill()

#on se place pour la porte
penup()
left(90)
forward(40)
right(90)
forward(hauteur)
right(90)
forward(largeur - 20)
pendown()

#on trace la porte
color("hsl(14 67.8% 28.7%)")
fillcolor("hsl(14 67.8% 28.7%)")

begin_fill()
right(90)
forward(30)
right(90)
forward(40)
right(90)
forward(30)
right(90)
forward(40)
end_fill()

#on se place pour la fenêtre de gauche
penup()
forward(20)
right(90)
forward(50)
right(90)
forward(30)
pendown()

#fenêtre de gauche
color("hsl(191 39.5% 82.2%)")
fillcolor("hsl(191 39.5% 82.2%)")

begin_fill()
forward(30)
left(90)
forward(30)
left(90)
forward(30)
left(90)
forward(30)
left(90)
end_fill()

#on se place pour la fenêtre de droite
penup()
forward(largeur / 2 - 30 + largeur / 2)
left(180)
forward(30)
pendown()

#fenetre de droite 

color("hsl(191 39.5% 82.2%)")
fillcolor("hsl(191 39.5% 82.2%)")

begin_fill()
forward(30)
right(90)
forward(30)
right(90)
forward(30)
right(90)
forward(30)
right(90)
end_fill()

hideturtle()

done()

Copiez-collez le dans Basthon, et exécutez-le. Vous devriez voir apparaître une jolie maison :

example intro

Les fenêtres sont aussi hautes que la porte : ce sont des portes fenêtres. Est-ce que c'est dangereux d'en mettre à l'étage ? Peut être... Est-ce que c'est stylé ? Sans aucun doute !

Modifiez la hauteur et la largeur pour trouver des valeurs qui posent problème. Pourquoi c'est un problème d'un point de vue du dessin paramétrique ?


Solution

Si on mets une largeur très grande ou une hauteur très grande, la façade fait "vide" : il n'y a que deux fenêtre isolées.

example intro

Si on mets une hauteur très petite, les fenêtre dépassent sur le toit :

example intro

C'est un problème parce que même si on peut changer automatiquement la taille de la maison, on va devoir ajouter les fenêtres à la main...

Idéalement, on voudrait pouvoir faire varier automatiquement le nombre de fenêtre avec la largeur et la hauteur de la façade.

Et ça tombe bien, il y a un outils super pour ça en Python : les boucles for.

Pro tip : s'écarter pour progresser

Il arrive qu'on remarque en cours de route qu'il nous manque une compétence pour atteindre un objectif complexe.

Il est souvent alors plus efficace de s'écarter temporairement de l'objectif pour acquérir cette compétence, puis de revenir sur l'objectif avec la compétence totalement ou partiellement acquise.

Ainsi, on peut se focaliser sur l'apprentissage sans avoir à gérer la complexité de l'objectif, et sans risquer de régresser en "cassant" quelque chose.

Voici deux illustrations :

En escalade, un jeté me bloque dans une voie. Avant de travailler ce mouvement dans la voie, je travaille le mouvement au sol, ou sur des voies plus faciles . Ainsi, je m'entraîne d'abord sans me sur-fatiguer pour atteindre le jeté dans la voie, et sans peur de tomber.

En programmation, je dois apprendre les boucles for pour dessiner les fenêtres de la maison. Je travaille d'abord les boucles for a part. Ainsi, je ne suis pas perturbé par le reste du code de la maison, et je ne risque pas de casser le code de la maison.

Activité : mission possible

Voici un petit bout de code en Python qui comporte une boucle for:

for _ in range(3)   
    print("TA tala ta ta")
    print("TA")
print("Ta tala ta ta")
print("TATATA")

Essayez de comprendre ce qu'il fait.

Une fois que vous pensez avoir compris, executez-le pour vérifier vos hypothèses.

Boucle for ?

Présente dans la majorité des langages de programmation, la boucle for permet de répéter un groupe de lignes de code, appelé corps de la boucle, un nombre déterminé de fois.

Voici une syntaxe un peu simplifiée d'une boucle for en Python.

for _ in range(NOMBRE DE REPETITIONS):
    instruction1
    instruction2
    instruction3

Le corps de la boucle est indenté (décalé) vers la droite.

Ca permet à l'interprêteur de différencier ce qui est dans la boucle et ce qui n'y est pas :

for _ in range(NOMBRE DE REPETITIONS):
    dans
    la
    boucle
pas 
dans 
la 
boucle

Au clavier

On peut faire l'indentation avec la touche tabulation, ou tab. Elle a généralement un symbole qui ressemble à .

Elle se trouve en haut à gauche sur le clavier, juste au-dessus de la touche verrouillage majuscule .

Vous pouvez aussi utiliser des espaces, mais il faut faire attention a toujours avoir le même nombre d'espaces.

Activité : un avant dernier carré.

Utilisez une boucle for pour faire un carré.

Promis, c'est l"avant dernière fois que je vous fait dessiner un carré.

La dernière, ce sera dans le prochain chapitre, pour vous expliquer comment ne plus avoir à dessiner un carré.

Solution

Normalement, c'est pas compliqué : on répète 4 fois aller tout droit, et tourner.

from turtle import *

for _ in range(4):
    forward(100)
    left(90)

done()

Bravo ! vous avez factorisé le code : maintenant, dessiner les 4 côtés d'un carré prends seulement 2 lignes, répétées 4 fois. Ca va nous permettre de rendre le code beaucoup plus lisible !

Paramétriser les répétitions : polygones

Et surtout, de dessiner des polygones avec PLEINS de côtés très facilement !

Activité : pentagone

Dessinez un pentagone régulier avec une boucle for

Les côtés d'un pentagone forment un angle de 108 degrés !

Solution
from turtle import *

for _ in range(5):
    forward(100)
    #on oublie pas que l'angle qu'on donne n'est pas le bon
    # il faut donc faire 180 - angle voulu
    left(180 - 108)

done()

Activité : octogone

Dessinez un octogone régulier avec une boucle for1

Les côtés d'un octogone forment un angle de 135 dégrés !

Solution
from turtle import *

for _ in range(8):
    forward(70)
    #on oublie pas que l'angle qu'on donne n'est pas le bon
    # il faut donc faire 180 - angle voulu
    left(180 - 135)

done()

Activité : dodécagone

Dessinez un dodécagone (12 cotés) régulier avec une boucle for

Les côtés d'un dodécagone forment un angle de 150 degrés !

Solution
from turtle import *

for _ in range(12):
    forward(70)
    #on oublie pas que l'angle qu'on donne n'est pas le bon
    # il faut donc faire 180 - angle voulu
    left(180 - 150)

done()

Vous pouvez bien entendu utiliser une variable pour le nombre de répétitions :

nombre = 100
for _ in range(nombre):
    print("AAAAAAH")

Activité : etoiles

Traduisez en Python le code suivant :

soit un nombre N

On répète N fois :
    Avancer de 200
    tourner a gauche de 154 degrés

Utilisez une variable pour N. Donnez-lui eventuellement un autre nom.

N'oubliez pas la première et la dernière ligne (from ... et done ()).

Testez différentes valeurs pour N, par exemple 10, 20, 50, 100, 120 et 200.

Solution
from turtle import *

speed(0)

repetitions = 50

for _ in range(repetitions):
    forward(200)
    left(154)

done()

Normalement, vous venez de découvrir un des attraits de la génération paramétrique : la surprise.

  • On crée un programme un peu complexe avec des paramètres
  • On lance le programme en fixant des valeurs pour les paramètres
  • On découvre ce que le programme produit, et c'est la surprise !

Répéter encore et encore le même bout de code, c'est déjà super utile. Mais ça a quand-même des limites.

Un truc qui serait trop bien, c'est de pouvoir faire un truc un tout petit peu différent à chaque tour de boucle.

Et... Oh, COMME PAR HASARD, pile, PILE quand on en a besoin : la prochaine section vous explique comment faire !

Variable d'itération

Comme promis, voici une boucle qui fait presque la même chose, mais pas exactement la meme chose à chaque tour :

for nombre in range(4)
    print(nombre)

Activité : vérifiez

Executez le code ci-dessus pour vérifier que j'ai pas menti !

Plus généralement, en Python, on peut écrire une boucle for comme suit :

for NOM_VARIABLE in range( N ): #N le nombre de répétitions
    instructions

Ici, NOM_VARIABLE est la variable d'itération de la boucle.

C'est une variable un peu particulière, qui change de valeur à chaque itération (tour de boucle).

On peut l'utiliser pour paramétriser le corps de la boucle.

Quand on l'utilise avec range(N), elle prends successivement toutes les valeurs entières de 0 à N-1.

Activité : spirale

Ecrivez un programme qui dessine une spirale, du style :

spirale

c'est pas forcément très facile, prenez votre temps et n'hésitez pas à demander de l'aide !

Solution
from turtle import *


speed(0)

for i in range(100):
    forward(1 + i * 4)
    left(90)


done()

Activité : juste par curiosité...

Essayez de modifier l'angle de votre spirale.

Vous devriez observer des résultats ... surprenants !

Solution ou presque

J'aime beaucoup :

118, 119, 123, 143, 151, 154, 166.

j'aime un peu :

168, 70, 71, 73, 80, 91

Rénovations rétrogaming

Gardez votre code

Vous allez améliorer le code d'une activité à l'autre, et le réutiliser dans les prochains chapitres.

Si possible GARDEZ-LE précieusement quelque part où vous pourrez le retrouver (par exemple, dans un document texte) !

TODO (prof) ajouter une extension pour le doc texte

Dans tous les cas, pas de panique. Je vous fournirai des points de sauvegarde du code quand on en aura besoin dans le prochains chapitres.

Maintenant, vous avez plus ou moins tous les outils pour faire de belles fenêtres à votre grange !

Vous pourrez reprendre le code de la grange que vous avez écrit au chapitre précédent, ou utiliser le checkpoint dans le dépliant suivant :

Checkpoint : code de la grange
from turtle import *
speed(0)

largeur = 150
hauteur = 100
profondeur = 60

# On se déplace pour centrer la maison

left(180)
forward(largeur/2)
left(90)
forward(hauteur / 2 + profondeur / 2)
#on oublie pas de se réorienter correctement
left(90)

#face avant
fillcolor("hsl(33 42.5% 85.8%)")
color("hsl(33 42.5% 85.8%)")

begin_fill()
forward(largeur)
left(90)
forward(hauteur)
left(90)
forward(largeur)
left(90)
forward(hauteur)
end_fill()

#on se positionnne pour le dessus
penup()
left(180)
forward(hauteur)
right(90)
forward(40)
pendown()

#dessus
color("hsl(0 80.7% 63.5%)")
fillcolor("hsl(0 80.7% 63.5%)")

begin_fill()
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
left(90)
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
end_fill()

#pan gauche
color("hsl(0 80.4% 69.6%)")
fillcolor("hsl(0 80.4% 69.6%)")

begin_fill()
right(45)
forward(60)
right(135)
forward(profondeur)
right(45)
forward(60)
right(135)
forward(profondeur)
end_fill()

#on se positionne pour le pan droit

penup()
left(90)
forward(largeur - 40 * 2)
pendown()

#on dessine le pan droit
color("hsl(0 80.7% 56.8%)")
fillcolor("hsl(0 80.7% 56.8%)")

begin_fill()
right(45)
forward(60)
left(135)
forward(profondeur)
left(45)
forward(60)
left(135)
forward(profondeur)
end_fill()

#on se place pour la porte
penup()
left(90)
forward(40)
right(90)
forward(hauteur)
right(90)
forward(largeur - 20)
pendown()

#on trace la porte
color("hsl(14 67.8% 28.7%)")
fillcolor("hsl(14 67.8% 28.7%)")

begin_fill()
right(90)
forward(30)
right(90)
forward(40)
right(90)
forward(30)
right(90)
forward(40)
end_fill()

done()

Activité : briefing

Je vais vous aider, pas à pas, à adapter le nombre de fenêtres à la largeur de votre maison.

example grange example grange

Deux valeurs sont paramétrables : la largeur des fenêtre, et aussi l'écartement minimal entre les fenêtres (et entre les fenêtres et les bords du mur).

Les fenêtres sont centrées, et le nombre de fenêtres s'adapte automatiquement pour maximiser le nombre de fenêtres sans dépasser sur les écarts minimums.

Les fenêtres sont de simples carrés/rectangles. J'utilise ici la couleur suivante :

color("hsl(191 39.5% 82.2%)")
fillcolor("hsl(191 39.5% 82.2%)")

Si vous voulez du défi

Essayer d'ajouter ce comportement à votre programme avec uniquement les informations du briefing.

Si vous voules ENCORE PLUS de défi

Adaptez aussi le nombre de fenêtres à la hauteur.

Dans cette section, vous aurez sans doute besoin d'un opérateur supplémentaire :

opérateur description exemples
A // B Division entière de A par B 10 // 10, 3 // 2, 7 // 2`

La division entière (ou division euclidienne) est la division "avec reste" :

7 // 2 # vaut 3, parce que 7 = 2 x 3 + 1

Pour résumer, on doit dessiner des fenêtres :

  • Centrées
  • Avec un espacement défini
  • En nombre suffisant, mais pas en surnombre
  • Pas trop proches des murs non plus

Ca fait beaucoup !

Pro tip : approche incrémentale

Vous vous rappelez ? On va faire petit à petit :

  • Dessiner UNE fenêtre
  • Dessiner des fenêtres avec un nombre choisi à la main
  • Choisir automatiquement le nombre de fenêtres
  • Centrer les fenêtres

Activité : une fenêtre

Reprenez le code de la grange du chapitre précédent. Ou utilisez le checkpoint en début de section.

Dessinez une fenêtre à la grange, paramétrée par deux variables :

  • espacement_fenetres, qui est la distance entre le mur et la fenêtre
  • largeur_fenetres, qui est la largeur de la fenêtre.

grange fenetre

Solution
from turtle import *
speed(0)

largeur = 150
hauteur = 100
profondeur = 60

largeur_fenetres = 30
espacement_fenetres = 30

# On se déplace pour centrer la maison

left(180)
forward(largeur/2)
left(90)
forward(hauteur / 2 + profondeur / 2)
#on oublie pas de se réorienter correctement
left(90)

#face avant
fillcolor("hsl(33 42.5% 85.8%)")
color("hsl(33 42.5% 85.8%)")

begin_fill()
forward(largeur)
left(90)
forward(hauteur)
left(90)
forward(largeur)
left(90)
forward(hauteur)
end_fill()

#on se positionnne pour le dessus
penup()
left(180)
forward(hauteur)
right(90)
forward(40)
pendown()

#dessus
color("hsl(0 80.7% 63.5%)")
fillcolor("hsl(0 80.7% 63.5%)")

begin_fill()
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
left(90)
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
end_fill()

#pan gauche
color("hsl(0 80.4% 69.6%)")
fillcolor("hsl(0 80.4% 69.6%)")

begin_fill()
right(45)
forward(60)
right(135)
forward(profondeur)
right(45)
forward(60)
right(135)
forward(profondeur)
end_fill()

#on se positionne pour le pan droit

penup()
left(90)
forward(largeur - 40 * 2)
pendown()

#on dessine le pan droit
color("hsl(0 80.7% 56.8%)")
fillcolor("hsl(0 80.7% 56.8%)")

begin_fill()
right(45)
forward(60)
left(135)
forward(profondeur)
left(45)
forward(60)
left(135)
forward(profondeur)
end_fill()

#on se place pour la porte
penup()
left(90)
forward(40)
right(90)
forward(hauteur)
right(90)
forward(largeur - 20)
pendown()

#on trace la porte
color("hsl(14 67.8% 28.7%)")
fillcolor("hsl(14 67.8% 28.7%)")

begin_fill()
right(90)
forward(30)
right(90)
forward(40)
right(90)
forward(30)
right(90)
forward(40)
end_fill()


#on se place pour la fenêtre de gauche
penup()
forward(20)
right(90)
forward(50)
right(90)
forward(espacement_fenetres)
pendown()

#fenêtre de gauche
color("hsl(191 39.5% 82.2%)")
fillcolor("hsl(191 39.5% 82.2%)")

begin_fill()
forward(largeur_fenetres)
left(90)
forward(30)
left(90)
forward(largeur_fenetres)
left(90)
forward(30)
left(90)
end_fill()


done()

Pro tip : versions et checkpoints

Quand vous modifiez du code existant, il y a toujours un risque de le casser.

Pour ne pas risquer de perdre votre travail quand vous tentez des trucs, n'hésitez pas à sauvegarder votre code (par exemple dans un document texte) avant de vous lancer dans des grosses modifications.

L'idéal est de nommer les fichiers d'une manière qui vous permette de vous y retrouver facilement.

Je vous propose la règle suivante :

  • Le nom du fichier commence par le nom du projet,
  • suivi de la date et de l'heure de l'enregistrement, au format AAAA-MM-JJ_HH-MM. De cette manière l'ordre chronologique est aussi l'ordre alphabétique !
  • Suivi, eventuellement, d'un court descriptif de l'état du code.

Par exemple :

ma_grange_2026-10-01_17-30.txt


ma_grange_2026-10-01_17-30_une_fenetre.txt

Activité : des fenêtres

Ajoutez une variable nombre_fenetres dans le code.

Modifiez le code pour dessiner le nombre de fenêtres défini par la variable.

Elles doivent être espacées de espacement_fenetres.

grange fenetre

Solution
from turtle import *
speed(0)

largeur = 150
hauteur = 100
profondeur = 60

largeur_fenetres = 30
espacement_fenetres = 30
nombre_fenetres = 3

# On se déplace pour centrer la maison

left(180)
forward(largeur/2)
left(90)
forward(hauteur / 2 + profondeur / 2)
#on oublie pas de se réorienter correctement
left(90)

#face avant
fillcolor("hsl(33 42.5% 85.8%)")
color("hsl(33 42.5% 85.8%)")

begin_fill()
forward(largeur)
left(90)
forward(hauteur)
left(90)
forward(largeur)
left(90)
forward(hauteur)
end_fill()

#on se positionnne pour le dessus
penup()
left(180)
forward(hauteur)
right(90)
forward(40)
pendown()

#dessus
color("hsl(0 80.7% 63.5%)")
fillcolor("hsl(0 80.7% 63.5%)")

begin_fill()
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
left(90)
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
end_fill()

#pan gauche
color("hsl(0 80.4% 69.6%)")
fillcolor("hsl(0 80.4% 69.6%)")

begin_fill()
right(45)
forward(60)
right(135)
forward(profondeur)
right(45)
forward(60)
right(135)
forward(profondeur)
end_fill()

#on se positionne pour le pan droit

penup()
left(90)
forward(largeur - 40 * 2)
pendown()

#on dessine le pan droit
color("hsl(0 80.7% 56.8%)")
fillcolor("hsl(0 80.7% 56.8%)")

begin_fill()
right(45)
forward(60)
left(135)
forward(profondeur)
left(45)
forward(60)
left(135)
forward(profondeur)
end_fill()

#on se place pour la porte
penup()
left(90)
forward(40)
right(90)
forward(hauteur)
right(90)
forward(largeur - 20)
pendown()

#on trace la porte
color("hsl(14 67.8% 28.7%)")
fillcolor("hsl(14 67.8% 28.7%)")

begin_fill()
right(90)
forward(30)
right(90)
forward(40)
right(90)
forward(30)
right(90)
forward(40)
end_fill()


#on se place pour la ligne de fenêtres
penup()
forward(20)
right(90)
forward(50)
right(90)
forward(espacement_fenetres)
pendown()

#ligne de fenêtres
color("hsl(191 39.5% 82.2%)")
fillcolor("hsl(191 39.5% 82.2%)")

for _ in range(nombre_fenetres):
    begin_fill()
    forward(largeur_fenetres)
    left(90)
    forward(30)
    left(90)
    forward(largeur_fenetres)
    left(90)
    forward(30)
    left(90)
    end_fill()

    # on oublie pas l'espacement 
    penup()
    forward(espacement_fenetres + largeur_fenetres)
    pendown()

done()

Pro tip : réflexion sur papier

Des fois, ça peut être intéressant de réfléchir un peu en dehors du code, par exemple sur une feuille de papier.

Par exemple quand il y a des maths.

  • Faire des schémas
  • Réfléchir avec des formules etc...

Mais attention, il ne faut pas abandonner l'essai-erreur que j'avais introduit dans un des premiers pro tips pour autant. Si vous commencez à stagner sur le papier, n'hésitez pas à tester vos idées incomplètes dans le code !

Activité : formule du nombre de fenêtres

On veut trouver la formule qui donne, étant donné une largeur de fenetre et un espacement de fenetre, le plus grand nombre de fenêtres qui tiennent dans une largeur donnée.

Vous l'avez deviné, cette activité comporte ... des maths . Elle propose donc deux modes :

  • Le mode "maths" vous amène trouver la formule par vous même, avec un guidage limité.
  • Le mode "moins maths" vous propose de comprendre la formule, mais sans trop la chercher.

Première étape : formule de largeur

Soient :

  • \(F\) la largeur d'une fenêtre
  • \(E\) l'espacement entre les fenêtres (et les murs)
  • \(N\) le nombre de fenêtres.

Donnez l'expression de \(L\), la largeur des \(N\) fenetres et leurs espacements.

Solution

La largeur des fenêtres est : \(F \times N\)

La largeur des espacements est \(E \times ( N + 1)\). Avec \(N-1\) espacements entre les fenêtres, et 2 espacements de chaque côté pour les murs.

On a donc :

\[L = F \times N + E \times (N + 1)\]

On peut factoriser la formule en

\[L = (F + E) \times N + E\]

Deuxième étape : formule du nombre

Appliquez les règles de résolution d'equation sur l'expression de l'étape précédente pour isoler \(N\).

Solution

Pour isoler \(N\), on part de :

\[L = (F + E) \times N + E\]

On commence par transférer le \(+E\) :

\[L - E = (F + E) \times N\]

On transfère ensuite le \(\times (F + E)\) :

\[\frac{L - E}{F + E} = N\]

Et voilà !

Troisième étape : chuuuut !

Utilisez la formule de l'étape précedent pour calculer le nombre de fenêtres :

  • Avec une largeur de 30
  • Et un espacement de 20
  • Dans une largeur totale de 200

Expliquez pourquoi le résultat est erronné. Quel nombre faut il utiliser à la place ?

Solution

Le calcul est assez simple :

\[ \frac{200 - 20}{30 + 20} = 3.6 \]

Ce résultat est erronné parce que le nombre de fenêtre est forcément un entier. On dit qu'il est discret (c'est pour ça que l'activité s'appelle "chuuuut !").

Il faut donc utiliser un nombre entier à la place. On choisit donc l'entier inférieur (parce que le supérieur fait dépasser).

On peut donc mettre 3 fenêtres dans cette configuration.

Première étape : formule de largeur

Soient :

  • \(F\) la largeur d'une fenêtre
  • \(E\) l'espacement entre les fenêtres (et les murs)
  • \(N\) le nombre de fenêtres.

\(L\), largeur totale de l'ensemble des fenêtres et des espacements, est donnée par :

\[L = (F + E) \times N + E\]

Dessinez, sur un schéma, à quoi correspondent les termes (Les lettres quoi) de cette formule.

Solution

schema formule

Seconde étape : isoler N

On peut réécrire la formule comme suit :

\[N = \frac{L - E}{F + E}\]

Expliquez pourquoi cette forme, qui isole N, est plus pratique pour nous.

Solution

La formule où L est isolée permet de calculer facilement la largeur totale d'un nombre de fenêtres.

La formule où N est isolée permet de calculer facilement, pour une largeur totale, le nombre de fenêtres qui tiennent dans cette largeur.

C'est cette deuxième option qui nous intéresse.

Troisième étape : arrondi

Si on utilise la formule de l'étape précédente :

  • Avec une largeur de 30
  • Et un espacement de 20
  • Dans une largeur totale de 200

Ca nous donne :

\[ \frac{200 - 20}{30 + 20} = 3.6 \]

Expliquez pourquoi la réponse à notre problème est 3 (arrondi à l'inférieur) et non 3.6.

Solution

On ne peux avoir qu'un nombre entier de fenêtres, puisque 0.6 fenêtres n'a pas vraiment de sens.

Donc on prends l'entier inférieur. (parce que l'entier supérieur a une largeur totale trop grande)

Activité : calcul automatique du nombre de fenêtres

Utilisez la formule de l'activité précédente pour calculer automatiquement le nombre de fenêtres dans le code de la grange.

Lancez bien votre code avec plusieurs largeurs pour vérifier qu'il marche !

En Python, l'opérateur // (division entière) combine une division suivie d'un arrondi :

opérateur description exemples
A // B Division entière de A par B 10 // 10, 3 // 2, 7 // 2`
7 // 2 # vaut 3

On peut aussi utiliser des parenthèses, comme en math, pour la priorité des opérations :

(3 + 2) * 10 # vaut 50
Solution

Seule une ligne est modifiée, on applique juste la formule.

\(L\) est la largeur totale qu'on ne veut pas dépasser, c'est à dire la largeur de la maison.

# N             = (   L    -          E         ) /  (       F         +          E         )
nombre_fenetres = (largeur - espacement_fenetres) // (largeur_fenetres + espacement_fenetres)

Voici le code complet, au cas où :

from turtle import *
speed(0)

largeur = 150
hauteur = 100
profondeur = 60

largeur_fenetres = 30
espacement_fenetres = 30
nombre_fenetres = (largeur - espacement_fenetres) // (largeur_fenetres + espacement_fenetres)

# On se déplace pour centrer la maison

left(180)
forward(largeur/2)
left(90)
forward(hauteur / 2 + profondeur / 2)
#on oublie pas de se réorienter correctement
left(90)

#face avant
fillcolor("hsl(33 42.5% 85.8%)")
color("hsl(33 42.5% 85.8%)")

begin_fill()
forward(largeur)
left(90)
forward(hauteur)
left(90)
forward(largeur)
left(90)
forward(hauteur)
end_fill()

#on se positionnne pour le dessus
penup()
left(180)
forward(hauteur)
right(90)
forward(40)
pendown()

#dessus
color("hsl(0 80.7% 63.5%)")
fillcolor("hsl(0 80.7% 63.5%)")

begin_fill()
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
left(90)
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
end_fill()

#pan gauche
color("hsl(0 80.4% 69.6%)")
fillcolor("hsl(0 80.4% 69.6%)")

begin_fill()
right(45)
forward(60)
right(135)
forward(profondeur)
right(45)
forward(60)
right(135)
forward(profondeur)
end_fill()

#on se positionne pour le pan droit

penup()
left(90)
forward(largeur - 40 * 2)
pendown()

#on dessine le pan droit
color("hsl(0 80.7% 56.8%)")
fillcolor("hsl(0 80.7% 56.8%)")

begin_fill()
right(45)
forward(60)
left(135)
forward(profondeur)
left(45)
forward(60)
left(135)
forward(profondeur)
end_fill()

#on se place pour la porte
penup()
left(90)
forward(40)
right(90)
forward(hauteur)
right(90)
forward(largeur - 20)
pendown()

#on trace la porte
color("hsl(14 67.8% 28.7%)")
fillcolor("hsl(14 67.8% 28.7%)")

begin_fill()
right(90)
forward(30)
right(90)
forward(40)
right(90)
forward(30)
right(90)
forward(40)
end_fill()


#on se place pour la ligne de fenêtres
penup()
forward(20)
right(90)
forward(50)
right(90)
forward(espacement_fenetres)
pendown()

#ligne de fenêtres
color("hsl(191 39.5% 82.2%)")
fillcolor("hsl(191 39.5% 82.2%)")

for _ in range(nombre_fenetres):
    begin_fill()
    forward(largeur_fenetres)
    left(90)
    forward(30)
    left(90)
    forward(largeur_fenetres)
    left(90)
    forward(30)
    left(90)
    end_fill()

    # on oublie pas l'espacement 
    penup()
    forward(espacement_fenetres + largeur_fenetres)
    pendown()

done()

Activité : centrage

Vu que c'est plus ou moins la dernière activité du chapitre, je vais un peu moins vous aider. N'hésitez pas à appeler votre prof si besoin pour vous débloquer.

Modifiez le code pour que le groupe de fenêtre soient centrées au milieu de la facade de la maison, peu importe la taille choisie.

grange fenetre

Solution

On peut remarquer que la largeur totale des fenêtres et des espacements est inférieure ou égale à la largeur de la facade de la maison.

On répartit alors cette différence de chaque côté, en décalant les fenêtres de sa moitié.

TODO schema ici ?

from turtle import *
speed(0)

largeur = 180
hauteur = 100
profondeur = 60

largeur_fenetres = 30
espacement_fenetres = 30
nombre_fenetres = (largeur - espacement_fenetres) // (largeur_fenetres + espacement_fenetres)
#ici, on calcule la largeur totale des fenetres
largeur_totale_fenetres = nombre_fenetres * (largeur_fenetres + espacement_fenetres) - espacement_fenetres
#et ici on calcule de combien on doit décaler pour le centrage.
centrage = (largeur - largeur_totale_fenetres) / 2

# On se déplace pour centrer la maison

left(180)
forward(largeur/2)
left(90)
forward(hauteur / 2 + profondeur / 2)
#on oublie pas de se réorienter correctement
left(90)

#face avant
fillcolor("hsl(33 42.5% 85.8%)")
color("hsl(33 42.5% 85.8%)")

begin_fill()
forward(largeur)
left(90)
forward(hauteur)
left(90)
forward(largeur)
left(90)
forward(hauteur)
end_fill()

#on se positionnne pour le dessus
penup()
left(180)
forward(hauteur)
right(90)
forward(40)
pendown()

#dessus
color("hsl(0 80.7% 63.5%)")
fillcolor("hsl(0 80.7% 63.5%)")

begin_fill()
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
left(90)
forward(largeur - 40 * 2)
left(90)
forward(profondeur)
end_fill()

#pan gauche
color("hsl(0 80.4% 69.6%)")
fillcolor("hsl(0 80.4% 69.6%)")

begin_fill()
right(45)
forward(60)
right(135)
forward(profondeur)
right(45)
forward(60)
right(135)
forward(profondeur)
end_fill()

#on se positionne pour le pan droit

penup()
left(90)
forward(largeur - 40 * 2)
pendown()

#on dessine le pan droit
color("hsl(0 80.7% 56.8%)")
fillcolor("hsl(0 80.7% 56.8%)")

begin_fill()
right(45)
forward(60)
left(135)
forward(profondeur)
left(45)
forward(60)
left(135)
forward(profondeur)
end_fill()

#on se place pour la porte
penup()
left(90)
forward(40)
right(90)
forward(hauteur)
right(90)
forward(largeur - 20)
pendown()

#on trace la porte
color("hsl(14 67.8% 28.7%)")
fillcolor("hsl(14 67.8% 28.7%)")

begin_fill()
right(90)
forward(30)
right(90)
forward(40)
right(90)
forward(30)
right(90)
forward(40)
end_fill()


#on se place pour la ligne de fenêtres
penup()
forward(20)
right(90)
forward(50)
right(90)
forward(espacement_fenetres + centrage)
pendown()

#ligne de fenêtres
color("hsl(191 39.5% 82.2%)")
fillcolor("hsl(191 39.5% 82.2%)")

for _ in range(nombre_fenetres):
    begin_fill()
    forward(largeur_fenetres)
    left(90)
    forward(30)
    left(90)
    forward(largeur_fenetres)
    left(90)
    forward(30)
    left(90)
    end_fill()

    # on oublie pas l'espacement 
    penup()
    forward(espacement_fenetres + largeur_fenetres)
    pendown()

done()

Félicitations, c'était pas si facile !

Le code commence à devenir très compliqué à gérer, tellement que ça en devient critique.

Donc si on veut faire un dessin complexe, il nous faut un outils pour gérer la complexité.

C'est l'objet du prochain chapitre : fonctions.

notes prof

jeux de mots avec boucle :

ca tourne en rond ca frise si ya pleins de boucles

-> par la suite, introduire les boucles, et remarquer qu'on peut carrément raccourcir le code ! -> Puis utiliser boucles pour dessiner plusieurs fenêtres.

-> A l'intro du prochain chapitre (fonctions), proposer un défi difficile et une introspection sur comment on pense le code en isolation, puis introduire fonctions, paramètres etc.

Extensions

n-gones

Activité : n-gone !

**Dessinez un polygone régulier paramétrisé : **

Son nombre de côtés est une variable nombre_cotes

La longueur de ses côtés est une variable également.

L'angle formé par les côtés d'un polygone régulier à nombre_cotes côtés est donné par la formule suivante :

angle_cotes = 180 - (360 / nombre_cotes)

La démonstration de cette formule est dans l'extension Angles d'un polygone régulier, au cas où vous voudriez y jeter un oeil par curiosité.

Solution
from turtle import *

nombre_cotes = 7
longueur_cotes = 70 

angle_cotes = 180 - (360 / nombre_cotes) #on calcule l'angle

#on utilise la variable dans la boucle
for _ in range(nombre_cotes): 

    forward(longueur_cotes)

    left(180 - angle_cotes)
done()

Angles d'un polygone régulier

TODO ajouter démo de pourquoi 180 - (360 / n)

Faire défiler des formes

TODO creer ca en activité

Activité : autre figure

Un des attraits de la génération paramétrique, c'est la surprise :

On écrit un programme

On lui donne des paramètres

On a la surprise du résultat

Pour illustrer, écrivez un programme comme suit :

Soit 
un nombre N
une distance L
Un angle A

on repete N fois :
    avancer de L
    tourner a gauche de A

Puis testez avec différentes valeurs de N, L et A.

Voici quelques valeurs que je trouve intéressantes :

N L A
50 200 154
50 190 88
50 190 91
100 200 100
100 200 140
100 200 170
50 100 50
50 100 73
25 100 73

Paréidolie

TODO ajouter activité sur le fait que la maison de l'intro ressemble un peu a un visage, et qu'on peut faire un même en faisant varier la hauteur ou la largeur de la maison (moi qui réussit l'exercice. Mon pote "prends pas la grosse tete" ma tete : ). Ptet renvoyer sur la DAO ? peut etre une remarque sur pourquoi la porte est décalée à gauche histoire d'éviter que ca ressemble trop a un dicateur allemand ?


  1. N'est-ce pas hilarant de dessiner un octogone dans Basthon ? ↩