Exercice 21 : le Lotto en Python

 Énoncé 21 

Le programme simule le tirage du Lotto belge (chaque pays a ses particularités, vous pouvez l'adapter à votre pays). Un tambour contient 45 boules numérotées de 1 à 45. 6 boules sont tirées dans ce tambour sans remise (la boule tirée n'est pas remise dans le tambour avant le tirage suivant). Ensuite, un numéro complémentaire est tiré parmi les 39 boules restantes.
Dans un premier temps, les numéros sont affichés dans l'ordre du tirage, le complémentaire étant affiché à part. Dans un second temps, les 6 premiers numéros sont affichés classés par ordre arithmétique avec toujours le numéro complémentaire à part.

 Analyse 

A. La succession de questions à se poser, le Quoi Faire, est le suivant :

  1. Ce programme nécessite-t-il une répétitive ?
    • La réponse est "Oui", il y a 6 boules à tirer + une septième, le numéro complémentaire;
    • De plus, le tirage se fait sans remise. Il faudra donc éviter de tirer une boule qui ne se trouve plus dans le tambour. Le système de tirage au hasard devra donc recommencer s'il tire une boule qui n'est plus dans le tambour. Il y aura donc plusieurs répétitives imbriquées.
  2. Ce programme nécessite-t-il un ou plusieurs tours de main ?
    • Il faudra compter le nombre de boules tirées, mais comme on sait d'avance qu'il y en aura 6, on utilisera une boucle for qui est une répétitive avec le compteur inclus;
  3. Qu'est-ce qui viendra avant la répétitive ?
    • Le fait de prévenir l'utilisateur de ce que fera le programme;
    • Le fait d'initialiser certaines variables, ce qui est une nécessité avant les boucles while.
  4. Qu'est-ce qui viendra dans la répétitive ?
    • Le fait de tirer au hasard le numéro d'une boule;
      • Il faudra recommencer jusqu'à trouver un numéro qui est encore dans le tambour.
    • Le fait "d'enlever" la boule chosie du tambour.
    • Le fait d'ajouter la boule choisie dans les résultats du tirage.
  5. Qu'est-ce qui arrêtera la répétitive ?
    • Le fait que la boucle for ait bouclé 6 fois;
  6. Qu'est-ce qui viendra après la répétitive ?
    • Le fait de tirer un numéro complémentaire;
      • Il faudra recommencer jusqu'à trouver un numéro qui est encore dans le tambour.
    • Le fait d'afficher les numéros tirés dans l'ordre du tirage + le complémentaire;
    • Le fait d'afficher les 6 numéros tirés dans l'ordre arthmétique croissant + le complémentaire.

B. Il est aussi intéressant de se poser la question du Comment Faire pour rejoindre toutes les exigences du quoi faire.

  1. Quelle structure va permettre de simuler le tambour ?
    • On peut pour cela utiliser une liste que l'on nommera tambour;
    • On initialisera cette liste avec les numéros de 1 à 45 inclus;
    • Chaque fois qu'un numéro sera tiré, ce numéro sera enlevé de la liste tambour.
  2. Quelle structure va permettre de stocker les résultats ?
    • On peut pour cela utiliser une liste que l'on nommera lotto;
    • On initialisera cette liste totalement vide au départ;
    • Chaque fois qu'un numéro sera tiré, ce numéro sera ajouté à la liste lotto.
  3. Et quelle structure pour le numéro complémentaire ?
    • Il s'agit d'un seul numéro, il peut donc être mémorisé dans la variable complementaire.
  4. Comment faire pour ne pas tirer deux fois le même numéro ?
    • Une boucle while va tourner pour tirer un numéro "tant que cette boule ne sera pas dans le tambour";
    • En "positif", le tirage sera répété jusqu'à trouver une boule qui soit dans le tambour...
    • Dès qu'une boule sera trouvée dans le tambour, la boucle s'arrêtera et le processus se poursuivra.

 Le programme en pseudo-code 

Avant de se lancer dans la rédaction du programme en Python, il semble judicieux d'en écrire les grandes lignes, les idées essentielles, en français.
Voici à quoi pourrait ressembler un résumé des grandes étapes à aborder.

