Découvrir le python – Chapitre 2 – Diamonds in the skaaaaaaye

Wèèèèèsh lecteurtrice !! Bien ou bien ?

T’as lu mon article précédent et t’as grave kiffé au taquet de ouf’ ? Sois jouasse, en rev’là une gorgée !

Avant qu’on s’y remette, j’espère que t’as fait tes devoirs, ou que t’as au moins essayé.

Si ce n’est pas le cas, ce n’est pas grave, je vais simplement prévenir mes robots correcteurs. Ils te jetteront du sable fin sur les sourcils, puis te pendront par les pieds et te fouetteront jusqu’à ce que tes larmes aient entièrement nettoyé tes sourcils.

Voici la solution du devoir, avec plein de commentaires qui expliquent comment c’est gaulay.

Un diamant

Let’s go sur un truc simple pour commencer. Retourne dans Trinket, ton bel environnement de dev, enlève le programme initial et ajoute les deux lignes habituelles au début : « import turtle », « turtle.speed(0) ». On va commencer simple, tu vas me dessiner un diam’s.

♫ C’est le python qui va dicter ton code. ♪ Génération Oui-Oui. ♬♪

Un diamant, c’est quatre quarts de cercle. Sauf qu’après chaque quart, la tortue fait demi-tour, pour changer le sens de tracé du quart suivant.

On n’est pas des prolos et on veut un gros diam, alors tu me fais des quart de cercles de 100 pixels de rayon. Tu as le droit de le réaliser d’abord à la crade, c’est à dire en copiant-collant 4 fois le même morceau de programme. Mais ensuite, tu me met ça sous forme d’une boucle.

Tu devrais réussir à bling-blinguer un diamant cossu comme ça :

Lien vers la réponse si tu as du mal à te remettre dans la vibe.

Laissez-moi vos coordonnées

Si tu as fait quelques années d’école, lecteurtrice, tu as sûrement placé des points sur une feuille, pour faire un graphique ou pour tracer une droite. Tu utilisais alors des coordonnées : un nombre en X, un autre en Y.

Si tu es Muriel Robin, lecteurtrice, tu pourrais faire la blague « laissez-moi vos cordonniers, je vous rappellerais », et tu aurais été super drôle, pour l’époque.

La tortue se déplace dans un espace défini par des coordonnées. Cet espace est orienté de la même manière qu’en cours de maths :

  • La coordonnée (0, 0) correspond au milieu de la zone de dessin.
  • Lorsqu’on va vers la droite, la première valeur (le X) augmente, elle diminue lorsqu’on va vers la gauche.
  • Lorsqu’on va vers le haut, la deuxième valeur (le Y) augmente, elle diminue lorsqu’on va vers le bas.

C’est pas du tout orienté selon les conventions habituelles en informatique. On va pas s’attarder là-dessus pour l’instant, sinon je vais encore traiter les matheux de ringards.

La fonction « turtle.setpos » permet de positionner la tortue à des coordonnées données (Wesh, lecteurtrice ! « coordonnées données » ça fait une répétition lolilol !).

Voici un lien vers la doc de la fonction.

Au début de ton programme, ajoute un setpos pour positionner la tortue aux coordonnées X = -40, Y = +30.

Le déplacement va dessiner un trait moche. On réglera ça au chapitre suivant.

Mais avant, tu vas mettre ces coordonnées dans deux variables, intitulées « pos_x » et « pos_y ». Tu te souviens de ce qu’est une variable ?

Au début du programme, tu définis la variable « pos_x » à -40 et la variable « pos_y » à 30.

Ensuite, dans l’instruction « turtle.setpos », tu n’utilises plus directement les valeurs -40 et 30, mais les deux variables que tu viens de définir.

Pour l’instant, ces variables servent à R (Wesh lecteurtrice, langage de jeune !!), mais ce sera utile très bientôt.

Lien vers le code, si t’en chie.

Attention, les majuscules-minuscules sont importantes. « pos_x » et « Pos_x », ce n’est pas la même chose.

Les conventions de codage en python conseillent d’écrire les noms de variables tout en minuscules. Lorsqu’un nom est composé de plusieurs mots, on les sépare par des « _ » (le tiret bas). Un jour, jeune programmeurtrice dont les poils n’ont pas encore poussés, je te parlerai plus en détail de la notion de « convention de codage » et du PEP-8.

Si t’as envie d’appeler tes variables « posx » et « posy », t’as le droit, tu fais tout qu’est-ce que tu veux, c’est ta création, c’est bonheur. Il faudra juste que tu t’en rappelles, parce que dans la suite de l’article je continue de les appeler « pos_x » et « pos_y ».

Il n’est pas rare de s’over-prendre la tête en boucle pendant des heures sur la manière de nommer une variable.

Up and Down

C’est trognon ces variables, mais ça règle pas le problème du trait dégueubeurk que fait le setpos.

Je te donne juste le nom des deux fonctions permettant de régler le problème : « turtle.penup », « turtle.pendown ». Tu te débrouilles pour savoir ce que ça fait, comment ça marche, est-ce que ces fonctions ont besoin de paramètres, où les appeler, etc. Peut-être que tu peux commencer par les taper dans un moteur de recherche.

Tu regardes des docs et des exemples de code, tu testes dans ton programme, si ça fait des trucs pétés, tu testes autre chose. Azy lecteur, fais pas ta tafiolle, azy lectrice, fait pas ton tafiot (Wesh lecteurtrice, t’as vuuuu ? Écriture inclusive sur le mot « tafiolle » !)

Quand tu auras réussi, ça fera le même diam’s qu’au tout début, mais sans le trait moche.

Lien vers la réponse, si t’es au bout de ta vie.

Tout ça pour ça ? Je t’entends penser d’ici : « you you foutay de magl, ou bien ? ».

Ne brûle pas cet article tout de suite lecteurtrice, la suite est plus intéressante.

lofteurs.up() and lofteurs.down()

Pléthore de diam’s

Ce serait le top de la bling-bling-itude de pouvoir dessiner des diamants où on veut. Mais pas en copiant-collant le code, sinon ce serait le top de la cra-cra-itude. Alors on va créer une fonction.

Tu ne sais pas ce qu’est une fonction ? Eh bien si. Tu en utilises depuis le début : « print », « turtle.circle », « turtle.penup », … Maintenant, tu vas en créer une nouvelle qui sera rien qu’à toi.

