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#

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

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.

Pierre, feuille, ciseaux#

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.

  1. 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".

  2. É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, ni feuille, ni ciseaux est 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

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 ?

La chasse au trésor#

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

Brûlant !

3 ou 4

Chaud

5 à 7

Tiède

8 et plus

Froid

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

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.

Le Loto#

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 :

  1. 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é.

  2. Le jeu tire 6 numéros différents au hasard.

  3. 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) pour n bons 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

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.

Le jeu du cochon#

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

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.

Le pendu#

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 mot fribourg si les lettres proposées sont ["r", "o", "z"] ;

  • mot_trouvé(mot, lettres) qui retourne True si toutes les lettres du mot ont été trouvées, et False sinon.

_ _ _ _ _ _ - 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

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.

Le blackjack#

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) :

  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.

  2. Sinon, c'est au tour du croupier : il reçoit deux cartes, puis tire des cartes tant que son total est inférieur à 17.

  3. 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

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é".

Le Tamagotchi#

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 :

  1. Le jeu affiche le numéro du jour et les trois jauges sous la forme de barres, par exemple Satiété : ######---- 6 / 10.

  2. Le joueur choisit une action :

    • manger : satiété +4, énergie -1

    • dormir : énergie +4, satiété -1

    • jouer : bonheur +4, énergie -1

    • toute autre réponse : l'animal ne comprend pas et boude (bonheur -2)

  3. Le temps passe : les trois jauges perdent 1 point.

  4. Une fois sur cinq (au hasard), l'animal attrape un rhume et perd 2 points d'énergie.

  5. 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

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 ?