Construction élémentaires III : La boucle while

Objectifs :

À la fin de cette séquence vous serez capable de :

  • Utiliser la boucle while pour répéter un morceau de programmme.
  • Manipuler les instructions break et continue.
  • (Modifier un algorithme et son pseudo-code)

Un mini-projet

Améliorer notre jeu « nombre à deviner » de sorte que l'on puisse jouer tant que l'on n'a pas la bonne réponse.

1. Mise en œuvre de l'instruction while

1.1. Premier exemple : La baitaille perdue

Le programme "La Bataille Perdue" décrit le dernier et vaillant combat d'un héros submergé par une armée de trolls, un scénario que l'on pourrait trouver dans un jeu de rôle. Le programme narre l'action de la bataille. Il décrit le combat, coup par coup, alors que le héros terrasse un troll, mais subit ensuite davantage de dégâts. À la fin, le programme se termine toujours par la mort du héros.

code Python

In [ ]:
#Un héros téméraire
print("Votre héros solitaire est encerclé par une immense armée de trolls.")
print("Leurs corps verdâtres en décomposition s'étendent à perte de vue.")
print("Votre héros dégaine son épée pour le dernier combat de sa vie.\n")
sante = 10
trolls = 0
degats = 3
while sante >= 3:
    trolls += 1
    sante -= degats
    print(f"Votre héros brandit son épée et terrasse un troll maléfique, mais encaisse {degats} points de dégâts.\n")
    
print(f"Votre héros s'est battu avec vaillance et a vaincu {trolls} trolls.")
print("Mais hélas, votre héros n'est plus.")
input("\n\nAppuyez sur la touche Entrée pour quitter.")

