Challenges#
Chaque challenge de cette page consiste à programmer un mini-jeu complet, jouable directement dans la page. Ensemble, ils mobilisent toutes les notions vues jusqu'ici : variables, entrées utilisateur, branchements, boucles, listes et fonctions. Contrairement aux exercices, un challenge ne vous dit pas quelle notion utiliser : à vous de choisir les bons outils et d'organiser votre programme. Les jeux sont classés par difficulté croissante, et la plupart se terminent par une partie Pour aller plus loin facultative.
Vous devez réaliser deux défis à choix. Sous le titre de chaque défi, le menu Compétences travaillées indique quelles notions il mobilise (un ✗ signale une notion absente du défi). Choisissez vos deux défis de manière à ce qu'ensemble, ils couvrent toutes les notions.
Astuce
Avant de vous lancer dans le code, décrivez en français le déroulement d'une partie : qu'est-ce qui se répète à chaque tour ? qu'est-ce qui ne se fait qu'une fois, au début ou à la fin ? quelles informations le jeu doit-il garder en mémoire ?
Quelques outils supplémentaires#
Les mini-jeux ci-dessous utilisent trois petits outils qui prolongent ce que vous connaissez déjà.
Le module random permet d'introduire du hasard. La fonction randint(a, b) donne un nombre entier aléatoire entre a et b (compris). Pour tirer un élément d'une liste au hasard, il suffit de tirer son index. Exécutez le programme ci-dessous plusieurs fois.
1from random import randint
2
3dé = randint(1, 6)
4print("Le dé affiche", dé)
5
6couleurs = ["rouge", "vert", "bleu"]
7print("Couleur tirée au sort :", couleurs[randint(0, len(couleurs) - 1)])
L'opérateur not in est le contraire de in : il vaut True si l'élément ne fait pas partie de la liste.
1invités = ["Mila", "Loris", "Anja"]
2if "Kilian" not in invités:
3 print("Kilian n'est pas invité")
Un str se manipule presque comme une liste de caractères. On peut connaître sa longueur avec len(), le parcourir caractère par caractère avec un for, et tester si un caractère en fait partie avec in.
1mot = "Fribourg"
2print(len(mot)) # 8 caractères
3for lettre in mot: # parcourt le texte caractère par caractère
4 print(lettre)
5if "o" in mot:
6 print("Il y a un o dans", mot)
Calcul mental#
Compétences travaillées
Notion |
Dans ce défi |
|---|---|
Variables et entrées utilisateur |
calculs, |
Branchements conditionnels |
|
Boucles conditionnelles |
✗ |
Listes et boucles for |
|
Fonctions |
✗ |
Pour aller plus loin ajoute : une fonction avec paramètres et return, une liste et l'indexation.
Pour s'échauffer, programmez un jeu de calcul mental en 10 questions. À chaque question, le jeu tire deux nombres au hasard entre 2 et 12 et demande leur produit. Le jeu compte les bonnes réponses, mais aussi la série en cours (le nombre de bonnes réponses d'affilée), et retient la meilleure série de la partie. À la fin, il affiche le score, la meilleure série, et un message qui dépend du score :
9 ou 10 :
Génie du calcul !6 à 8 :
Pas mal du tout !5 ou moins :
Il est temps de réviser tes livrets...
Question 1 : 7 x 8 = ?
Ta réponse : <-- [56]
Juste ! Série en cours : 1
Question 2 : 12 x 4 = ?
Ta réponse : <-- [48]
Juste ! Série en cours : 2
Question 3 : 9 x 6 = ?
Ta réponse : <-- [56]
Faux, la réponse était 54
...
Score : 8 / 10 - meilleure série : 5
Pas mal du tout !
1from random import randint
2
3#Écrivez votre jeu ici
Solution
1from random import randint
2
3score = 0
4série = 0
5meilleure_série = 0
6
7for question in range(1, 11):
8 a = randint(2, 12)
9 b = randint(2, 12)
10 print("Question", question, ":", a, "x", b, "= ?")
11 réponse = int(input("Ta réponse :"))
12 if réponse == a * b:
13 score = score + 1
14 série = série + 1
15 if série > meilleure_série:
16 meilleure_série = série
17 print("Juste ! Série en cours :", série)
18 else:
19 série = 0
20 print("Faux, la réponse était", a * b)
21
22print("Score :", score, "/ 10 - meilleure série :", meilleure_série)
23if score >= 9:
24 print("Génie du calcul !")
25elif score >= 6:
26 print("Pas mal du tout !")
27else:
28 print("Il est temps de réviser tes livrets...")
Le nombre de questions étant connu à l'avance, une boucle
foravecrange(1, 11)est plus simple qu'unwhile. La variablequestionsert en plus à afficher le numéro de la question.Les deux nombres sont tirés dans la boucle, pour qu'ils changent à chaque question.
Une mauvaise réponse remet la série à 0, mais pas la meilleure série : c'est pour cela qu'il faut deux variables différentes.
Pour aller plus loin
Rendez le jeu plus varié : à chaque question, l'opération est tirée au hasard parmi +, - et
x. Écrivez pour cela une fonction calcule(a, b, opération) qui retourne le résultat de
l'opération demandée.
Solution du bonus
1from random import randint
2
3def calcule(a, b, opération):
4 if opération == "+":
5 return a + b
6 elif opération == "-":
7 return a - b
8 else:
9 return a * b
10
11opérations = ["+", "-", "x"]
12score = 0
13série = 0
14meilleure_série = 0
15
16for question in range(1, 11):
17 a = randint(2, 12)
18 b = randint(2, 12)
19 opération = opérations[randint(0, 2)]
20 print("Question", question, ":", a, opération, b, "= ?")
21 réponse = int(input("Ta réponse :"))
22 if réponse == calcule(a, b, opération):
23 score = score + 1
24 série = série + 1
25 if série > meilleure_série:
26 meilleure_série = série
27 print("Juste ! Série en cours :", série)
28 else:
29 série = 0
30 print("Faux, la réponse était", calcule(a, b, opération))
31
32print("Score :", score, "/ 10 - meilleure série :", meilleure_série)
Pierre, feuille, ciseaux#
Compétences travaillées
Notion |
Dans ce défi |
|---|---|
Variables et entrées utilisateur |
|
Branchements conditionnels |
|
Boucles conditionnelles |
|
Listes et boucles for |
indexation, |
Fonctions |
paramètres et |
Pour aller plus loin ajoute : une liste de listes, for ... in range(len()).
Programmez une partie de pierre-feuille-ciseaux contre l'ordinateur, en 3 manches gagnantes. Pour rappel, la pierre bat les ciseaux, les ciseaux battent la feuille, et la feuille bat la pierre.
Commencez par écrire une fonction
gagnant(coup_joueur, coup_ordi)qui retourne"joueur","ordi"ou"égalité"selon les deux coups reçus en paramètres. Testez-la avant de continuer :gagnant("pierre", "ciseaux")doit retourner"joueur".Écrivez ensuite le programme principal. À chaque manche, l'utilisateur entre son coup, l'ordinateur joue un coup au hasard, et le score est mis à jour. Un coup qui n'est ni
pierre, nifeuille, niciseauxest refusé. La partie s'arrête dès qu'un des deux joueurs atteint 3 points.
Ton coup ? <-- [pierre]
L'ordinateur joue ciseaux
Tu gagnes la manche ! Score : 1 - 0
Ton coup ? <-- [papier]
Coup invalide !
Ton coup ? <-- [feuille]
L'ordinateur joue feuille
Égalité ! Score : 1 - 0
...
Ton coup ? <-- [ciseaux]
L'ordinateur joue feuille
Tu gagnes la manche ! Score : 3 - 1
Bravo, tu remportes la partie !
1from random import randint
2
3coups = ["pierre", "feuille", "ciseaux"]
4
5def gagnant(coup_joueur, coup_ordi):
6 #Complétez le corps de la fonction
7
8#Écrivez le programme principal ici
Solution
1from random import randint
2
3coups = ["pierre", "feuille", "ciseaux"]
4
5def gagnant(coup_joueur, coup_ordi):
6 if coup_joueur == coup_ordi:
7 return "égalité"
8 elif (coup_joueur == "pierre" and coup_ordi == "ciseaux") or (coup_joueur == "ciseaux" and coup_ordi == "feuille") or (coup_joueur == "feuille" and coup_ordi == "pierre"):
9 return "joueur"
10 else:
11 return "ordi"
12
13points_joueur = 0
14points_ordi = 0
15
16while points_joueur < 3 and points_ordi < 3:
17 coup_joueur = input("Ton coup ?")
18 if coup_joueur in coups:
19 coup_ordi = coups[randint(0, 2)]
20 print("L'ordinateur joue", coup_ordi)
21 résultat = gagnant(coup_joueur, coup_ordi)
22 if résultat == "joueur":
23 points_joueur = points_joueur + 1
24 print("Tu gagnes la manche ! Score :", points_joueur, "-", points_ordi)
25 elif résultat == "ordi":
26 points_ordi = points_ordi + 1
27 print("L'ordinateur gagne la manche ! Score :", points_joueur, "-", points_ordi)
28 else:
29 print("Égalité ! Score :", points_joueur, "-", points_ordi)
30 else:
31 print("Coup invalide !")
32
33if points_joueur == 3:
34 print("Bravo, tu remportes la partie !")
35else:
36 print("Dommage, l'ordinateur remporte la partie...")
La fonction ne fait que décider du gagnant : elle n'affiche rien et ne modifie pas le score. Le programme principal récupère sa valeur de retour et s'occupe du reste.
Le coup de l'ordinateur est tiré en choisissant un index au hasard entre 0 et 2.
La boucle continue tant que personne n'a atteint 3 points : il faut donc que les deux scores soient inférieurs à 3, d'où le
and.
Pour aller plus loin
Ajoutez un quatrième et un cinquième coup, comme dans la version pierre-feuille-ciseaux-lézard-Spock : les ciseaux coupent la feuille, la feuille recouvre la pierre, la pierre écrase le lézard, le lézard empoisonne Spock, Spock casse les ciseaux, les ciseaux décapitent le lézard, le lézard mange la feuille, la feuille désavoue Spock, Spock vaporise la pierre, et la pierre écrase les ciseaux. Quelle partie du programme faut-il modifier ? Pouvez-vous éviter d'écrire une condition géante ?
Solution du bonus
1from random import randint
2
3coups = ["pierre", "feuille", "ciseaux", "lézard", "spock"]
4
5# victoires[i] contient la liste des coups battus par coups[i]
6victoires = [["ciseaux", "lézard"], # pierre
7 ["pierre", "spock"], # feuille
8 ["feuille", "lézard"], # ciseaux
9 ["spock", "feuille"], # lézard
10 ["ciseaux", "pierre"]] # spock
11
12def gagnant(coup_joueur, coup_ordi):
13 if coup_joueur == coup_ordi:
14 return "égalité"
15 for i in range(len(coups)):
16 if coups[i] == coup_joueur:
17 if coup_ordi in victoires[i]:
18 return "joueur"
19 return "ordi"
20
21print(gagnant("spock", "pierre")) # joueur
22print(gagnant("lézard", "ciseaux")) # ordi
23print(gagnant("feuille", "feuille")) # égalité
Seule la fonction gagnant doit changer : le programme principal reste identique, il suffit
d'ajouter les nouveaux coups dans la liste coups (et de remplacer randint(0, 2) par
randint(0, len(coups) - 1)). Plutôt que d'écrire dix conditions, on range les règles dans une
liste de listes : victoires[i] contient les coups battus par coups[i].
La chasse au trésor#
Compétences travaillées
Notion |
Dans ce défi |
|---|---|
Variables et entrées utilisateur |
calculs, |
Branchements conditionnels |
|
Boucles conditionnelles |
|
Listes et boucles for |
✗ |
Fonctions |
paramètres et |
Pour aller plus loin ajoute : listes (append, indexation), for ... in range(len()), boucles imbriquées.
Un trésor est enterré sur une île de 10 x 10 cases. Sa position (une colonne et une ligne entre 1 et 10) est tirée au hasard au début de la partie. Le joueur dispose de 6 pelles : à chaque essai, il choisit une case où creuser. S'il ne trouve pas le trésor, le jeu lui donne un indice selon la distance qui le sépare du trésor, c'est-à-dire le nombre de cases à parcourir horizontalement plus le nombre de cases à parcourir verticalement :
Distance |
Indice |
|---|---|
1 ou 2 |
|
3 ou 4 |
|
5 à 7 |
|
8 et plus |
|
Votre programme contiendra au moins deux fonctions : valeur_absolue(nombre) (la même que dans la page sur les fonctions), qui permet de calculer les écarts sans se soucier de leur signe, et indice(distance), qui retourne le texte de l'indice.
Un trésor est caché sur une île de 10 x 10 cases. Tu as 6 pelles.
Colonne (1 à 10) : <-- [5]
Ligne (1 à 10) : <-- [5]
Tiède - il te reste 5 pelle(s)
Colonne (1 à 10) : <-- [8]
Ligne (1 à 10) : <-- [5]
Chaud - il te reste 4 pelle(s)
Colonne (1 à 10) : <-- [8]
Ligne (1 à 10) : <-- [2]
Brûlant ! - il te reste 3 pelle(s)
Colonne (1 à 10) : <-- [9]
Ligne (1 à 10) : <-- [2]
Trésor trouvé ! Tu es riche !
1from random import randint
2
3trésor_x = randint(1, 10)
4trésor_y = randint(1, 10)
5
6#Écrivez votre jeu ici
Solution
1from random import randint
2
3def valeur_absolue(nombre):
4 if nombre >= 0:
5 return nombre
6 return -nombre
7
8def indice(distance):
9 if distance <= 2:
10 return "Brûlant !"
11 elif distance <= 4:
12 return "Chaud"
13 elif distance <= 7:
14 return "Tiède"
15 else:
16 return "Froid"
17
18trésor_x = randint(1, 10)
19trésor_y = randint(1, 10)
20pelles = 6
21trouvé = False
22
23print("Un trésor est caché sur une île de 10 x 10 cases. Tu as", pelles, "pelles.")
24while pelles > 0 and trouvé == False:
25 x = int(input("Colonne (1 à 10) :"))
26 y = int(input("Ligne (1 à 10) :"))
27 pelles = pelles - 1
28 distance = valeur_absolue(x - trésor_x) + valeur_absolue(y - trésor_y)
29 if distance == 0:
30 trouvé = True
31 else:
32 print(indice(distance), "- il te reste", pelles, "pelle(s)")
33
34if trouvé:
35 print("Trésor trouvé ! Tu es riche !")
36else:
37 print("Plus de pelles... Le trésor était en colonne", trésor_x, "ligne", trésor_y)
La partie peut s'arrêter pour deux raisons : le trésor est trouvé, ou il n'y a plus de pelles. La condition du
whilecombine donc les deux avec unand, et unifaprès la boucle détermine laquelle des deux s'est produite.La variable
trouvéest un booléen qui passe àTruelorsque la distance vaut 0.Sans valeur absolue, un écart de
-3et un écart de+3ne donneraient pas la même distance, alors que le trésor est aussi loin dans les deux cas.
Pour aller plus loin
Avant chaque essai, affichez la carte de l'île, avec un X sur les cases déjà creusées et un .
sur les autres. Pour vous souvenir des trous, rangez leurs colonnes et leurs lignes dans deux
listes trous_x et trous_y.
Solution du bonus
1from random import randint
2
3def valeur_absolue(nombre):
4 if nombre >= 0:
5 return nombre
6 return -nombre
7
8def indice(distance):
9 if distance <= 2:
10 return "Brûlant !"
11 elif distance <= 4:
12 return "Chaud"
13 elif distance <= 7:
14 return "Tiède"
15 else:
16 return "Froid"
17
18trous_x = []
19trous_y = []
20
21def creusé(x, y):
22 for i in range(len(trous_x)):
23 if trous_x[i] == x and trous_y[i] == y:
24 return True
25 return False
26
27def affiche_carte():
28 for y in range(1, 11):
29 ligne = ""
30 for x in range(1, 11):
31 if creusé(x, y):
32 ligne = ligne + "X "
33 else:
34 ligne = ligne + ". "
35 print(ligne)
36
37trésor_x = randint(1, 10)
38trésor_y = randint(1, 10)
39pelles = 6
40trouvé = False
41
42while pelles > 0 and trouvé == False:
43 affiche_carte()
44 x = int(input("Colonne (1 à 10) :"))
45 y = int(input("Ligne (1 à 10) :"))
46 trous_x.append(x)
47 trous_y.append(y)
48 pelles = pelles - 1
49 distance = valeur_absolue(x - trésor_x) + valeur_absolue(y - trésor_y)
50 if distance == 0:
51 trouvé = True
52 else:
53 print(indice(distance), "- il te reste", pelles, "pelle(s)")
54
55if trouvé:
56 print("Trésor trouvé ! Tu es riche !")
57else:
58 print("Plus de pelles... Le trésor était en colonne", trésor_x, "ligne", trésor_y)
Le trou numéro i se trouve en colonne trous_x[i] et en ligne trous_y[i]. La carte est
construite ligne par ligne grâce à une boucle dans une boucle : la boucle extérieure parcourt
les lignes, la boucle intérieure ajoute un caractère par colonne à la variable ligne.
Le Loto#
Compétences travaillées
Notion |
Dans ce défi |
|---|---|
Variables et entrées utilisateur |
|
Branchements conditionnels |
|
Boucles conditionnelles |
|
Listes et boucles for |
|
Fonctions |
✗ |
Pour aller plus loin ajoute : fonctions avec paramètres et return (dont une qui retourne une liste).
Au Swiss Loto, le joueur choisit 6 numéros différents entre 1 et 42, puis 6 numéros sont tirés au sort. Plus le joueur a de bons numéros, plus il gagne d'argent. Programmez une grille de Loto :
Le joueur entre ses 6 numéros un par un. Un numéro hors de la plage 1 à 42, ou déjà choisi, est refusé.
Le jeu tire 6 numéros différents au hasard.
Le jeu affiche le tirage, les bons numéros du joueur et son gain, grâce à la liste
gains:gains[n]est le gain (en CHF) pournbons numéros.
Choisis un numéro entre 1 et 42 : <-- [7]
Choisis un numéro entre 1 et 42 : <-- [13]
Choisis un numéro entre 1 et 42 : <-- [13]
Tu as déjà choisi ce numéro !
Choisis un numéro entre 1 et 42 : <-- [50]
Ce numéro n'existe pas !
Choisis un numéro entre 1 et 42 : <-- [21]
Choisis un numéro entre 1 et 42 : <-- [30]
Choisis un numéro entre 1 et 42 : <-- [38]
Choisis un numéro entre 1 et 42 : <-- [42]
Tes numéros : [7, 13, 21, 30, 38, 42]
Tirage : [30, 2, 13, 41, 7, 19]
Tes bons numéros : [7, 13, 30]
Tu gagnes 10 CHF
1from random import randint
2
3gains = [0, 0, 0, 10, 100, 5000, 1000000]
4
5#Écrivez votre jeu ici
Solution
1from random import randint
2
3gains = [0, 0, 0, 10, 100, 5000, 1000000]
4
5# 1. Choix des numéros du joueur
6mes_numéros = []
7while len(mes_numéros) < 6:
8 n = int(input("Choisis un numéro entre 1 et 42 :"))
9 if n < 1 or n > 42:
10 print("Ce numéro n'existe pas !")
11 elif n in mes_numéros:
12 print("Tu as déjà choisi ce numéro !")
13 else:
14 mes_numéros.append(n)
15print("Tes numéros :", mes_numéros)
16
17# 2. Tirage au sort
18tirage = []
19while len(tirage) < 6:
20 n = randint(1, 42)
21 if n not in tirage:
22 tirage.append(n)
23print("Tirage :", tirage)
24
25# 3. Bons numéros et gain
26bons = []
27for n in mes_numéros:
28 if n in tirage:
29 bons.append(n)
30print("Tes bons numéros :", bons)
31print("Tu gagnes", gains[len(bons)], "CHF")
On ne sait pas à l'avance combien de numéros le joueur va entrer (il peut se tromper) : on répète donc tant que la liste ne contient pas 6 numéros.
Le tirage suit exactement la même logique : un numéro tiré qui est déjà sorti est simplement ignoré, et on recommence jusqu'à en avoir 6.
Le nombre de bons numéros sert directement d'index dans la liste
gains.
Pour aller plus loin
Un joueur décide de jouer les mêmes numéros chaque semaine, à 2.50 CHF la grille, jusqu'à obtenir
au moins 5 bons numéros. Simulez cette situation : combien de semaines (et d'années) faut-il
attendre, et combien d'argent le joueur a-t-il dépensé ? Pour éviter de réécrire du code, créez
une fonction tire_numéros() qui retourne un tirage, et une fonction nb_bons(mes_numéros, tirage) qui retourne le nombre de bons numéros. Exécutez le programme plusieurs fois.
Solution du bonus
1from random import randint
2
3def tire_numéros():
4 tirage = []
5 while len(tirage) < 6:
6 n = randint(1, 42)
7 if n not in tirage:
8 tirage.append(n)
9 return tirage
10
11def nb_bons(mes_numéros, tirage):
12 nombre = 0
13 for n in mes_numéros:
14 if n in tirage:
15 nombre = nombre + 1
16 return nombre
17
18mes_numéros = [7, 13, 21, 30, 38, 42]
19semaines = 1
20while nb_bons(mes_numéros, tire_numéros()) < 5:
21 semaines = semaines + 1
22
23print("Il a fallu", semaines, "semaines, soit environ", int(semaines / 52), "ans.")
24print("Argent dépensé :", semaines * 2.5, "CHF")
En moyenne, il faut attendre plus de 24 000 semaines, soit environ 465 ans... pour un gain de 5000 CHF.
Le jeu du cochon#
Compétences travaillées
Notion |
Dans ce défi |
|---|---|
Variables et entrées utilisateur |
|
Branchements conditionnels |
|
Boucles conditionnelles |
|
Listes et boucles for |
✗ |
Fonctions |
fonctions sans paramètre, |
Pour aller plus loin ajoute : un paramètre de fonction.
Le jeu du cochon est un jeu de dés qui se joue à deux, ici contre l'ordinateur. Le premier à atteindre 50 points gagne. À son tour, un joueur lance un dé autant de fois qu'il le souhaite, et additionne les résultats :
s'il décide de s'arrêter, il garde les points de son tour, qui s'ajoutent à son score ;
mais s'il fait un 1, il perd tous les points de son tour, et c'est au tour de l'adversaire !
Tout l'intérêt du jeu est donc de savoir quand s'arrêter. L'ordinateur, lui, suit une stratégie simple : il relance tant que le total de son tour est inférieur à 15.
Votre programme contiendra deux fonctions : tour_joueur() et tour_ordi(), qui jouent chacune un tour complet et retournent le nombre de points gagnés pendant ce tour.
*** Ton tour *** Score : 0 contre 0
Tu fais 4 - total du tour : 4
Relancer (l) ou garder (g) ? <-- [l]
Tu fais 6 - total du tour : 10
Relancer (l) ou garder (g) ? <-- [g]
*** Tour de l'ordinateur ***
L'ordinateur fait 3 - total du tour : 3
L'ordinateur fait 1 et perd les points de ce tour !
*** Ton tour *** Score : 10 contre 0
Tu fais 1... tu perds les points de ce tour !
*** Tour de l'ordinateur ***
...
Bravo, tu gagnes 52 à 41 !
1from random import randint
2
3def tour_joueur():
4 #Complétez le corps de la fonction
5
6def tour_ordi():
7 #Complétez le corps de la fonction
8
9#Écrivez le programme principal ici
Solution
1from random import randint
2
3def tour_joueur():
4 total_tour = 0
5 choix = "l"
6 while choix == "l":
7 dé = randint(1, 6)
8 if dé == 1:
9 print("Tu fais 1... tu perds les points de ce tour !")
10 return 0
11 total_tour = total_tour + dé
12 print("Tu fais", dé, "- total du tour :", total_tour)
13 choix = input("Relancer (l) ou garder (g) ?")
14 return total_tour
15
16def tour_ordi():
17 total_tour = 0
18 while total_tour < 15:
19 dé = randint(1, 6)
20 if dé == 1:
21 print("L'ordinateur fait 1 et perd les points de ce tour !")
22 return 0
23 total_tour = total_tour + dé
24 print("L'ordinateur fait", dé, "- total du tour :", total_tour)
25 print("L'ordinateur garde ses", total_tour, "points.")
26 return total_tour
27
28score_joueur = 0
29score_ordi = 0
30
31while score_joueur < 50 and score_ordi < 50:
32 print("*** Ton tour *** Score :", score_joueur, "contre", score_ordi)
33 score_joueur = score_joueur + tour_joueur()
34 if score_joueur < 50:
35 print("*** Tour de l'ordinateur ***")
36 score_ordi = score_ordi + tour_ordi()
37
38if score_joueur >= 50:
39 print("Bravo, tu gagnes", score_joueur, "à", score_ordi, "!")
40else:
41 print("L'ordinateur gagne", score_ordi, "à", score_joueur, "...")
Le
return 0à l'intérieur de la boucle met immédiatement fin au tour quand le dé tombe sur 1 : les points accumulés sont perdus, et la suite de la fonction n'est jamais exécutée.Les fonctions ne modifient pas les scores elles-mêmes : elles retournent les points du tour, et c'est le programme principal qui les ajoute au bon score.
Le
if score_joueur < 50évite que l'ordinateur joue encore un tour alors que le joueur a déjà gagné.
Pour aller plus loin
L'ordinateur n'est pas très malin : même lorsque les points de son tour lui suffisent déjà pour
atteindre 50, il continue à relancer jusqu'à 15 et risque de tout perdre. Donnez à la fonction
tour_ordi un paramètre score (son score actuel), et faites-le s'arrêter dès que
score + total_tour atteint 50.
Solution du bonus
1from random import randint
2
3def tour_ordi(score):
4 total_tour = 0
5 while total_tour < 15 and score + total_tour < 50:
6 dé = randint(1, 6)
7 if dé == 1:
8 print("L'ordinateur fait 1 et perd les points de ce tour !")
9 return 0
10 total_tour = total_tour + dé
11 print("L'ordinateur fait", dé, "- total du tour :", total_tour)
12 print("L'ordinateur garde ses", total_tour, "points.")
13 return total_tour
14
15print(tour_ordi(45)) # l'ordinateur s'arrête dès qu'il a au moins 5 points
Dans le programme principal, l'appel devient alors score_ordi = score_ordi + tour_ordi(score_ordi).
Le pendu#
Compétences travaillées
Notion |
Dans ce défi |
|---|---|
Variables et entrées utilisateur |
|
Branchements conditionnels |
|
Boucles conditionnelles |
|
Listes et boucles for |
|
Fonctions |
paramètres et |
Pour aller plus loin ajoute : len() sur un str, for ... in range().
Programmez le jeu du pendu. L'ordinateur choisit un mot au hasard dans une liste, et le joueur doit le deviner en proposant des lettres une par une. À chaque tour, le jeu affiche le mot avec les lettres déjà trouvées et des _ à la place des autres. Le joueur a droit à 7 erreurs ; une lettre déjà proposée ne compte pas comme une erreur, mais le jeu le signale.
Votre programme contiendra deux fonctions :
mot_masqué(mot, lettres)qui retourne le mot à afficher, par exemple"_ r _ _ o _ r _ "pour le motfribourgsi les lettres proposées sont["r", "o", "z"];mot_trouvé(mot, lettres)qui retourneTruesi toutes les lettres du mot ont été trouvées, etFalsesinon.
_ _ _ _ _ _ - vies : 7
Propose une lettre : <-- [e]
Raté !
_ _ _ _ _ _ - vies : 6
Propose une lettre : <-- [o]
Bien vu !
_ _ _ _ o _ - vies : 6
Propose une lettre : <-- [o]
Tu as déjà proposé cette lettre !
_ _ _ _ o _ - vies : 6
...
Bravo, le mot était bien python
1from random import randint
2
3mots = ["python", "fribourg", "ordinateur", "fondue", "clavier", "girafe", "chocolat", "trampoline"]
4mot = mots[randint(0, len(mots) - 1)]
5
6def mot_masqué(mot, lettres):
7 #Complétez le corps de la fonction
8
9def mot_trouvé(mot, lettres):
10 #Complétez le corps de la fonction
11
12#Écrivez le programme principal ici
Solution
1from random import randint
2
3mots = ["python", "fribourg", "ordinateur", "fondue", "clavier", "girafe", "chocolat", "trampoline"]
4mot = mots[randint(0, len(mots) - 1)]
5
6def mot_masqué(mot, lettres):
7 résultat = ""
8 for lettre in mot:
9 if lettre in lettres:
10 résultat = résultat + lettre + " "
11 else:
12 résultat = résultat + "_ "
13 return résultat
14
15def mot_trouvé(mot, lettres):
16 for lettre in mot:
17 if lettre not in lettres:
18 return False
19 return True
20
21lettres_proposées = []
22vies = 7
23
24while vies > 0 and mot_trouvé(mot, lettres_proposées) == False:
25 print(mot_masqué(mot, lettres_proposées) + "- vies :", vies)
26 lettre = input("Propose une lettre :")
27 if lettre in lettres_proposées:
28 print("Tu as déjà proposé cette lettre !")
29 else:
30 lettres_proposées.append(lettre)
31 if lettre in mot:
32 print("Bien vu !")
33 else:
34 vies = vies - 1
35 print("Raté !")
36
37if vies > 0:
38 print("Bravo, le mot était bien", mot)
39else:
40 print("Pendu ! Le mot était", mot)
mot_masquéconstruit le texte à afficher caractère par caractère, en partant d'un texte vide""auquel on ajoute soit la lettre, soit un_.Dans
mot_trouvé, il suffit d'une seule lettre non trouvée pour que le mot ne soit pas trouvé : la fonction retourne alorsFalseimmédiatement. Elle ne retourneTruequ'après avoir vérifié toutes les lettres, donc après la boucle.Toutes les lettres proposées sont rangées dans la même liste, qu'elles soient bonnes ou non : c'est ce qui permet de détecter les lettres déjà proposées.
Pour aller plus loin
Ajoutez un mode deux joueurs : au début de la partie, le premier joueur entre le mot à faire deviner, puis le programme affiche 30 lignes vides pour le cacher avant que le second joueur ne commence. Refusez aussi les propositions qui ne font pas exactement une lettre.
Solution du bonus
1def mot_masqué(mot, lettres):
2 résultat = ""
3 for lettre in mot:
4 if lettre in lettres:
5 résultat = résultat + lettre + " "
6 else:
7 résultat = résultat + "_ "
8 return résultat
9
10def mot_trouvé(mot, lettres):
11 for lettre in mot:
12 if lettre not in lettres:
13 return False
14 return True
15
16mot = input("Joueur 1, entre le mot à faire deviner :")
17for i in range(30):
18 print()
19
20lettres_proposées = []
21vies = 7
22
23while vies > 0 and mot_trouvé(mot, lettres_proposées) == False:
24 print(mot_masqué(mot, lettres_proposées) + "- vies :", vies)
25 lettre = input("Joueur 2, propose une lettre :")
26 if len(lettre) != 1:
27 print("Propose exactement une lettre !")
28 elif lettre in lettres_proposées:
29 print("Tu as déjà proposé cette lettre !")
30 else:
31 lettres_proposées.append(lettre)
32 if lettre in mot:
33 print("Bien vu !")
34 else:
35 vies = vies - 1
36 print("Raté !")
37
38if vies > 0:
39 print("Bravo, le mot était bien", mot)
40else:
41 print("Pendu ! Le mot était", mot)
Le mot n'est plus tiré au hasard : la ligne qui le choisissait est remplacée par un
input, et l'import derandintdevient inutile.Un
print()sans paramètre affiche une ligne vide : la boucleforen affiche 30 pour faire disparaître le mot de l'écran.Le contrôle de la longueur est placé en premier : une proposition invalide n'est ni ajoutée à la liste, ni comptée comme une erreur.
Le blackjack#
Compétences travaillées
Notion |
Dans ce défi |
|---|---|
Variables et entrées utilisateur |
|
Branchements conditionnels |
|
Boucles conditionnelles |
|
Listes et boucles for |
|
Fonctions |
paramètres et |
Pour aller plus loin ajoute : input() avec conversion int(), une boucle while imbriquée.
Au blackjack, le but est d'obtenir un total de cartes le plus proche possible de 21, sans le dépasser. Programmez une version simplifiée, dans laquelle chaque carte tirée vaut entre 1 et 10 (les valets, dames et rois valent 10, l'as vaut toujours 1) :
Le joueur reçoit deux cartes. Tant que son total est inférieur à 21, il peut demander une carte supplémentaire. S'il dépasse 21, il perd immédiatement.
Sinon, c'est au tour du croupier : il reçoit deux cartes, puis tire des cartes tant que son total est inférieur à 17.
Si le croupier dépasse 21, ou si le joueur a un meilleur total, le joueur gagne. En cas de totaux égaux, il y a égalité.
Votre programme contiendra au moins deux fonctions : tire_carte(), qui retourne la valeur d'une carte tirée au hasard, et total(main), qui retourne le total d'une liste de cartes.
Tes cartes : [7, 10] - total : 17
Une autre carte ? (o/n) <-- [o]
Tes cartes : [7, 10, 3] - total : 20
Une autre carte ? (o/n) <-- [n]
Cartes du croupier : [10, 4, 5] - total : 19
Tu as gagné !
1from random import randint
2
3def tire_carte():
4 #Une carte entre 1 et 13 (as, 2 à 10, valet, dame, roi)
5 carte = randint(1, 13)
6 #Complétez le corps de la fonction
7
8def total(main):
9 #Complétez le corps de la fonction
10
11#Écrivez le programme principal ici
Solution
1from random import randint
2
3def tire_carte():
4 #Une carte entre 1 et 13 (as, 2 à 10, valet, dame, roi)
5 carte = randint(1, 13)
6 if carte > 10:
7 return 10
8 return carte
9
10def total(main):
11 somme = 0
12 for carte in main:
13 somme = somme + carte
14 return somme
15
16# Tour du joueur
17main_joueur = [tire_carte(), tire_carte()]
18print("Tes cartes :", main_joueur, "- total :", total(main_joueur))
19choix = "o"
20while choix == "o" and total(main_joueur) < 21:
21 choix = input("Une autre carte ? (o/n)")
22 if choix == "o":
23 main_joueur.append(tire_carte())
24 print("Tes cartes :", main_joueur, "- total :", total(main_joueur))
25
26# Tour du croupier et résultat
27if total(main_joueur) > 21:
28 print("Tu dépasses 21, tu as perdu !")
29else:
30 main_croupier = [tire_carte(), tire_carte()]
31 while total(main_croupier) < 17:
32 main_croupier.append(tire_carte())
33 print("Cartes du croupier :", main_croupier, "- total :", total(main_croupier))
34 if total(main_croupier) > 21 or total(main_joueur) > total(main_croupier):
35 print("Tu as gagné !")
36 elif total(main_joueur) == total(main_croupier):
37 print("Égalité !")
38 else:
39 print("Le croupier gagne...")
Les cartes de chaque joueur sont rangées dans une liste, que l'on complète avec
appendà chaque nouvelle carte. La fonctiontotalpermet de recalculer le total à tout moment.Les valets, dames et rois correspondent aux valeurs 11, 12 et 13 tirées par
randint: leifdetire_carteles ramène à 10.Le croupier ne joue que si le joueur n'a pas dépassé 21 : dans le cas contraire, la partie est déjà perdue.
Pour aller plus loin
Ajoutez des jetons : le joueur commence avec 100 jetons. Avant chaque manche, il mise un
certain nombre de jetons (pas plus que ce qu'il possède). S'il gagne la manche, il remporte sa
mise ; s'il perd, il la perd. Le jeu enchaîne les manches jusqu'à ce que le joueur n'ait plus de
jetons ou décide d'arrêter. Indice : placez une manche complète dans une fonction manche() qui
retourne "joueur", "croupier" ou "égalité".
Solution du bonus
1from random import randint
2
3def tire_carte():
4 carte = randint(1, 13)
5 if carte > 10:
6 return 10
7 return carte
8
9def total(main):
10 somme = 0
11 for carte in main:
12 somme = somme + carte
13 return somme
14
15def manche():
16 main_joueur = [tire_carte(), tire_carte()]
17 print("Tes cartes :", main_joueur, "- total :", total(main_joueur))
18 choix = "o"
19 while choix == "o" and total(main_joueur) < 21:
20 choix = input("Une autre carte ? (o/n)")
21 if choix == "o":
22 main_joueur.append(tire_carte())
23 print("Tes cartes :", main_joueur, "- total :", total(main_joueur))
24
25 if total(main_joueur) > 21:
26 print("Tu dépasses 21 !")
27 return "croupier"
28
29 main_croupier = [tire_carte(), tire_carte()]
30 while total(main_croupier) < 17:
31 main_croupier.append(tire_carte())
32 print("Cartes du croupier :", main_croupier, "- total :", total(main_croupier))
33 if total(main_croupier) > 21 or total(main_joueur) > total(main_croupier):
34 return "joueur"
35 elif total(main_joueur) == total(main_croupier):
36 return "égalité"
37 else:
38 return "croupier"
39
40jetons = 100
41continuer = "o"
42
43while jetons > 0 and continuer == "o":
44 print("Tu as", jetons, "jetons.")
45 mise = int(input("Combien de jetons mises-tu ?"))
46 while mise < 1 or mise > jetons:
47 mise = int(input("Mise invalide ! Combien de jetons mises-tu ?"))
48
49 résultat = manche()
50 if résultat == "joueur":
51 jetons = jetons + mise
52 print("Tu gagnes la manche et remportes", mise, "jetons !")
53 elif résultat == "croupier":
54 jetons = jetons - mise
55 print("Le croupier gagne la manche, tu perds", mise, "jetons.")
56 else:
57 print("Égalité, tu récupères ta mise.")
58
59 if jetons > 0:
60 continuer = input("Nouvelle manche ? (o/n)")
61
62if jetons == 0:
63 print("Tu n'as plus de jetons... La partie est terminée !")
64else:
65 print("Tu quittes la table avec", jetons, "jetons.")
La manche du challenge précédent est déplacée telle quelle dans la fonction
manche(). Au lieu d'afficher le résultat, elle le retourne, ce qui permet au programme principal de mettre à jour les jetons.Le
return "croupier"placé juste après le dépassement de 21 met fin à la manche : le croupier ne joue alors même pas.Une deuxième boucle
whileredemande la mise tant qu'elle n'est pas valide.On ne propose une nouvelle manche que s'il reste des jetons : sinon, la boucle principale s'arrête d'elle-même.
Le Tamagotchi#
Compétences travaillées
Notion |
Dans ce défi |
|---|---|
Variables et entrées utilisateur |
calculs, |
Branchements conditionnels |
|
Boucles conditionnelles |
|
Listes et boucles for |
|
Fonctions |
paramètres, avec et sans |
Pour aller plus loin ajoute : une fonction de plus avec plusieurs return.
Pour terminer, programmez votre propre Tamagotchi, un petit animal virtuel dont il faut prendre soin pendant 15 jours. L'animal a trois jauges, notées de 0 à 10 : la satiété, l'énergie et le bonheur. Toutes commencent à 6. Si l'une d'entre elles tombe à 0, l'animal s'enfuit et la partie est perdue.
Chaque jour se déroule de la manière suivante :
Le jeu affiche le numéro du jour et les trois jauges sous la forme de barres, par exemple
Satiété : ######---- 6 / 10.Le joueur choisit une action :
manger: satiété +4, énergie -1dormir: énergie +4, satiété -1jouer: bonheur +4, énergie -1toute autre réponse : l'animal ne comprend pas et boude (bonheur -2)
Le temps passe : les trois jauges perdent 1 point.
Une fois sur cinq (au hasard), l'animal attrape un rhume et perd 2 points d'énergie.
Une jauge ne peut jamais dépasser 10 ni descendre sous 0.
Votre programme contiendra au moins deux fonctions : affiche_jauge(nom, valeur), qui affiche une jauge sous forme de barre, et limite(valeur), qui retourne la valeur ramenée entre 0 et 10.
Comment s'appelle ton animal ? <-- [Pixel]
=== Jour 1 ===
Satiété : ######---- 6 / 10
Énergie : ######---- 6 / 10
Bonheur : ######---- 6 / 10
Que fait Pixel ? (manger / dormir / jouer) <-- [jouer]
=== Jour 2 ===
Satiété : #####----- 5 / 10
Énergie : ####------ 4 / 10
Bonheur : #########- 9 / 10
Que fait Pixel ? (manger / dormir / jouer) <-- [dormir]
Oh non, Pixel a attrapé un rhume ! (-2 énergie)
=== Jour 3 ===
...
Bravo ! Pixel a survécu 15 jours grâce à toi !
1from random import randint
2
3#Écrivez votre jeu ici
Solution
1from random import randint
2
3def limite(valeur):
4 if valeur > 10:
5 return 10
6 elif valeur < 0:
7 return 0
8 return valeur
9
10def affiche_jauge(nom, valeur):
11 barre = ""
12 for i in range(10):
13 if i < valeur:
14 barre = barre + "#"
15 else:
16 barre = barre + "-"
17 print(nom, barre, valeur, "/ 10")
18
19nom = input("Comment s'appelle ton animal ?")
20satiété = 6
21énergie = 6
22bonheur = 6
23jour = 1
24
25while jour <= 15 and satiété > 0 and énergie > 0 and bonheur > 0:
26 print("=== Jour", jour, "===")
27 affiche_jauge("Satiété :", satiété)
28 affiche_jauge("Énergie :", énergie)
29 affiche_jauge("Bonheur :", bonheur)
30
31 # Action du joueur
32 action = input("Que fait " + nom + " ? (manger / dormir / jouer)")
33 if action == "manger":
34 satiété = satiété + 4
35 énergie = énergie - 1
36 elif action == "dormir":
37 énergie = énergie + 4
38 satiété = satiété - 1
39 elif action == "jouer":
40 bonheur = bonheur + 4
41 énergie = énergie - 1
42 else:
43 print(nom, "ne comprend pas et boude.")
44 bonheur = bonheur - 2
45
46 # Le temps passe
47 satiété = satiété - 1
48 énergie = énergie - 1
49 bonheur = bonheur - 1
50
51 # Événement aléatoire
52 if randint(1, 5) == 1:
53 print("Oh non,", nom, "a attrapé un rhume ! (-2 énergie)")
54 énergie = énergie - 2
55
56 satiété = limite(satiété)
57 énergie = limite(énergie)
58 bonheur = limite(bonheur)
59 jour = jour + 1
60
61if satiété > 0 and énergie > 0 and bonheur > 0:
62 print("Bravo !", nom, "a survécu 15 jours grâce à toi !")
63else:
64 print("Oh non,", nom, "s'est enfui...")
La boucle s'arrête soit après le 15ème jour, soit dès qu'une jauge tombe à 0. Après la boucle, on teste les jauges pour savoir laquelle des deux situations s'est produite.
Dans
affiche_jauge, la barre contient toujours 10 caractères : la boucle ajoute un#pour chaque point de la jauge, puis des-pour compléter.Les jauges ne sont ramenées entre 0 et 10 qu'à la fin de la journée, une fois toutes les modifications effectuées. C'est plus simple que d'appeler
limiteaprès chaque calcul.Le texte de l'
inputest construit en collant plusieursstravec+, carinput()ne prend qu'un seul texte en paramètre.
Pour aller plus loin
Faites grandir votre animal : il est un œuf les jours 1 à 3, un bébé les jours 4 à 7, un
ado les jours 8 à 11, puis un adulte. Affichez son stade au début de chaque jour. Ajoutez
ensuite une quatrième jauge, la propreté, avec l'action laver correspondante. Le jeu
reste-t-il gagnable ?
Solution du bonus
1from random import randint
2
3def limite(valeur):
4 if valeur > 10:
5 return 10
6 elif valeur < 0:
7 return 0
8 return valeur
9
10def affiche_jauge(nom, valeur):
11 barre = ""
12 for i in range(10):
13 if i < valeur:
14 barre = barre + "#"
15 else:
16 barre = barre + "-"
17 print(nom, barre, valeur, "/ 10")
18
19def stade(jour):
20 if jour <= 3:
21 return "œuf"
22 elif jour <= 7:
23 return "bébé"
24 elif jour <= 11:
25 return "ado"
26 else:
27 return "adulte"
28
29nom = input("Comment s'appelle ton animal ?")
30satiété = 6
31énergie = 6
32bonheur = 6
33propreté = 6
34jour = 1
35
36while jour <= 15 and satiété > 0 and énergie > 0 and bonheur > 0 and propreté > 0:
37 print("=== Jour", jour, "-", nom, "est un", stade(jour), "===")
38 affiche_jauge("Satiété :", satiété)
39 affiche_jauge("Énergie :", énergie)
40 affiche_jauge("Bonheur :", bonheur)
41 affiche_jauge("Propreté :", propreté)
42
43 action = input("Que fait " + nom + " ? (manger / dormir / jouer / laver)")
44 if action == "manger":
45 satiété = satiété + 4
46 énergie = énergie - 1
47 elif action == "dormir":
48 énergie = énergie + 4
49 satiété = satiété - 1
50 elif action == "jouer":
51 bonheur = bonheur + 4
52 énergie = énergie - 1
53 elif action == "laver":
54 propreté = propreté + 4
55 else:
56 print(nom, "ne comprend pas et boude.")
57 bonheur = bonheur - 2
58
59 # Le temps passe (la propreté ne baisse qu'un jour sur deux en moyenne)
60 satiété = satiété - 1
61 énergie = énergie - 1
62 bonheur = bonheur - 1
63 if randint(1, 2) == 1:
64 propreté = propreté - 1
65
66 if randint(1, 5) == 1:
67 print("Oh non,", nom, "a attrapé un rhume ! (-2 énergie)")
68 énergie = énergie - 2
69
70 satiété = limite(satiété)
71 énergie = limite(énergie)
72 bonheur = limite(bonheur)
73 propreté = limite(propreté)
74 jour = jour + 1
75
76if satiété > 0 and énergie > 0 and bonheur > 0 and propreté > 0:
77 print("Bravo !", nom, "est devenu un", stade(15), "en pleine forme !")
78else:
79 print("Oh non,", nom, "s'est enfui...")
La fonction
stadedécoupe les 15 jours en tranches avec une série deelif, de la même manière que les tarifs du zoo.Le jeu reste-t-il gagnable ? Pas si la propreté baisse d'un point chaque jour, comme les autres jauges : avec une seule action par jour pour quatre jauges qui baissent toutes, même en s'occupant chaque jour de la jauge la plus basse, l'animal ne tient presque jamais 15 jours. Il faut donc rééquilibrer le jeu. Ici, la propreté ne baisse qu'une fois sur deux (au hasard) : en s'occupant chaque jour de la jauge la plus basse, on gagne alors environ une partie sur deux, alors qu'en jouant au hasard on perd presque à coup sûr.
Équilibrer un jeu est une vraie partie du travail des développeurs : n'hésitez pas à modifier les valeurs (+4, -1, la probabilité du rhume...) et à tester plusieurs parties pour trouver la difficulté qui vous plaît.