Lorsqu’on crée une fonction, on lui associe un bloc de code, qu’on appelle le corps de la fonction. Comme tu as bien retenu la leçon précédente, tu sais déjà que ce bloc peut éventuellement contenir des sous-blocs, sous-sous-blocs, etc.

Ensuite on exécute la fonction (on peut aussi dire « appeler la fonction »), ce qui revient à exécuter son corps. Ça fait très bizarre de dire « exécuter son corps », alors dites-le uniquement dans votre tête, d’à-corps ?

Tu vas donc me créer une fonction, sans paramètre, intitulée « dessiner_diams ». Dans le corps, tu mets ce que tu as déjà écrit, depuis « turtle.penup » jusqu’à la boucle dessinant les quarts de cercle. Tu n’y mets pas l’initialisation des variables pos_x et pos_y, c’est fait exprès.

Voilà un lien de doc qui pourra t’aider : https://courspython.com/fonctions.html, à lire jusqu’au chapitre « Fonction avec paramètre ». Cela dit, les chapitres d’après peuvent t’aider pour la suite, et c’est assez bien expliqué. Y’a juste pas de fun, contrairement à mes articles qui regorgent d’espiègleries toutes pailletées de saveurs foisonnantes prestige t’as vu wesh ?

Seulement voilà. Si t’exécutes ton code là maintenant, t’auras queud’. Zéro diams. Retour à l’âge de prolétaire.

C’est normal, il faut appeler la fonction que tu as créée. À la fin du programme, ajoute « dessiner_diams() », et re-bling-bling !

Si tu appelles plusieurs fois de suite la fonction, ça ne changera pas le dessin final, car tu dessines plusieurs fois au même endroit.

Or, la fonction utilise les variables pos_x et pos_y pour se positionner avant de dessiner. Il suffit donc de les modifier puis de re-appeler la fonction.

Tant qu’on y est, tu vas ranger un peu ton code. En général on met les imports au début, puis la définition des fonctions, puis le code principal. Ça va donc donner un truc comme ça :

import turtle
# Cette ligne, y'a qu'à la laisser au tout début.
turtle.speed(0)

# Ici, il y a la définition de la fonction "dessiner_diams"

# Ensuite, la définition des variables pos_x et pos_y, 
# avec les mêmes valeurs qu'avant : -40 et +30

# Appel de la fonction.
dessiner_diams() 

# On redéfinit les variables pos_x et pos_y, 
# avec, disons : pos_x = 10 et pos_y = 60

# Re-fonction.
dessiner_diams()

Et ça devrait donner deux diamants, à deux endroits différents :

Lien vers la réponse, si t’es en PLS.

Avec des paramètres

On a fait un truc bizarre dans le chapitre précédent. On a utilisé les variables pos_x et pos_y à l’intérieur d’une fonction, alors qu’on ne les a pas définies dans la fonction elle-même. Ça n’a pas planté, grâce à la manière dont le langage python gère la portée des variables.

  • Ton programme principal est dans un certain contexte, avec des variables.
  • Tu exécutes la fonction « dessiner_diams », qui se crée un petit sous-contexte pour elle toute seule, avec ses variables.
  • Le python autorise l’accès aux variables d’un contexte englobant, mais uniquement en lecture.

Tu verras peut-être, dans les différents tutoriels du grand internet, les notions de « variables globales » et « variables locales ». C’est à peu près la même chose, mais je n’aime pas trop ces termes, car ça donne l’impression qu’il n’y a que deux contextes, alors qu’il peut y en avoir bien plus.

Je vais pas trop t’embrouiller avec des choses que t’as pas encore vues. Un module possède lui aussi un contexte. D’autre part, tu peux déclarer une fonction dans une fonction, ce qui crée un sous-sous-contexte, et une fonction dans une fonction dans une fonction. Et en plus ça s’appelle pas des contextes mais des « espaces de nommage ». Oublions tout ce batacouac.

Y’a des fois, c’est justifié d’accéder à une variable du contexte englobant, mais là non, c’est pourri.

Déjà, parce que ça oblige à écrire trois lignes de code pour dessiner un diamant où on veut : deux lignes pour pos_x, pos_y, et la dernière pour la fonction. Et ensuite ça fait bizarre, car le comportement de la fonction dépend de choses extérieures à elle. C’est inhabituel, alambiqué, complexe et source de bugs.

Alors on va ajouter deux paramètres à la fonction. Devine comment on va les appeler ? pos_x et pos_y. Hu hu hu.

Il faut ajouter ces paramètres dans la définition de la fonction (la ligne de code avec le mot-clé « def »), ainsi qu’à chaque exécution de la fonction.

Tu n’as plus besoin des lignes de code définissant les variables pos_x et pos_y. Tu peux mettre les coordonnées directement dans les paramètres d’appel à la fonction. Tiens voilà un exemple issu de la même doc que tout à l’heure . Ne t’attardes pas sur le corps de la fonction, osef. Regarde juste comment elle est déclarée, comment elle est appelée, et tu fais le même genre de chose avec ta fonction à toi.

Tu peux faire un petit test pour bien te rendre compte que les paramètres pos_x et pos_y existent dans l’espace de la fonction, mais plus en dehors. Ajoute « print(pos_x) » à la fin de ta fonction. Ça va fonctionner. Ajoute la même ligne tout à la fin de ton programme, ça va merdoyer.

C’est ce qu’on veut, lecteurtrice. Chaque variable et chaque paramètre doit être présent uniquement là où on en a besoin, et ne pas être accessible ailleurs. Sinon ça embrouille, on se demande ce que ça fout là, et on passe pour une baltringue ou un baltringuet (Wesh ! Écriture inclusive !).

Pour finir ce chapitre sur quelque chose d’over-classe, tu mets une boucle de 20 itérations dans laquelle tu exécutes ta fonction. Pour ses deux paramètres, indique directement le compteur de la boucle.

Ça va faire un truc comme ça :

Lien vers le code si t’as vomi ton cerveau.

On taille les diamants

Maintenant que tu as compris le truc avec les paramètres de fonctions, profitons-en pour en rajouter un troisième, permettant de choisir la taille du diamant.