Affiche+nl "Ce programme va simuler le tirage du Lotto, 6 numéros parmi 45 + un complémentaire."
tambour ← liste de 45 numéros de 1 à 45 inclus
lotto ← liste vide
numero ← 0 #*
Pour i allant de 0 à 5 inclus Fais
    Tant Que numero PAS dans le tambour Fais
        numero ← un nombre au hasard de 1 à 45 inclus
    enlève numero de tambour
    ajoute numero à lotto
Tant Que numero PAS dans le tambour Fais
    complementaire ← un nombre au hasard de 1 à 45 inclus
Affiche+nl "Résultats : ", lotto, " complémentaire : ", complementaire
Classer Lotto en ordre arithmétique croissant
Affiche+nl "Dans l'ordre : ", lotto, " complémentaire : ", complementaire

#* Il faut un numero absent du tambour afin de forcer la première boucle Tant Que qui suit à boucler au moins une fois.
On peut se demander pourquoi les boucles Tant Que suivantes vont toujours boucler au moins une fois par la suite, ce qui est essentiel pour que les tirages au hasard aient lieu...
Ceci s'explique par le fait que la valeur qui "traîne" dans numero est une valeur qui vient d'être enlevée de tambour. La prochaine boucle Tant Que bouclera donc d'office.

 Le programme en Python 

Attention : le tirage au hasard nécessite l'importation de la fonction randint de la bibliothèque random.

from random import randint
print ("Ce programme va simuler le tirage du Lotto, 6 numéros parmi 45 + un complémentaire.")
tambour = list(range(1, 46)) # La dernière valeur n'apparaît jamais dans la déclaration de liste
lotto = []
numero = 0
for i in range(6) :
    while numero not in tambour :
        numero = randint (1, 45)
    tambour.remove(numero)
    lotto.append(numero)
while numero not in tambour :
    complementaire = randint (1, 45)
print ("******* Tirage du Lotto *******")
print (lotto, "Complémentaire :", complementaire)
print () # Pour passer une ligne
lotto.sort()
print ("******* Dans l'ordre *******")
print (lotto, "Complémentaire :", complementaire)

Vous pouvez "copier-coller" ce programme dans votre éditeur IDLE pour vérifier s'il fonctionne selon les spécifications de départ.

 Débuggez malin !!! 

Zut, ce programme ne fonctionne pas... comment trouver l'erreur ?

Une manière de procéder est d'effectuer des affichages aux endroits-clés du programme.

Une première question à se poser est de savoir si le tirage du Lotto se fait correctement. Nous allons effectuer un affichage de lotto chaque fois qu'une valeur y est ajoutée pour voir ce qui se passe.

Veuillez ajouter un print (lotto) juste après l'instruction lotto.append(numero) et avec la même indentation. Effectuez le programme, que constatez-vous ?

lotto semble se compléter correctement au fil des tirages. L'erreur n'est donc pas là.

Cherchons encore...

Une seconde question à se poser est de savoir si le tirage du numéro complémentaire se fait correctement. Nous allons effectuer un affichage de complementaire après son tirage pour voir ce qui se passe.

Veuillez ajouter un print (complementaire) juste après l'instruction complementaire = randint (1, 45) et avec la même indentation. Effectuez le programme, que constatez-vous ?

L'endroit de l'erreur est trouvé, mais en quoi consiste cette erreur ?

? ? ? ? ? ? ?

L'erreur vient du fait que, dans la dernière boucle while il n'y a pas de liaison entre ce qui se passe dans la boucle et la condition d'arrêt. C'est complementaire qui est affecté alors que c'est l'état de numero, qui ne change pas, qui commande l'exécution de la boucle.

En conséquence, le choix de la variable complementaire est une mauvaise idée. Il suffit de continuer avec numero qui contiendra le numéro complémentaire puisqu'il a été tiré en dernier.

Pour la correction du programme, il suffit, les trois fois où on y fait appel, de remplacer complementaire par numero.

Veuillez corriger et tester le programme pour vérifier s'il fonctionne correctement. Y a-t-il parfois 1 et 45 qui apparaissent dans les tirages ? Y a-t-il des numéros plus petits que 1 ou plus grands que 45 qui apparaissent parfois ? Tous les numéros d'un même tirage sont-ils bien tous différents ?

Bonne poursuite de votre apprentissage.

Retour