Fonctionnement de l' instruction while :

  • Déterminer si la condition sante >= 3 est vraie ou fausse.
  • Si la condition est vraie, exécuter le corps, puis revenir à l'étape d'initialisation (avec les nouvelles valeurs de n et u).
        trolls += 1
        sante -= degats
        print(f"Votre héros brandit son épée et terrasse un troll maléfique mais encaisse {degats} points de dégâts.\n")
        
  • Si fausse (c'est-à-dire sante < 3), quitter l'instruction while et poursuivre l'exécution à l'instruction suivante (print(f"Votre héros s'est battu avec vaillance et a vaincu {trolls} trolls")).

Table de suivi de la boucle

sante nbre_trolls dommage test : sante ≥ 3
10 0 3 True
7 1 3 True
4 2 3 True
1 3 3 False

1.2. Deuxième exemple : Conversation avec un enfant de trois ans !

code Python

In [ ]:
print("Ce programme modélise une conversation avec un enfant de trois ans.")
print("Arrêtez cet enfant insupportable !\n")

reponse = ""
while reponse != "parce que":
    reponse = input("Pourquoi ?\n")
print("Oh ! D'accord.")
intput("Appuyer sur la touche Entrer pour quitter.")

Analyse de la boucle while
Contrairement à l'instruction if, la boucle while teste la condition (reponse != "parce que"). Si cette condition (test) est vraie, le corps de la boucle while (reponse = input("Pourquoi ?")) s'exécute. À la fin, la condition est réévaluée.
Tant que la condition reste vraie, le corps de la boucle continue de s'exécuter. Dès que la condition est fausse (reponse == "parce que"), la boucle arrête de s'exécuter. Et le programme exécute l'instruction qui suit la boucle (print("Oh ! D'accord.")).

1.3. Troisième exemple : Algorithme du seuil

On considère la suite \((u_{n})\) définie sur l'ensemble des entiers naturels par :

  • \(u_{0}=5\)
  • \(u_{n+1}=u_{n}+3\) pour tout entier naturel.
  1. Écrire un algorithme sous la forme d'un pseudo-code qui calcule et affiche les termes plus petits ou égaux à \(15\) de cette suite puis affiche le nombre de ses termes.
  2. Traduire ce pseudo-code en Python.

Pseudo-code

u← 5

n← 0

Tant que u ≤ 15, Faire:

u← u + 3

n← n + 1

Afficher n et u

Fin Tant que

Afficher n + 1

In [ ]:
#Initialisation
n = 0
u = 5

#début
while u <= 15:
    n = n + 1
    u = u + 3
    print(f"\nn = {n} et u = {u}")
#fin    
print(f"\nle nombre de termes est {n + 1} puisque l'on part de 0 à {n}")

Voici le fonctionnement de l' instruction while :

  • Déterminer si la condition \(u\le15\) est vraie ou fausse.
  • Si la condition est vraie, exécuter le corps, puis revenir à l'étape d'initialisation (avec les nouvelles valeurs de n et u).
  • Si fausse (c'est-à-dire \(u>15\)), quitter l'instruction while et poursuivre l'exécution à l'instruction suivante (print(f"\nle nombre de termes est {n + 1} puisque l'on part de 0 à {n}")).

Table de suivi de la boucle

Initialisation À la fin de l'itération n°1 À la fin de l'itération n°2 À la fin de l'itération n°3 À la fin de l'itération n°4
\(n\)
\(u\)
\(n=0\)
\(u=5\)
\(n=1\)
\(u=8\)
\(n=2\)
\(u=11\)
\(n=3\)
\(u=14\)
\(n=4\)
\(u=17\)
test
\(u\le15\) ?
Vrai Vrai Vrai Vrai Faux

Syntaxe

In [ ]:
while test :
    <expression n°1>
    ...
    <expression n°n>
<instruction si le test est évalué à Faux>

#Après les deux points il y a une indentation (décalage)
#expressionS n°... constituent le corps de la boucle (indenté par rapport à la ligne précédente)


Généralement, une boucle while est contrôlée par une variable (reponse dans notre simulateur, u dans l'exemple) qui est comparée à une ou plusieurs valeurs ("parce que" et 15).
Il est important que cette variable de contrôle soit initialisée avant la boucle (reponse = "" dans notre simulateur, u = 5 dans l'exemple).
S'assurer que le test peut être évalué à True et à False.

Application 1 :

L'objectif est de simuler la force d'un joueur dans un jeu !
Le joueur est autorisé à attaquer un adversaire tant que sa force est supérieure ou égale à 3, mais toutefois où il joue, il perd deux points de force.

  • Créer une variable appelée force et l'initialiser à 20.
  • Afficher un message indiquant la force du joueur.
    • Écrire une boucle while qui permet de jouer tant que sa puissance la lui permet.
    • À l'intérieur de la boucle while, afficher le message : "Votre force est de" suivi de la valeur de la force courante du joueur.
    • À l'intérieur de la boucle while, écrire une instruction qui réduit la puissance du joueur à chaque jeu.
  • En dehors de la boucle while, afficher le message : "Oh non, vous êtes trop faible pour continuer ! Game Oveeeeer."
In [ ]:
# La force du joueur commence à 20. 
force  =  20

# Le joueur est autorisé à continuer à jouer tant que sa force est supérieure à 3. 
while force >  3 : 
    print (f"Vous jouez toujours car votre force est de {force}." )
    # Perte de puissance
    force =  force -  3   
    
print (f"Oh non, vous êtes trop faible ! Game Oveeeeer. " )

Application 2 :

On considère la suite \((u_{n})\) définie sur l'ensemble des entiers naturels par :

  • \(u_{0}=5\)
  • \(u_{n+1}=1,25u_{n}+3\) pour tout entier naturel.

Déterminer la valeur de \(n\) à partir de laquelle \(u_{n}\) est supérieur à 200.

Boucle impossible

Le premier test est évalué à faux.

In [ ]:
#Une bouble impossible
n = 0
u = 15
while u < 10:
    u = u - 1
    print(u)

Boucle infinie : Répéter Indéfiniment

Pour mettre en œuvre une boucle infinie, on utilise en général une boucle "tant que" avec une condition toujours vraie.

In [ ]:
prenom = ""
while prenom != "Timoléon": # while "Timoléon":
    prenom = input("Entrer un prénom : ")
    print(prenom)
input("Appuyer sur la touche Entrer pour quitter.")
In [ ]:
#boucle infinie
cpteur = 0 
while cpteur >= 0:
    cpteur = cpteur + 1
    print(cpteur)
In [ ]:
#boucle infinie
cpteur = 0 
while True:
    cpteur = cpteur + 1
    print(cpteur)

Application 3 :

Associer ces deux programmes en un seul afin que ce dernier détermine aussi le nombre de tentatives pour trouver le prénom Timoléon.

2. Les instructions break et continue

L'instruction break est utile pour sortir immédiatement de la boucle lorsqu'une condition est vérifiée.

In [ ]:
prenom = ""
while prenom != "Timoléon":
    prenom = input("Entrer un prénom : ")
    print(prenom)
    if prenom.startswith("B"):
        break  
input("Appuyer sur la touche Entrer pour quitter.")
In [ ]:
while True:
    print()
    mot_de_passe = input("Choisir un nouveau mot de passe (composé de lettres et/ou de nombres) : ")
    if mot_de_passe.isalnum():
        print("Vous êtes connecté.")
        break
    print("Recommencer. Un mot de passe n'est constitué que de lettres et/ou de chiffres.")

L'instruction continue est utilisée pour abandonner le traitement du reste du corps de la boucle pour l'itération en cours et passer à la suivante, en restant dans la boucle.

In [ ]:
#boucle infinie
cpteur = 0
while cpteur >= 0:
    cpteur += 1
    print(cpteur)
    if cpteur == 15:
        break
    if cpteur == 7:
        continue

Les instructions break et continue doivent être utilisées avec parcimonie.

Utiliser la boucle while pour faire un menu.

Devine mon nombre

In [ ]:
#Deviner mon nombre

import random

"""
    L'ordinateur choisit un entier entre 1 et 100,
    Le joueur doit le deviner en une seule tentative. Et la machine signale à ce dernier
    si sa proposition est trop grande, trop petite ou la bonne.
"""

print("Bienvenue sur le jeu : Devinez mon nombre !")
print("\nJe pense à un entier compris entre 1 et 100.")
print("\nEssayez de deviner ce nombre.")

#Choisir le nombre à deviner
nbre_secret = random.randint(1, 100)
essai = int(input("Proposer un entier"))

if essai > nbre_secret:
    print("\nVotre proposition est plus grande que mon nombre.")
elif essai == nbre_secret:
    print(f"\nBravo, vous l'avez deviné ! J'avais choisi {nbre_secret}")
else:
    print("\Votre proposition est plus petite que mon nombre.")

Pour rendre le jeu intéressant, nous allons permettre de jouer plusieurs fois (tant que la bonne réponse n'est pas trouvée).
Modifier l'algorithme précédent afin qu'il réponde au problème posé.

L'algorithme pour notre jeu devient :

  • Afficher : Bienvenue sur le jeu : Deviner mon nombre !
  • Afficher : Je pense à un nombre entier compris entre 1 et 100.
  • Afficher : Essayez de deviner ce nombre.
  • Choisir un nombre à deviner entre 1 et 100.
  • Demander au joueur de proposer un nombre
  • Tant que la proposition du joueur est différente du nombre à deviner, Faire :
    • Si sa proposition est plus petite que le nombre à deviner, afficher : « proposition plus petite que le nombre à deviner. »
    • Sinon, afficher : « proposition plus grande que le nombre à deviner. »
    • Demander au joueur de tenter de nouveau.
  • Féliciter le joueur pour avoir deviné le bon nombre.

En déduire son pseudo-code.

Pseudo-code

Afficher : « Bienvenue sur le jeu : Deviner mon nombre ! »

Afficher : « Je pense à un nombre entier compris entre 1 et 100. »

Afficher : « Essayez de deviner ce nombre. »

nbre_secret ← un entier choisi au hasard entre 1 et 100

essai ← proposition du joueur

Tant que la proposition est différente du nombre à deviner, Faire:

Si essai < nbre_secret, Alors

Afficher : « proposition plus petite que le nombre à deviner »

Sinon, Afficher : « proposition plus grande que le nombre à deviner »

FinSI

Tenter de nouveau

Fin Tant que

Afficher : « Bravo, vous avez deviner mon nombre ! »

Programmer ce pseudo-code en Python.

In [ ]:
import random

print("Bienvenue sur le jeu : Devinez mon nombre !")
print("\nJe pense à un entier compris entre 1 et 100.")
print("\nEssayez de le deviner.\n\n")

#initialiser le nombre à deviner
nbre_secret = random.randint(1, 100)
#print(nbre_secret)
essai = int(input("Proposer un entier : "))
print()
while essai != nbre_secret:
    if essai > nbre_secret:
        print("\nVotre proposition est plus grande.\n")
    else:
        print("\nVotre proposition est plus petite.\n")
    essai = int(input("Tentez de nouveau : "))
    
print("\nBravo")

Exercice 2 :
Améliorer notre jeu de sorte que le programme affiche le nombre de tentatives qu'il a fallu au joueur pour deviner la bonne réponse.

Exercice 3 :
Améliorer notre jeu de sorte que le nombre de tentatives soit limité à 5.