C’est à peu près comme au chapitre précédent :

  • Ajoute un paramètre dans la définition de la fonction, après pos_x et pos_y. On l’appellera « taille ».
  • Utilise ce paramètre dans le corps de la fonction. Ça va se passer dans la ligne de code « turtle.circle(100, 90) »
  • Ajoute le paramètre lors de l’exécution de la fonction. Dans un premier temps, tu peux indiquer une valeur fixe. Le plus simple est de remettre 100.

Avec ça, tu auras la même image que précédemment, mais ton programme sera plus souple, comme lui :

Modifie la boucle affichant les 20 diamants, en faisant varier leur taille, de 0 pixels (inclus) à 100 pixels (exclus), en avançant par pas de 5 pixels.

Et plop :

Lien vers la réponse si t’es pas de taille.

Recentrons-nous

Hé, j’ai une idée géniale. On pourrait afficher des diamants de taille différente, mais tous en coordonnées (0, 0). Ça ferait un truc trop joli, comme une espèce de porte des étoiles magiques en forme de vagin de l’espace.

Sans plus attendre, re-re-modifie la boucle exécutant la fonction, et indique 0 dans les deux premiers paramètres.

Et paf, c’est moche.

Qu’est-ce à dire que ceci ?

La fonction positionne la tortue aux coordonnées (pos_x, pos_y), puis commence tout de suite à dessiner.

Donc ces coordonnées ne correspondent pas au centre du diamant, mais à la pointe de gauche.

Avant de dessiner, il faut se décaler vers la gauche, d’une distance égale à la taille du diamant.

Y’a deux manières de le faire :

Soit tu te positionnes dès le départ où il faut, en changeant le premier paramètre de l’instruction turtle.setpos. Au lieu de « pos_x », tu mets « pos_x – taille ».

Soit tu laisses le setpos comme il est, mais juste après, tu recules de la taille du diamant. La fonction pour reculer, c’est « turtle.backward », elle fonctionne comme le forward.

Je te conseille fortement la deuxième option. Tu en auras besoin au moment de faire tes devoirs. Eh ouais, lecteurtrice, t’auras encore des devoirs. La vie est dure.

Après avoir appliqué le décalage, ça devrait dessiner ça :

Lien vers la réponse, si t’es déconcentré ou déconnecentrée (Wesh, écriture inclusive, t’as vuuuuuu ?)

Diamonds are a girl’s best friend

I have a good filling about this

On va momentanément partir sur autre chose.

Teste-moi ça, dans un autre onglet Trinket :

import turtle
turtle.fillcolor("red")
turtle.begin_fill()

turtle.forward(60)
turtle.left(120)
turtle.forward(60)
turtle.left(120)
turtle.forward(60)

turtle.end_fill()

Ça va dessiner un magnifique triangle rempli de rouge.

Explications :

  • La fonction fillcolor est assez simple : elle définit une couleur de remplissage. Tu peux remplacer « red » par « green », « blue » ou d’autres couleurs en anglais.
  • La fonction begin_fill indique à la tortue qu’on va commencer à tracer un dessin qui sera à remplir.
  • Ensuite, des forward et des left, que tu connais déjà.
  • Finalement, la fonction end_fill indique à la tortue qu’on a fini le dessin et que le remplissage doit être effectué.

Ce n’est pas forcément évident à comprendre. Ces fonctions de fill impliquent beaucoup de traitements réalisés en interne par le python.

Lorsque tu es entre un begin_fill et un end_fill, à chaque fois que tu traces un bout de truc, que ce soit avec un forward, un circle ou autre chose, la tortue enregistre tous les pixels par où elle est passée. Au moment du end_fill, la tortue en déduit l’espace interne de pixel délimité par ton tracé, et elle les colorie. Comme l’outil « pot de peinture » dans les logiciels de dessin, t’as vu ?

Pas besoin de te prendre la tête avec ces traitements compliqués, le python le fait tout seul (plus exactement, c’est la librairie de code turtle qui le fait, osef). Mais du coup, c’est pas évident de comprendre ce que ça fait.

On pourrait presque considérer que tout ce que tu fais entre le begin_fill et le end_fill constitue un sous-bloc de code. D’ailleurs, si ça ne tenait qu’à moi, j’aurais fait un context manager, et ça se serait explicitement écrit comme des sous-blocs de code. Un « context manager », c’est un truc spécial du python que tu peux mentionner quand tu veux montrer à tes lecteurtrices à quel point tu es un over-expert du python.

Et là, lecteurtrice, je me plaît à imaginer que tu t’intéresses à ce que je te raconte jusqu’au plus profond de tes neurones, et que donc tu te poses plein de questions :

  • Si je dessine n’importe quoi et que je ne reviens pas à mon point de départ, est-ce que ça va colorier toute l’image comme dans Paint ?
  • Si je croise des traits, ça va se colorier comment ?
  • Si je fais plusieurs begin_fill et/ou plusieurs end_fill à la suite, ça donne quoi ?

Réponse : t’as qu’à tester. Tiens, je t’ai fait quelques exemples.

Bon, ceci étant expliqué, je veux un diamant de sang ! Yaaahahahhaaarrrr !!

Modifie la fonction de façon à ce qu’elle dessine un diamant coloré en rouge. Il suffit d’ajouter les instructions de fill, aux bons endroits.

Ensuite, les diamants vont se dessiner en se recouvrant l’un après l’autre. À la fin, tu auras ça :

Lien vers la réponse, si tu commences à pleurer du sang.

Ce sera tout pour aujourd’hui

Dans mon article précédent, j’ai dit qu’on ferait ça :

On n’y est pas encore, mais on s’en rapproche. Je m’arrête là pour l’instant. J’ai d’autres trucs à faire que d’écrire des cours de python. Désolé. Promis, le mois prochain, on y arrive.

En attendant, pour pas que tu t’ennuies, BADAM-BING ! LES DEVOIRS !!!

Dessine-moi ça :

Petit indice : depuis le début, on dessine des diamants tout droit, parce que l’orientation initiale de la tortue est droite. Et si tu tournais un peu ta tortue avant de dessiner un diamant ? Pas trop, un ou deux degrés…

Découvrir la programmation python et faire des petits dessins, là tout de suite

Hey !

