memoire — Un jeu de mémoire

Dans ce jeu, l’utilisateur se voit présenter une suite de directions aléatoires (haut, bas, gauche, droite), et doit ensuite la reproduire en inclinant la carte dans les directions proposées, dans le bon ordre. À chaque fais qu’il réussit, un nouvel élément est ajouté à la liste.

L’algorithme est composé de trois boucles imbriquées.

  • Chaque passage dans la boucle extérieure correspond à une nouvelle partie.

  • Chaque passage dans la boucle intermédiaire correspond à une nouvelle manche (l’affichage d’une suite à mémoriser, et la lecture de la suite proposée par l’utilisateur) ;

  • Chaque passage dans la boucle intérieure correspond à la lecture de la suite proposée par l’utilisateur.

La sortie d’une boucle se fait uniquement avec l’instruction break.

L’algorithme en pseudo-code ressemble à ceci.

while True:

   Attendre que l'utilisateur secoue la carte.

   Initialisation de la partie

   while True:

      Ajout d'une direction à la liste
      Affichage de la liste des directions

      while True:

         Lecture de la liste des directions, en vérifiant la validité au fur et à mesure.
         Si toute la liste est lue, ou qu'une erreur est détectée:
            break

      Si toute la liste a été lue:
         Afficher ☺️
      Sinon
         break

   # Perdu…
   Afficher 💀

Et le vrai code est le suivant.

  1# Copyright 2019 Louis Paternault
  2#
  3# This file is part of Jouets.
  4#
  5# Jouets is free software: you can redistribute it and/or modify
  6# it under the terms of the GNU General Public License as published by
  7# the Free Software Foundation, either version 3 of the License, or
  8# (at your option) any later version.
  9#
 10# Jouets is distributed in the hope that it will be useful,
 11# but WITHOUT ANY WARRANTY; without even the implied warranty of
 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13# GNU General Public License for more details.
 14#
 15# You should have received a copy of the GNU General Public License
 16# along with Jouets.  If not, see <http://www.gnu.org/licenses/>.
 17
 18"""Indique le nord par une flèche."""
 19import random
 20
 21import utime
 22
 23from microbit import *
 24
 25HAUT, BAS, GAUCHE, DROITE, ATTENTE = range(5)
 26
 27ETATS_DIRECTIONS = (HAUT, BAS, GAUCHE, DROITE)
 28MOUVEMENTS = ("up", "left", "right", "down")
 29MOUVEMENT2ETAT = {"up": HAUT, "down": BAS, "left": GAUCHE, "right": DROITE}
 30
 31
 32def affiche_direction(etat):
 33    if etat == HAUT:
 34        display.show(Image.ARROW_S)
 35    elif etat == BAS:
 36        display.show(Image.ARROW_N)
 37    elif etat == GAUCHE:
 38        display.show(Image.ARROW_W)
 39    elif etat == DROITE:
 40        display.show(Image.ARROW_E)
 41
 42
 43def clignote(image):
 44    for i in range(5):
 45        display.show(image)
 46        sleep(100)
 47        display.clear()
 48        sleep(100)
 49
 50
 51display.scroll("Secouer pour commencer.", wait=False, loop=True)
 52
 53while True:
 54    # Début de partie
 55    mouvement = None
 56    while mouvement != "shake":
 57        mouvement = accelerometer.current_gesture()
 58    for i in range(3, 0, -1):
 59        display.show(str(i))
 60        sleep(1000)
 61    display.show("?")
 62
 63    objectif = []
 64
 65    # Nouvelle manche
 66    while True:
 67        # Augmentation et affichage de l'objectif
 68        objectif.append(random.choice(ETATS_DIRECTIONS))
 69        for direction in objectif:
 70            affiche_direction(direction)
 71            sleep(500)
 72            display.clear()
 73            sleep(100)
 74        display.show("?")
 75
 76        # Lecture de la liste donnée par l'utilisateur
 77        etat = ATTENTE
 78        index = 0
 79        debut = 0
 80        while True:
 81            mouvement = accelerometer.current_gesture()
 82
 83            # Changement d'état
 84            if etat == ATTENTE:
 85                if mouvement in MOUVEMENTS:
 86                    debut = utime.ticks_ms()
 87                    etat = MOUVEMENT2ETAT[mouvement]
 88            elif etat in ETATS_DIRECTIONS:
 89                if mouvement in MOUVEMENTS and etat != MOUVEMENT2ETAT[mouvement]:
 90                    debut = utime.ticks_ms()
 91                    etat = MOUVEMENT2ETAT[mouvement]
 92                elif mouvement not in MOUVEMENTS:
 93                    etat = ATTENTE
 94                elif utime.ticks_ms() - debut > 500:
 95                    affiche_direction(etat)
 96                    sleep(500)
 97                    if etat == objectif[index]:
 98                        etat = ATTENTE
 99                        index += 1
100                        if index == len(objectif):
101                            break
102                        display.show("?")
103                    else:
104                        break
105
106        if index == len(objectif):
107            clignote(Image.HAPPY)
108        else:
109            break
110
111    # La seule manière d'arriver là est d'avoir perdu
112    clignote(Image.SKULL)
113    display.scroll("Score: {}".format(len(objectif) - 1), loop=True, wait=False)