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."""
 19from microbit import *
 20import utime
 21import random
 22
 23HAUT, BAS, GAUCHE, DROITE, ATTENTE = range(5)
 24
 25ETATS_DIRECTIONS = (HAUT, BAS, GAUCHE, DROITE)
 26MOUVEMENTS = ("up", "left", "right", "down")
 27MOUVEMENT2ETAT = {"up": HAUT, "down": BAS, "left": GAUCHE, "right": DROITE}
 28
 29
 30def affiche_direction(etat):
 31    if etat == HAUT:
 32        display.show(Image.ARROW_S)
 33    elif etat == BAS:
 34        display.show(Image.ARROW_N)
 35    elif etat == GAUCHE:
 36        display.show(Image.ARROW_W)
 37    elif etat == DROITE:
 38        display.show(Image.ARROW_E)
 39
 40
 41def clignote(image):
 42    for i in range(5):
 43        display.show(image)
 44        sleep(100)
 45        display.clear()
 46        sleep(100)
 47
 48
 49display.scroll("Secouer pour commencer.", wait=False, loop=True)
 50
 51while True:
 52    # Début de partie
 53    mouvement = None
 54    while mouvement != "shake":
 55        mouvement = accelerometer.current_gesture()
 56    for i in range(3, 0, -1):
 57        display.show(str(i))
 58        sleep(1000)
 59    display.show("?")
 60
 61    objectif = []
 62
 63    # Nouvelle manche
 64    while True:
 65        # Augmentation et affichage de l'objectif
 66        objectif.append(random.choice(ETATS_DIRECTIONS))
 67        for direction in objectif:
 68            affiche_direction(direction)
 69            sleep(500)
 70            display.clear()
 71            sleep(100)
 72        display.show("?")
 73
 74        # Lecture de la liste donnée par l'utilisateur
 75        etat = ATTENTE
 76        index = 0
 77        debut = 0
 78        while True:
 79            mouvement = accelerometer.current_gesture()
 80
 81            # Changement d'état
 82            if etat == ATTENTE:
 83                if mouvement in MOUVEMENTS:
 84                    debut = utime.ticks_ms()
 85                    etat = MOUVEMENT2ETAT[mouvement]
 86            elif etat in ETATS_DIRECTIONS:
 87                if mouvement in MOUVEMENTS and etat != MOUVEMENT2ETAT[mouvement]:
 88                    debut = utime.ticks_ms()
 89                    etat = MOUVEMENT2ETAT[mouvement]
 90                elif mouvement not in MOUVEMENTS:
 91                    etat = ATTENTE
 92                elif utime.ticks_ms() - debut > 500:
 93                    affiche_direction(etat)
 94                    sleep(500)
 95                    if etat == objectif[index]:
 96                        etat = ATTENTE
 97                        index += 1
 98                        if index == len(objectif):
 99                            break
100                        display.show("?")
101                    else:
102                        break
103
104        if index == len(objectif):
105            clignote(Image.HAPPY)
106        else:
107            break
108
109    # La seule manière d'arriver là est d'avoir perdu
110    clignote(Image.SKULL)
111    display.scroll("Score: {}".format(len(objectif) - 1), loop=True, wait=False)