Alors comme ça tu veux essayer la programmation et tu ne sais pas par où commencer ? Tu as joué un peu avec des formules Excel et tu as trouvé ça relou ? Tu as pris peur devant la quantité faramineuse de case à cocher et de Giga-octets nécessaires à l’installation de Visual Studio ? On s’est moqué de toi quand tu as dit que le C++ était mieux que le HTML ? Allez, viens, t’as cliqué à la bonne porte. J’ai filé des cours de python à des jeunes en collèges et lycées, et j’ai presque eu l’impression d’avoir été intéressant. Autant t’en faire profiter !

Non-installation des outils nécessaires

Quand on débute en programmation, il faut s’inscrire sur des sites (github, stackoverflow, …), installer des interpréteurs, des compilateurs et un tas d’autres bronxs. Sauf que toi, tu veux pas forcément t’y mettre sérieusement, tu veux juste découvrir pour savoir si ça vaudra le coup de t’y mettre sérieusement. Tkt, lecteurtrice, je suis là pour ça.

Va voir par ici : https://trinket.io/python (ouvre le lien dans un nouvel onglet, car tu auras besoin de passer de l’un à l’autre).

C’est un petit environnement d’exécution en python, rien que pour toi. « Python » est le nom d’un serpent, mais aussi d’un langage de programmation.

Dans la partie gauche, c’est le code que tu écris, dans la partie droite, le résultat de l’exécution de ce code. T’as vu lecteurtrice ? J’ai utilisé le mot « code ». Ça veut dire exactement la même chose que « programme », mais ça fait plus expert. Hésite pas à utiliser ce mot.

Un premier exemple s’est déjà exécuté. On s’en fout. Efface tout le texte de la partie gauche et met seulement ces trois lignes :

import turtle
turtle.forward(50)
turtle.left(90)

En haut de la fenêtre se trouve un bouton « Play » (une flèche vers la droite), clique dessus. Si y’a pas, t’as un bouton « Stop » à la place, clique puis reclique dessus.

Devant tes yeux ébahis, un trait va se tracer.

Tant qu’à faire, clique sur le bouton « Expand » en bas de la fenêtre, ce sera plus pratique.

Mais que sont donc ces trois lignes que tu as copié-collées ?

La première sert à importer la librairie de code intitulée « turtle ». C’est ce qui te permet de tracer des petits dessins.

Si t’es un vieux ou une vieille, lecteurtrice, tu te souviens peut-être du plan « Informatique Pour Tous » et surtout du langage « Logo ». Turtle en est inspiré.

Le principe, c’est que la petite flèche noire dans la partie droite représente une tortue (ou n’importe quelle autre animal si tes goûts en matière de zoophilie sont différents). Tu la diriges avec des instructions de code.

  • « turtle.forward(50) » signifie que tu la fais avancer de 50 pixels.
  • « turtle.left(90) » signifie que tu la fais tourner de 90 degrés vers la gauche.

Juste pour montrer que tu as bien compris, tu vas changer le code pour me dessiner un beau carré de 50 pixels de côté. T’as juste à re-écrire trois fois de plus les deux dernières lignes. Fais un copier-coller, ça passe crême. Ne recopie pas « import turtle », qui n’a besoin d’être écrit qu’une seule fois au début. Appuie sur Play pour relancer le programme.

Ça y’est, t’imprimes ?

On peut aussi écrire du texte. À la fin de ton programme, ajoute la ligne :

print("yo ho ho ho. lolilol")

Le carré va se redessiner et du texte va s’afficher dans la partie juste en-dessous.

La fonction « print » affiche en bas à droite le texte que tu lui indiques. Ça s’appelle la sortie standard. C’est un truc de base que tu as tout le temps, même avec autre chose que le python.

En général, quand on découvre la programmation, on ne commence qu’avec ça, on ne dessine pas avec turtle. Du coup, on se retrouve à faire des exercices poucraves, genre pisser la suite de Fibona-qui-chie ou sortir la solution d’une équation du premier degré. C’est chiant. Nous on fais pas ça, nous on met des paillettes dans la life, t’as vu ?

Quand tu programmes, que tu sois débutant ou pas, il y a plein de fois où tu écris des trucs pétés qui déclenchent des erreurs. Ça fait partie du jeu. Dans le bel environnement de développement que je te propose, les erreurs s’affichent en bas de la fenêtre, et la ligne de code pétée est surlignée en rouge. On va tester ça tout de suite. Après le print, tu écris n’importe quoi. Vas-y lâche toi, fais pas ta/ton mijauré·e. (Wesh ! T’as vu lecteurtrice ? Je fais de l’écriture inclusive, c’est à la mode).

Appuie sur Play, et tu verras un message outrageusement irrespectueux, genre « NameError: nanani » ou « Bad input: nianiania ».

Les messages d’erreurs sont plus ou moins explicites, selon ton niveau de connaissance, la débilité que tu as écrite et la complexité de ton programme. Des fois ça peut aider de chercher sur internet ce que ça veut dire. Des fois pas. Tkt, lecteurtrice, tout au long de ce tuto, je t’ai mis des exemples de code qui fonctionnent. Si t’es grave dans la derche, ça t’aidera. Mais essaye à chaque fois de trouver la réponse par toi-même.

L’autre truc rigolo, c’est quand ton programme n’a aucune erreur, mais qu’il ne fait pas du tout ce que tu veux. Dans ce cas, met des « print ». Ça te permet de voir par où passe l’exécution, d’afficher le contenu de tes variables, etc.

On va tester ça tout de suite. Ajoute ça à la fin de ton programme :

x = 5
print("Valeur de x")
print(x)

Tu peux aussi écrire plusieurs trucs sur une même ligne, en séparant chaque valeur par une virgule. Ajoute aussi ça :

print("Valeur de x :", x)

Et rond et rond

On continue avec un truc simple. En plus du carré, tu vas me dessiner un cercle de rayon 60 pixels. Lorsque ton programme s’exécute, on doit voir ça :

Tu sais pas comment on dessine un cercle ? Mince alors. Eh bien, cherche. Va voir par là si j’essuie : https://docs.python.org/3.8/library/turtle.html#turtle.circle

C’est aussi ça, la prog. Tu passes ton temps à chercher comment on fait certains trucs, parce qu’on ne peut pas retenir tous les trucs.

Ensuite, au lieu d’un cercle entier, tu me dessines juste un tiers de cercle. Faut que ça donne ça :

Pour t’aider, re-zy-va voir le lien internet sus-cité.

