Profitez-en, après celui là c'est fini

Processing, septième cours

novembre 27th, 2008 Posted in Processing

Le fonctionnement (et l’intérêt) des ordinateurs repose sur assez peu de fonctions, finalement : effectuer des calculs numériques, accéder à des valeurs (écrire, lire, modifier), tester des conditions et enfin répêter des actions. Tout le reste, ce qu’on nomme l’algorithmie (la combinaison de ces fonctions), en découle.
Nous allons donc à présent nous pencher sur les boucles (loop en anglais), ou itérations, qui permettent donc de répéter une action.
Processing en connaît manipule deux types, les boucles conditionnelles et les boucles itératives.

Les boucles conditionnelles

La syntaxe d’une boucle conditionnelle, qui sera familière à tous les programmeurs (C, C++, Java, Actionscript,…), est la suivante : while (condition) { instructions }, où « condition » est la propriété à tester et « instructions » est l’ensemble de commandes. C’est, typiquement, avec ce genre de commande mal invoquée que l’on bloque un programme. Par exemple si j’écris while(1==1){ print(« ok »); }, l’exécution du programme n’aura aucune raison de quitter la boucle puisque la condition testée (est-ce que 1 est égal à 1 ?) ne deviendra jamais fausse. Avec Processing, ce genre de boucle infernale n’est pas fatale et impose, au pire, de quitter le programme, mais la plupart du temps, lorsque l’ordinateur « plante », c’est qu’un de ses programmes importants est tombé sur une boucle infinie de ce type.
Voici une boucle au résultat aléatoire mais, a priori, contrôlé :

while(random(100)<95){
   point(random(100),random(100));
}

Ce qui, en clair, signifie que nous alons tirer un nombre au hasard entre 0 et 100. Si ce nombre est inférieur à 95, le programme dessinera un point n’importe où dans la fenêtre d’affichage, puis refera un tirage au hasard entre 0 et 100. Il est tout à fait possible que le premier nombre tiré soit, par exemple, 96. Dans un tel cas, la condition qui nous permet de quitter la boucle sera remplie dès le départ et l’instruction (dessiner un point n’importe où) ne sera pas exécutée. Il est aussi possible que l’ordinateur, taquin, ne veuille jamais produire le moindre nombre au hasard qui excède 94.9999… ce qui aurait pour résultat de nous laisser coincés dans notre boucle. Heureusement, les probabilités, même avec le hasard très imparfait de l’ordinateur, font que nous avons une chance sur 20 de dépasser le nombre 95 et donc, de quitter la boucle. Voici le résultat de cinq lancements différents du programme :

Les boucles itératives

La syntaxe des boucles intératives est un peu barbare de prime abord et nous force à nous pencher sur les variables. Voici un exemple typique de boucle itérative :

for(int a=0; a<100; a+=4){
   line (a,0,a,100);
}

Le résultat est l’image que vous voyez à droite : une ligne a été tracée tous les quatre pixels.
On peut traduire notre boucle ainsi :
1) Départ : Créer une variable nommée a et dont la valeur de départ est 0 (zéro). Je lui ai donné le nom a car tel est mon bon plaisir, mais elle aurait aussi bien pu se nommer ornithorynque.
2) Boucle : Si la valeur de a est inférieure à 100, alors
-a) dessiner une ligne entre les points (a,0) et (a,100)
-b) incrémenter a de 4 (a+=4 signifie que a doit devenir égal à a+4)
3) Revenir au début de la boucle si sa condition (a<100) est remplie. Sinon, le programme est terminé.

Dans notre cas, a prend les valeurs successives de 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92 et 96.

La syntaxe précise est donc :
for ( départ ; condition pour rester dans la boucle ; itération ) { instructions }
Ce n’est pas très beau à lire, d’autant que c’est le seul cas où on utilise des points-virgule pour autre chose que pour terminer une commande, mais on s’y fait car la syntaxe est la même dans un grand nombre de langages de programmation.

On peut par ailleurs imbriquer des boucles dans les boucles, ce qui est particulièrement intéressant pour dessiner des images, qui sont en deux dimensions. Si je veux parcourir tous les pixels de mon image un a un et, par exemple, y dessiner un point d’une couleur tirée au hasard, je peux le faire avec des boucles imbriquées. Cette fois, au lieu d’utiliser des variables nommées a, b, c ou ornithorynque, je vais utiliser des variables nommées d’une manière qui reflète leur usage, à savoir colonne et rangee (sans accent).

