La solution naïve
Imaginons que notre algoblob ne soit pas tout seul. Ils sont plusieurs ... La solution naïve, ce serait de nommer les variables en ajoutant un nom ou un numéro devant chaque variable
abscisse1 = 10
abscisse2 = 20
abscisse3 = 50
Il est assez évident de voir qu'une telle solution n'est pas viable. Il faudrait changer le nombre de variables à chaque fois que l'on ajoute ou l'on enlève un algoblob, sans compter les copier coller pour les déplacements.... Il y a mieux : nous allons utiliser des listes
Vous vous souvenez ? Nous avions vu comment utiliser des listes pour voir la vie en couleur avec nos algoblobs. Nous avions utilisé une liste de couleurs. Et si nous utilisions des listes pour stocker les caractéristiques de nos algoblobs ? Une liste contiendra les abscisses, une liste contiendra les ordonnées, etc. Mais pour pouvoir travailler, il nous faudra parcourir nos listes.
Parcourir une liste
Ce qui est intéressant avec une liste, c'est que l'on peut parcourir une liste pour effectuer des opérations sur chaque élément de la liste. Faire des actions répétitives est au cœur de l'informatique.
la boucle for
Pour effectuer une action répétitive sur une liste, on utilise la boucle for. La syntaxe est assez simple.
maListe=['carotte','patates','chou','navet','haricot']
for legume in maListe :
print(legume)
Lorsque l'on effectue la boucle for, la variable legume
va prendre successivement toutes
les valeurs des éléments de la liste et effectuer les instructions qui sont dans le bloc de code
indenté en dessous.
Vous n'aimez peut être pas le navet ? Reprenez le programme au dessus et modifiez afin que, au lieu d'afficher juste le nom du légume, il affiche j'aime bien ce légume : ..., sauf pour le navet ou vous devez afficher Je n'aime pas ce légume : .... Bien entendu, il faudra utiliser une condition.
Plus fort... nous allons utiliser une seconde liste. Celle des légumes que vous n'aimez pas.
Il est possible de poser une condition sur l'appartenance à une liste ou pas. Le mot clef
in
a en effet deux usages :
- pour parcourir une boucle lorsqu'il est associé au mot clef
for
, par exemplefor legume in maListe :
-
pour déterminer l'appartenance à une liste s'il est associé à un test avec
if
ouelif
, par exempleif legume in listePasBon :
reprenez le programme au dessus. Étendez la liste des légumes de base. Créer une seconde liste que vous appelerez "listePasBon" et dans laquelle vous mettrez les légumes que vous n'aimez pas. Modifiez ensuite le programme pour qu'il affiche la liste de tous les légumes en précisant pour chacun si vous aimez ou non ce légume (et pas seulement le navet)
Seconde façon d'utiliser la boucle for
Il y a une seconde façon d'utiliser la boucle for. On peut utiliser une liste particulière,
qui est créé par l'appel à la fonction range
. Cette fonction va faire une liste
particulière qui est une liste d'entier (en fait, c'est plus compliqué, c'est un itérateur,
mais on va faire comme ci ...). Pour parcourir notre liste, on va pouvoir utiliser les indices
comme dans le code ci dessous. Notez que range(n)
donne n nombres entier,
en commençant à 0 et en finissant à n-1 (donc range(10)
va de 0 à 9)
On va aussi se servir de la fonction len
qui retourne la longueur d'une liste (abbréviation de length).
- Éxécutez le programme.
- On pourrait aussi afficher la position dans la première boucle, mais en ajoutant une variable que l'on modifie au fur et à mesure Essayez de le faire
Mais pourquoi faire
Vous allez me dire que ... ce n'est pas très intéressant de pouvoir ajouter juste un numéro devant un élément de la liste. Mais il faut penser dans l'autre sens. Il faut penser à la création des éléments d'une liste. Par exemple, si nous voulons créer une liste qui contient les carrés des nombres de 1 à 12, cela sera assez facile
maListe = []
for i in range(12) :
nombre = i+1 # i va de 0 à 11
maListe.append( nombre * nombre )
Au passage, on pourrait s'éviter le décalage en utilisant la fonction range avec un départ (inclus) et une arrivée (exclue) :
maListe = []
for nombre in range(1,13) :
maListe.append( nombre * nombre )
Et là, on se rend compte de l'intérêt de cette démarche : on va pouvoir remplir une liste de façon automatisée.
Notez bien qu'il serait aussi possible d'utiliser une boucle while
avec un compteur.
On ne le fait généralement pas car cela nécessite de rajouter une variable que l'on controle,
là où la boucle for
combiné au range
effectuera ces opérations pour nous.
Ils se multiplient !
Et c'est bien ce que nous voulons faire : nous voulons que nos algoblobs se multiplient. Qu'il n'y en ait plus un seul, mais plusieurs ! Disons une douzaine par exemple. On va reprendre le code que l'on avait avant, mais au lieu d'avoir des variables, nous allons avoir des listes de variables et nous allons les parcourir.
- Dans votre éditeur Python, reprenez le dernier fichier que nous avions où l'algoblob se déplaçait. Il est reproduit ci dessous, vous pouvez le copier si besoin
- au lieu des variables abscisse, ordonnee,vitesseX,vitesseY, créer 4 tableaux vides correspondant à ces 4 éléments caractéristiques
- Faites une boucle pour remplir ces 4 tableaux avec pour chacun 12 éléments,
qui correspondront aux 4 caractéristiques (x,y,vx,vy) de nos 12 blobs.
- La vitesse sera aléatoire comme actuellement
- l'abscisse sera aléatoire en utilisant
uniform(0,largeur)
- l'ordonnee sera aléatoire en utilisant
uniform(0,hauteur)
-
modifier ensuite toute la partie qui est en dessous de
background(0)
pour que les instructions soient toutes dans une boucle qui va parcourir les 12 valeurs des 4 tableaux pour afficher et faire se déplacer nos 12 blobs. - Éxécutez le programme et savourez ce foisonnement d'algoblob. Non seulement ils sont vivants, mais vous les avez multipliés !
- Bonus : vous pouvez aussi transformer le rayon en tableau et avoir des rayons aléatoires.
from p5 import *
from random import uniform
largeur,hauteur = 500, 500
abscisse, ordonnee, rayon = 250, 250, 20
vitesseX, vitesseY = uniform(-5,5), uniform(-5,5)
if vitesseX == 0 and vitesseY == 0:
vitesseX = 1
def setup():
size(largeur,hauteur)
def draw():
global abscisse, ordonnee, vitesseX, vitesseY
background(0)
circle(abscisse,ordonnee,rayon)
abscisse = abscisse + vitesseX
ordonnee = ordonnee + vitesseY
if abscisse > largeur :
abscisse = largeur
vitesseX = - vitesseX
if abscisse < 0 :
abscisse = 0
vitesseX = -vitesseX
if ordonnee > hauteur :
ordonnee = hauteur
vitesseY = -vitesseY
if ordonnee < 0 :
ordonnee = 0
vitesseY = - vitesseY
run()
Voilà, nos algoblobs sont nombreux et ils évoluent librement ... dans l'espace qui leur est alloué. Et la suite ? Ce n'est quand même pas très pratique ces tableaux qui trainent dans un peu tous les sens. On va essayer de regrouper les données en utilisant une autre structure composée : les dictionnaire. Les informations sur chaque algoblob seront stockées dans un dictionnaire, et notre liste des algoblobs sera juste une liste de dictionnaires.