Comme promis, lecteurtrice, voilà un lien vers la réponse, à n’utiliser qu’en cas d’extrême urgence mondiale, si tu n’arrive pas à trouver par toi-même.

Humeur variable

Mine de rien, on a fait un truc super important dans le chapitre pré-précedent, avec l’instruction « x = 5 ». On a déclaré une variable.

Ooooohhhhh.

Définition : une variable est un truc dans lequel tu mets le machin que tu veux. Tu peux ensuite réutiliser le truc, ça fait comme si c’était le machin. Débrouille-toi avec ça.

Le signe « égal » utilisé n’a pas la même signification qu’en maths. C’est une affectation et pas une égalité. Ce sont deux notions différentes, mais qui existent toutes les deux en programmation. On verra ça plus tard.

Dans ta tête, quand tu vois écrit « x = 5 », tu peux te dire « x prend la valeur de 5 », ou bien « x devient 5 ». Ce sera plus exact que « x égal 5 ».

Tu peux aussi te faire dans ta tête la voix française de Jim Carrey. Sérieusement, ça aide.

Si tu veux plus de détails sur les variables, va voir ce tutoriel. Il est assez bien fichu, y compris les chapitres après, sur les listes, les tuples, les fonctions… Ça pourrait te servir pour la suite.

On est pas chez ces ringards de matheux, t’as le droit d’avoir des noms de variables de plusieurs lettres, à condition qu’il n’y ait pas d’espace. Par exemple : « ma_super_variable = 5 ».

Ton environnement de dev a aussi un mode console, mais je t’embête pas avec ça pour l’instant. Par contre, un truc utile, au lieu de cliquer sur Play, tu peux utiliser le raccourci Ctrl+Entrée. Ça exécute ton code.

Si tu veux avoir l’air d’un vrai programmeur qui a des gonades, utilise des raccourcis claviers plutôt que ta souris. (Wesh lecteurtrice ! T’as vu ? Écriture inclusive avec le mot « gonades »). Comme t’as souvent les mains sur le clavier pour écrire du code, vaut mieux essayer de tout faire avec le clavier plutôt que de perdre une demi-seconde à attraper la souris.

Autre bidouille, spécifique à turtle. Au début de ton programme, juste après l’instruction « import », tu peux ajouter la ligne « turtle.speed(0) ».

La tortue dessinera ses traits et ses cercles plus vite. Tu me remercieras quand tu en seras à exécuter ton code pour la vingtième fois parce que tu seras en train d’essayer de faire marcher quelque chose qui ne veut pas marcher.

Une boucle pour une spirale

Commence par nettoyer le bazar des chapitres précédents. Supprime toutes les instructions de dessins : « turtle.forward », « turtle.left » et « turtle.circle ». Si tu tiens absolument à garder ces premiers blablablutiements, sauvegarde-les dans un petit fichier texte. Ou sinon, laisse-les où ils sont, mais en commentaire. Il suffit d’écrire un caractère dièse « # » au début de la ligne.

Très utile les commentaires. Ça peut servir à expliquer des choses directement dans le programme. Tu peux aussi écrire ton autobiographie.

Si je te fais enlever tout ça, c’est pour repartir sur une zone de dessin propre. Parce qu’on va faire du fun.

Des spirales comme la coiffure de princesse Leia

Si t’es pas trop vieux ou vieille, lecteurtrice, tu as certainement entendu l’expression de langage de jeune : « être en boucle sur quelque chose ». Ça vient de l’informatique.

Sans plus attendre, copie-colle moi cette ligne à la fin de ton programme :

for compteur in range(11):print(compteur * 8)

Tu exécutes, et ça écrit la table de 8 dans la sortie standard.

Cette ligne de code est à lire en deux parties, séparée par le caractère « : ». La première partie indique que tu veux faire une boucle, c’est à dire exécuter plusieurs fois la même chose.

Le « 11 » indique que cette boucle s’exécutera 11 fois, en comptant de 0 à 10. Ça a l’air crétin de commencer à compter à partir de zéro, mais ça se justifie. Je prendrais le temps de t’expliquer plus tard, quand tes poils auront poussés, jeune lecteurtrice.

Le morceau de code après le deux-points, c’est le contenu de ta boucle. C’est à dire l’instruction que tu veux exécuter plusieurs fois. Tu la connais déjà, c’est un « print ».

Le caractère étoile « * » signifie simplement la multiplication. En maths, la multiplication est notée par une croix, mais ce caractère n’existait pas sur les premiers ordinateurs. D’ailleurs, ces crétins de matheux n’utilisent même pas la croix, ils mettent rien du tout. « 2a » signifie « 2 multiplié par a ».

Déso, mais le caractère rien-du-tout ça existe pas, même sur les ordinateurs récents. Qu’est-ce qu’ils sont cons ces matheux.

Revenons aux boucles. Celles-ci sont gentilles. En plus de répéter un truc, elles te donnent gratochement une variable. Ici, on l’a appelé « compteur ». Celle-ci change automatiquement de valeur à chaque passage de la boucle.

Ça fait comme si t’avais écrit :

compteur = 0
print(compteur * 8)
compteur = 1
print(compteur * 8)
compteur = 2
print(compteur * 8)
...
compteur = 10
print(compteur * 8)

Ceci étant expliqué, on est bien d’accord que la table de 8, c’est des maths et c’est ringardos. Nous on veut du fun. On va dessiner une putain de spirale !

Tu sais comment ça se dessine, lecteurtrice ? Il suffit de tracer des morceaux de cercles de plus en plus grand. On dit qu’on fait des tiers de cercles, avec des rayons qui augmentent de 10 pixels en 10 pixels. On en fait 15.

Si t’es débile, lecteurtrice, tu vas faire ça :

turtle.circle(0, 120)
turtle.circle(10, 120)
turtle.circle(20, 120)
...

Mais tu vaux mieux que ça et tu me le fais sous forme d’une boucle, Okaye ?

Le dessin tracé ressemblera à ça :

Le lien vers la réponse, si jamais tu galères.

Une spirale qui grossit et des blocs de code

Sais-tu qu’on peut changer la taille du trait ? Mets-nous l’instruction « turtle.pensize(5) » juste avant ta boucle. Voilà une jolie spirale plus épaisse. Le nombre indiqué correspond à une taille en pixel. Évite de mettre trop gros, ça fera des pâtés moches. Le pensize doit être petit. D’ailleurs « pensize » est un anagramme de « ze penis ».