for(int colonne=0; colonne <100; colonne++){
  for(int rangee=0; rangee <100; rangee++){
     stroke(random(255));
     point(colonne, rangee); 
  }
}

La première boucle s’applique à une variable nommée colonne qui va avoir toutes les valeurs possibles entre 0 et 100. Pour chacun de ces états, une seconde boucle s’appliquera à une variable nommée rangee qui aura elle aussi toutes les valeurs possibles entre 0 et 100.
Ceci fait que la commande stroke (changer la couleur du trait) et la commande point (dessiner un point) seront exécutées 100 x 100 fois, c’est à dire 10 000 fois. Dans l’exemple ci-contre, la couleur appliquée aux pixels de l’image est un niveau de gris.
L’étrange ++ signifie que l’on augmente la variable de 1. Ainsi, « a++ » est synonyme de « a=a+1 », et réciproquement on peut écrire « a– » mais aussi « a-=1 » au lieu de « a=a-1 ». La notation des opérations arithmétiques sur des variables peut être un peu déroutante de prime abord. On s’y fait rapidement :

  • a++ : augmenter a de 1
  • a+=1 : augmenter a de 1
  • a=a+1 : augmenter a de 1
  • a-– : décrémenter a de 1
  • a-=1 : décrémenter a de 1
  • a=a-1 : décrémenter a de 1
  • a*=2 (ou a=a*2) : multiplier a par 2
  • a/=5 (ou a=a/5) : diviser a par 5

Les boucles ne sont pas ce que les débutants en programmation comprennent le mieux, ni ce que j’explique le mieux. Il s’agit néanmoins d’un outil extrèmement pratique.
Supposez que vous vouliez réaliser un motif de 530×120 pixels où un petit cercle blanc est dessiné tous les 10 pixels, comme ceci :

… Avec un logiciel de dessin comme Gimp ou Photoshop, c’est tout à fait possible, par un jeu de copier-coller laborieux. Une erreur est vite faite et c’est tout de même assez long. Pour Processing, ce programme suffit :

size(530, 120);smooth();noStroke();fill(255);
background(0);
 for(int x=0;x<53;x++){
  for(int y=0;y<12;y++){
    ellipse(5+x*10,5+y*10, 4, 4);
  }
}

Mais à présent, imaginez que vous vouliez obtenir ce même motif en appliquant à chacun de vos petits cercles de 4 pixels un décalage aléatoire de plus ou moins un pixel, comme ceci :

L’impression d’irrégularité ordonnée serait difficile à obtenir manuellement, une fois encore.
Cette fois, le programme sera :

size(530, 120);smooth();noStroke();fill(255);
background(0);
 for(int x=0;x<53;x++){
  for(int y=0;y<12;y++){
    ellipse(5+x*10+random(-1,1),5+y*10+random(-1,1), 4, 4);
  }
}

L’utilité permanente des boucles fait que nous les reverrons souvent dans les articles ultérieurs. Nous verrons aussi une autre forme de boucle, la boucle temporelle, qui nous permet d’exécuter une action n fois par seconde.

Notez que pour s’extraire d’une boucle avant qu’elle ait fini de s’exécuter, on écrit ceci : break;

  1. 3 Responses to “Processing, septième cours”

  2. By david t on Nov 27, 2008

    ah, ça commence à devenir intéressant! je regarderai ça plus tard, là faut quand même que je travaille un tout petit peu. :) mais bravo pour ce travail, vraiment beaucoup plus profond que ce à quoi je m’attendais.

  3. By criquet on Oct 17, 2009

    Tout a fait je suis daccord avec david t

  4. By OP on Mai 3, 2011

    la première fois que je mémorise clairement ce que j’apprends avec un tuto
    explications simples et limpides
    merci++

Postez un commentaire


Veuillez noter que l'auteur de ce blog s'autorise à modifier vos commentaires afin d'améliorer leur mise en forme (liens, orthographe) si cela est nécessaire.
En ajoutant un commentaire à cette page, vous acceptez implicitement que celui-ci soit diffusé non seulement ici-même mais aussi sous une autre forme, électronique ou imprimée par exemple.