Soyons over-fun. Tu vas me dessiner une spirale de plus en plus épaisse. Le trait pourrait varier de 0 à 14 pixels, par exemple. Ça tombe bien, ta boucle s’exécute déjà avec un compteur qui va de 0 à 14.

Et là on arrive à une notion très importante en programmation (python ou autre) : les blocs de code.

Un programme est un gros bloc de code, avec plusieurs instructions dedans.

Dans un bloc de code, il peut y avoir des sous-blocs, eux-mêmes pouvant contenir des sous-sous-blocs, etc. Un peu comme ces ringards de matheux quand ils imbriquent des parenthèses. Zou, un exemple.

3 * ((1 + 6) * 2) + 4 * (2 + 5) – 1
Cette expression contient deux sous-blocs : ((1 + 6) * 2) et (2 + 5).
Le premier sous-bloc contient un sous-sous bloc : (1 + 6)

La comparaison s’arrête là. En maths, on évalue en premier les sous-blocs les plus profonds. En programmation, on commence au début, et on avance en rentrant (ou pas) dans les sous-blocs.

Une boucle annonce un sous-bloc, qu’elle exécutera plusieurs fois. Dans le chapitre précédent, ton sous-bloc n’avait qu’une seule instruction : « turtle.circle(compteur * 10, 120) ».

Chaque début et fin de sous-bloc doit être clairement indiqué dans le programme. Dans les langages C et Javascript, on utilise pour ça des accolades « {} », en LISP, des parenthèses « () », en Pascal, les mots « begin » et « end », etc.

Pour que le programme soit plus facilement lisible, on indente les blocs. Toutes les instructions d’un sous-bloc doivent être écrites avec un décalage de quelques espaces au début (en général on en met 4). Les instructions d’un sous-sous-bloc doivent être décalée deux fois, soit 8 espaces, et ainsi de suite. Quand on sort d’un bloc, on enlève un décalage d’indentation.

Il y a des tas de gens qui ne respectent pas cette mise en forme. Leurs programmes sont alors beaucoup moins lisibles. Si tu rencontres ce type de personnes, il est de ton devoir de les insulter et les stigmatiser.

Tu as sûrement déjà vu des images corporate bullshit montrant un écran d’ordinateur avec des lignes de code. C’est hype, swag, geek, hacker et tagada-tsoin-tsoin.

T’as vu lecteurtrice comment sont organisées ces petites lignes ? Ça se décale, puis ça se recale, se redécale, se rerecale. C’est ça l’indentation.

Et en python, comment donc marque-t-on les débuts et fin de blocs ?

Tu vas rire lecteurtrice, c’est par l’indentation elle-même ! Quand tu veux que des lignes de code soient dans un sous-bloc, tu leur mets des espaces au début. Quand ton sous-bloc se termine, tu écris la ligne suivante sans les espaces.

C’est un peu déroutant, mais ça a un très gros avantage. Ton code est obligé d’être bien présenté. En python, tu ne pourras jamais te faire insulter ou stigmatiser parce que tu n’auras pas respecté les règles d’indentation. (On pourra toutefois t’humilier pour plein d’autres raisons).

Les éditeurs de texte conçus pour la programmation prennent en compte cette particularité des indentations. Essayons ça tout de suite. Retourne à ton programme et copie-colle ce texte, sans oublier les deux-points à la fin : « for compteur in range(15): » , puis tu appuies sur Entrée. Ton curseur va à la ligne d’en dessous, mais pouf ! Il s’est décalé de 2 espaces ! Écrit un truc puis réappuie sur Entrée, ça restera décalé.

Quand tu as fini ton bloc, appuies sur backspace, ça enlève les deux espaces d’un coup, et tu retournes au bloc de code supérieur.

Dans l’environnement que je t’ai proposé, une indentation est représentée par 2 espaces. Ailleurs, ce sera 4, ou 8, ou une tabulation. Il y a des discussions sans fin entre les développeurs pour savoir s’il vaut mieux indenter avec des espaces ou des tabulations. Je ne t’en parle pas maintenant, tu n’es pas encore assez mature pour réaliser à quel point les développeurs peuvent avoir des discussions immatures.

Assez discuté, au boulot ! Tu me fais cette boucle, avec un sous-bloc de deux instructions. La première est un « pensize », la seconde un « circle ».

Ça doit donner un truc comme ça.

Lien vers la réponse si c’est la hass pour toi.

Ce sera tout pour aujourd’hui !

J’espère que ça t’as plu lecteurtrice. To be continued le mois prochain. On fera un dessin comme ça :

En attendant, voici tes devoirs. Essaye de me faire un dessin comme ça :

Je te donne pas le code. Tu te débrouilles. C’est réalisable avec les notions que je viens d’expliquer. Deux petits indices, quand même :

– On peut faire des boucles imbriquées, c’est à dire une boucle dans une boucle. Pense à rajouter une indentation (un décalage d’espace au début de la ligne) à chaque fois que tu rentres dans une nouvelle boucle. Et utilise un nom de variable différent pour chaque boucle, sinon ça va confusionner.

– Les tracés de cercle (et de morceaux de cercle) dépendent de l’orientation initiale de la tortue. Tu peux tester ça vite fait : écrit un programme qui fait uniquement « turtle.circle(60, 120) », puis ajoute juste avant l’instruction « turtle.left(180) ». Le morceau de cercle changera de sens.

Un dernier conseil : n’écris pas trop de code d’un coup. Tu rajoutes quelques lignes, tu appuies sur Play pour vérifier que ça swagge, tu rajoutes ou modifies quelques autres lignes, tu retestes, etc. Si t’écris trop d’un coup et que ça plante quand tu testes, ce sera plus difficile de trouver où que c’est que ça merdouille.

Comme je suis gentil et fun, tu auras le la réponse à l’exercice dans mon prochain article.

Ook ook à toi, lecteurtrice !

*Drop du clavier et je m’en vais comme un prince.

Du code commenté et documenté pour Noël

Il m’arrive assez souvent de pondre un article aux environs de Noël, voire le jour même, car c’est le moment où je suis en vacances. Comme plein de monde, en fait.

Comme promis le mois dernier, j’ai rangé et commenté le code de ma petite animation pour la vidéo-boulette de l’UTBM. C’est dans mon repository git, par ici : https://github.com/darkrecher/anim-tunnel-utbm

J’ai fini un autre mini-projet sur lequel j’avançais par intermittence depuis quelques mois : compléter un challenge de niveau « très difficile » sur le site CodinGame.

Il s’agit du challenge « Vox Codei – épisode 2 ». Des vilains carrés rouges se déplacent sur un quadrillage, il faut déterminer les coordonnées où placer des bombes pour les détruire.

Cliquez sur l’image pour accéder au challenge (il vous faut un compte CodinGame).

Boum !

J’en ai profité pour utiliser « aboard », ma librairie de code gérant des plateaux de jeux en 2D. Je vous en avais déjà parlé, fouillez dans mes anciens articles ou dans mes repo git si ça vous intéresse.

Petit conseil pour les jeux dans CodinGame

Que ce soit des challenges ou des combats de bots : respectez le rythme des échanges stdin/stdout entre votre code et le jeu. À chaque tour de jeu, récupérez bien les infos qui vous sont envoyées en appelant des fonctions « input() », même si vous n’en faites rien.

Dans Vox Codei, la situation du plateau de jeu, avec les positions des carrés rouges, vous est transmise à chaque tour. Et à chaque tour, vous devez renvoyer soit le texte « WAIT », soit les coordonnées d’une bombe à poser.

Les mouvements des carrés rouges sont assez simples. Au bout de quelques tours, il est possible de les extrapoler. Vous n’aurez donc plus besoin des infos transmises par le jeu. J’avais pris la décision de ne plus les lire, et de simplement renvoyer mon WAIT ou mes coordonnées.

Eh bien ça met le jeu dans les choux.

Comme vous ne récupérez rien, le jeu croit que vous en êtes resté au début. Il attend, et au bout d’un moment, considère que c’est votre code qui est dans les choux. Il y a en effet un temps limite d’exécution pour chaque tour. Le jeu arrête votre programme si celui-ci est dépassé, pour les cas où vous auriez envoyé du code pourri comportant une boucle infinie.

Vous êtes alors averti d’un message d’erreur indiquant, en substance : « Désolé gros con, on a killé ton process car on le suspectait de glander. Corrige ton code de merde. Respect et robustesse. » Sauf que votre code n’est pas spécialement lent, c’est juste qu’il n’exécute pas les input() permettant de vider régulièrement le buffer d’entrée-sortie entre vous et le jeu.

De la doc publiée mais pas publique

Ce mini-projet m’ayant pris un peu de temps, je me suis dit que ça méritait une petite documentation, que j’ai directement écrite dans le code. Ensuite, j’ai publié le tout sur CodinGame.

Le problème, c’est que seuls les gens ayant déjà résolu le challenge ont accès aux solutions publiées par les autres. Je me suis donc cassé le fondement à décrire et commenter un algo dont seules 258 personnes pourront profiter. Ce qu’elles ne feront pas forcément car rien ne dit que ça les intéressera.

Tant pis pour la gloire. Je me console en me disant que j’ai réussi une chose que seules 258 autres personnes dans le monde ont réussie.

Joyeux Noël quand même

Voici pour l’occasion Meagan Kerr et ses dents du bonheur.

 

Jouez avec un phrase-bizarre-otron

Coucou !

Petit article rapide.

J’ai participé à un concours de code, sur le thème : « réalisez un truc qui ressemble plus ou moins à de l’intelligence artificielle ».

J’ai créé un programme qui lit un roman et génère des phrases bizarres à partir de ça. Elles sont (presque) grammaticalement correctes, mais n’ont aucun sens.

Vous pouvez l’essayer ici : https://repl.it/talk/challenge/FrankenPhrase/10740

Comme romans, j’ai mis :

  • En français :
    • 20 000 Lieues Sous Les Mers
    • Les Trois Mousquetaires
  • En anglais
    • Frankenstein
    • The Story of Nuclear Energy, de Isaac Asimov.
  • Plus, ceux que vous voulez, si vous prenez le temps de les uploader, tout en lisant la doc d’utilisation.

Ça fait parfois des phrases marrantes :

« Quelques explications, un coup de pintadines, je vous souhaiter que les oubliettes. »

« Que Votre Éminence, qui, et, le jeune femme que dit Aramis, traversant la reine. »

ou parfois des choses poétiques :

« C’était alors la conversation sur son sein des monocentres, plus facile. »

« La surface de latitude nord, je passerai sous nos yeux une grande dépense du fleuve de toi. »

Si vous avez le temps, inscrivez-vous sur le site et laissez-moi un petit upvote.

La méthode de génération est super simple : c’est juste des statistiques par rapport aux fréquences d’apparition des mots. Par exemple, le mot « géantes » apparaît plus souvent à côté du mot « fesses » que du mot « tripoter ».

Pas d’analyse sémantique, on ne cherche pas à identifier les verbes, les sujets, ou autres. Pas de réseaux de neurones non plus. En fait je sais même pas si ce que j’ai fait peut être considéré comme de l’I.A. ou même du machine learning.

En tout cas, c’est assez rigolo. Ça donne des textes surréalistes, un peu à la André Breton.

André Breton me fait penser aux bretons me fait penser aux bretonnes me fait penser à une vidéo intitulée « Dominique la grosse bretonne ».

Voilà.

 

Solution alzheimerienne des tours de Hanoï

Comme promis, voici le deuxième article du mois. Ça fait un certain nombre de fois que je publie des articles courts, donc je voulais me rattraper.

Par contre, j’ai jamais promis que ce deuxième article serait intéressant.

Il s’agit céans d’un petit bout de code en python, résolvant le problème des tours de Hanoï de manière alzheimerienne.

Je vous en avais parlé il y a quelques années.

La manière alzheimerienne impose de ne pas se souvenir des coups joués précédemment, et de ne pas partir dans des trips de récursivité sous acide.

Le coup à jouer est déduit uniquement de la situation courante, c’est à dire la position des disques. Vous pouvez donc appliquer cet algorithme même si vous êtes atteint de la maladie d’Alzheimer. Ha ha ha.

J’ai pris le temps de remettre le code au propre, en PEP-8, avec des commentaires corrects. Le tout est sur mon github.

Explication de l’algorithme

Elle est dans la docstring du fichier python. Je vous la remets ici.

Il faut d’abord déterminer le nombre de « coupures » dans l’ordre des disques.

Lorsque deux disques de taille N-1 et N sont empilés sur un même poteau, il n’y a pas de coupure entre eux. Lorsqu’ils sont sur deux poteaux différents, on compte une coupure.

De plus, lorsque le gros disque du bas n’est pas sur le poteau de fin, on compte également une coupure.

Exemple :

  • Le disque 1 (le plus petit) est sur le poteau de départ.
  • Les disques 2 et 3 sont sur le poteau intermédiaire.
  • Le disque 4 (le plus gros) est aussi sur le poteau de départ.

 

      |           |           |
      |           |           |
      |           |           |
     +++        -----         |
  ---------    +++++++        |
  .................................

 

On compte les coupures en partant du plus gros disque vers le plus petit (mais on aurait pu compter dans l’autre sens).

  • Le 4 n’est pas sur le poteau de fin. +1 coupure
  • Le 4 et le 3 ne sont pas sur le même poteau. +1 coupure
  • Le 3 et le 2 sont sur le même poteau. OK
  • Le 2 et le 1 ne sont pas sur le même poteau. +1 coupure

Total : 3 coupures.

Cette dame s’appelle Miss Twin Towers, soit l’équivalent de deux tiers d’un jeu de tour de Hanoï

Si le nombre de coupures est impair, il faut déplacer le disque 1 (le petit).

Pour déterminer son poteau de destination :

Si le nombre total de disque est pair, le petit disque doit se déplacer vers l’avant :

poteau de départ -> poteau intermédiaire -> poteau de fin -> poteau de départ -> etc.

Si le nombre total de disque est impair, il doit se déplacer vers l’arrière :

poteau de fin -> poteau intermédiaire -> poteau de départ -> poteau de fin -> etc.

Si le nombre de coupures est pair, il faut déplacer un disque autre que le petit disque. Dans ce cas, il n’y a toujours qu’un seul mouvement possible.

Parmi les deux poteaux ne contenant pas le petit disque, l’un d’eux est vide. Il faut alors déplacer un disque du poteau non vide vers le poteau vide.

Parmi les deux poteaux ne contenant pas le petit disque, aucun n’est vide. Il faut prendre le plus petit disque parmi ces deux poteaux, et le déplacer vers l’autre.

Lorsque le nombre de coupures vaut 0, le jeu est terminé. Tous les disques sont sur le poteau de fin, dans le bon ordre.

Il faudrait une vraie démonstration mathématique pour prouver que cet algo fonctionne, mais je ne sais pas la faire. Ça semble fonctionner quel que soit le nombre de disques.

Les tours c’est fun

Pour finir, voici une image d’un vieux jeu que j’avais beaucoup aimé : Mystic Towers. Je n’ai pu profiter que de la version shareware, mais c’était quand même chouette

Oh, et il semblerait qu’on arrive déjà à la fin du mois. Il faut que je démarre un nouvel article. Diantre.

Un truc fait ailleurs mais le voilà ici

 

J’ai écrit un texte quelque part. Mais il est associé à mon nom du monde du travail. (Ça fait beaucoup de fois de suite une combinaison des lettres « m », « n », « o », mais osef).

Cependant, j’aime bien ce texte et je trouve qu’il mériterait d’apparaître sur ce blog.

Alors j’ai fait une bidouille à l’arrache. J’ai balancé le texte dans pastebin. Et je vous en donne le lien : https://pastebin.com/rXgMFx0q .

La mise en forme, les images et une grande partie des liens ont été perdus en route. Désolé.

La lecture est un peu fastidieuse, du fait que c’est du texte brut. Bon courage. En même temps, j’ai pas l’impression que grand monde lise ce blog, alors on n’est plus à ça près. Je viens de me rendre compte que ça fait presque 10 ans que je blablate dans ce coin paumé de la « blogosphère ». Faudra que je trouve un moyen débile de faire une rétrospective pour les 10 ans, mais de manière plus originale que « ce blog a 10 ans, youpi, blablabla ».

Pour en revenir à ce texte. Il est évident qu’en fouinant un peu, on retrouvera l’endroit originel de sa publication, et vice-versa : les personnes connaissant cet endroit originel pourraient tomber sur ce blog. Je ne me fais pas d’illusion, le lien entre mon nom du monde du travail et le nom « Réchèr » est déjà connu de plusieurs personnes, et tôt ou tard, il deviendra plus ou moins public. En attendant, j’essaye de faire durer l’anonymat le plus longtemps possible.

Si vous souhaitez garder l’anonymat, la première chose à faire est de ne pas laisser trainer des photos de votre visage un peu partout :

 

Pru-Pra-Prok sur github

Wouwi-zouwi m’sieurs-dames et tous les autres.

J’ai mis mon dessin animé sur github. Vous vous en souvenez peut-être, c’était ce truc là :

C’est par ici : https://github.com/darkrecher/pru-pra-prok

Rien de nouveau par rapport à la version initiale (qui date de plus de 10 ans). Mais j’ai tout de même pris le temps de le recompiler avec gcc sous MingW32, et de documenter le tout de la manière la plus détaillée possible, afin d’offrir à d’autres personnes la possibilité de modifier, mâchonner, recompiler, créer ses propres dessins animés, etc.

J’ai toujours été agacé par les gens qui libèrent leur code source sans y ajouter la documentation nécessaire à son exploitation. « Huuurrrrr duuuurrrrr. Tu fais makefile et ça marche ». J’essaye donc de ne pas faire comme eux.

Après, ça vaut ce que ça vaut. On trouvera facilement des logiciels d’animations infiniment meilleur que ce truc (rien que Scratch, par exemple).

La githubisation de ce projet fait partie de mon grand plan « vidage de fonds de tiroir de tous mes vieux bouts de code ». C’est bientôt terminé, il ne me reste plus qu’un pack de mini-projets. Ensuite je pourrais passer à autre chose. Soyez assurés que vous serez les premiers informés de la suite des événements.

Pour finir cet article, je propose de glisser du domaine des dessins animés vers celui du cinéma, avec cette image du film Dikkenek.

(Tiens, ça me fait penser au catalogue des 3 Belges dans les copains des Tilleuls … Aucun lien, désolé).