Memory
Durée estimée: 90 minutes
Présentation :
Vous connaissez le jeu : des paires de cartes sont disposées faces cachées. Le joueur retourne une carte puis une seconde qui doit être la même que la première. Sinon, l'essai est compté comme une erreur et les deux cartes sont retournées avant de rejouer.Ce que vous allez faire :
Vous allez réaliser cette application en deux versions.
Dans la première, avec 4 cartes vous allez analyser puis coder tout l'algorithme du jeu. Vous pourrez ensuite augmenter le nombre de cartes en ajoutant du code.
Dans la seconde version, vous augmenterez le nombre de cartes jusqu'à 16, mais avec des boucles, en gérant les boutons dans une liste plutôt que deux par deux. C'est plus difficile, mais plus puissant.
- Vous allez d'abord analyser la manière dont le jeu fonctionne et le décomposer en étapes :
- l'initialisation du jeu, avec le mélange des cartes
- la conduite de chaque partie, avec
- le choix d'une première carte,
- le choix d'une seconde carte,
- la comparaison des deux,
- et les actions à faire selon qu'elles correspondent ou pas,
- Ensuite vous allez passer à la réalisation
- avec la phase de design,
- puis de codage des blocs.
Pré-requis :
Cette application suppose- que vous êtes déjà familiers d'App Inventor, avec deux ou trois réalisations à votre actif,
- que vous ayez déjà utilisé des variables et des boutons,
- que vous ayez une première expérience des listes,
- que vous êtes prêt à passer un peu de temps à analyser (avec un crayon, un papier et une gomme) l'application à réaliser, avant de plonger dans le codage.
Ce que vous allez apprendre :
Avec cette application, vous allez aborder ou approfondir plusieurs notions importantes :
- l'analyse fonctionnelle, le pseudo-code et la réalisation d'un diagramme de flux,
- l'utilisation des listes,
- l'utilisation généralisée des procédures (i.e. l'abstraction procédurale),
- et (dans la version 2) l'utilisation des composants en tant que variables et dans une liste.
Ressources en entrée :
Pour la première version de cette application, vous pouvez créer un projet sur App Inventor, ou cliquer sur le canevas de projet suivant :
http://onvaessayer.org/appinventor?repo=memoryStart1a.
Dans ce canevas :
- les composants ont déjà été sélectionnés et l'interface utilisateur défini, sauf pour les boutons d'images (le premier a été défini mais vous devez créer les trois autres),
- les images ont été importées : 1.png à 8.png pour les cartes et back.png pour une carte cachée,
- du côté programme, les variables sont initialisées,
- et c'est à vous de faire le reste...
(Si vous travaillez en groupe ou dans une classe, conservez ces noms de variables, ça facilitera les échanges.)
Pour la deuxième étape, si vous avez trop de difficultés avec la première, vous pouvez commencer la seconde à partir du projet à l'adresse :
http://onvaessayer.org/appinventor?repo=memoryStart1b.
Faites une copie avant de modifier, par exemple : memoryV1 et ajoutez vos intiales au nom du projet si vous êtes en groupe, (suivez les indications de votre animateur).
Réalisation
Vidéo 1° partie : analyse et démarrage
Vidéo 2° partie : codage de la préparation d'une partie
Vidéo 3° partie : codage de chaque partie, tests,debug
Vidéo 4° partie : augmentation du nombre de cases
Analyse et décomposition fonctionnelle :
Cette application est moins facile qu'elle en a l'air. Vous devez commencer par l'analyser et décrire précisément ce qu'elle doit faire, sinon vous aurez du mal à la fin.Avant de lire la suite, prenez un papier, un crayon et une gomme et décrivez précisément ce que fait l'application, comme si vous deviez l'expliquer à quelqu'un qui ne connait pas le jeu.
- Préparer et lancer une partie :
- choisir plusieurs paires de cartes ou d'images identiques (2 paires pour commencer),
- mélanger les cartes,
- distribuer les cartes en lignes et colonnes, faces cachées.
- Conduire d'une partie :
Une partie est une série d'essais dont chacun se déroule de la façon suivante :- le joueur retourne une première carte,
- puis une seconde carte (ce qui compte pour un essai),
- Si les images sont les mêmes : elles sont laissées apparentes,
- Si les images sont différentes :
- cet essai compte pour une erreur,
- les cartes sont laissées apparentes, le temps pour le joueur de s'en rappeler,
- puis les deux cartes sont remises face cachée.
Dans cette version, chaque joueur fait une partie complète. Celui qui a terminé avec le plus petit nombre d'erreurs ou d'essais a gagné.
Modélisation et diagramme des flux :
Dans notre cas, les cartes sont des boutons disposés dans un tableau. L'image affichée pour chaque bouton est son image de fond (background image). Quand la carte est cachée, l'image de fond est celle du dos des cartes (back.png), et quand elle est visible, l'image de fond est celle tirée au sort pour cette case du tableau (1.png ou 2.png). Le joueur va cliquer sur les boutons pour retourner la carte.
Avant de coder, nous allons expliciter les enchainements :
- avec un graphique : le diagramme de flux
- et dans un langage algorithmique plus proche de l'ordinateur : le pseudo-code.
Prenez le temps de le faire ce diagramme soigneusement, parcourez le avec le doigt en lisant à voix haute l'enchainement des opérations, envisagez tous les cas possibles. Posez lui des questions et vérifiez qu'il contient les réponses :
- oui mais si ... je clique sur le bouton recommencer pendant la partie ?
- oui mais si ... je clique sur une image déjà affichée ?
- oui mais si ...
Ensuite ou en même temps, explicitez dans un langage clair mais plus proche de l'ordinateur (pseudo-code) ce que fait chaque bloc fonctionnel ou fonction.
Pseudo-code :
- Quand je lance une partie :
- mettre en forme le tableau (qui contient une carte ou bouton par case),
- mettre les cartes face cachée,
- choisir des paires d'images et les affecter les images au hasard aux boutons du tableau,
- activer les boutons qui sont face cachée, pour pouvoir cliquer et vor l'image,
- remettre les compteurs à 0 (nombre d'esais, nombre d'erreurs).
- Quand je clique sur une carte (ou bouton) :
- afficher l'image de cette carte,
- si c'est la première carte retournée :
- enregistrer son numéro comme celui de la première carte,
et continuer (attendre le prochain clic).
- enregistrer son numéro comme celui de la première carte,
- si c'est la seconde carte retournée :
- ajouter 1 au nombre d'essais,
- enregistrer son numéro comme celui de la deuxième carte,
- Examiner si les images des deux cartes sont les mêmes
Si oui :- ajouter 2 au nombre d'images trouvées,
- remettre à 0 les numéros de cartes retournées,
- si toutes les cartes ont été trouvées, dire au joueur qu'il a gagné,
sinon continuer (attendre le prochain clic).
- ajouter 1 au nombre d'erreurs,
- faire vibrer le smartphone pour indiquer l'erreur,
- afficher un bouton que le joueur devra cliquer pour continuer,
- et quand le joueur clique sur ce bouton
(après avoir pris le temps de regarder les images pour s'en rappeler)- masquer les deux cartes retournées,
- remettre à 0 les numéros de cartes retournées,
- masquer le bouton et continuer(attendre le prochain clic).
Cette description s'appelle le pseudo-code
Variables de l'application (revue préliminaire):
Avant de passer au design, il est intéressant de réfléchir aux paramètres et variables qui définissent l'état de l'application à un moment donné. Vous pouvez le faire maintenant ou en même temps que le design de l'interface.- listeDesImagesARépartirDansLesCases :
c’est la liste des images à afficher. Ce sont des paires que l'on va ensuite répartir au hasard dans les cases du tableau - listeDesImagesDeCases :
c'est la liste des images dans les cases du tableau. Ces cases sont numérotées en partant de la première ligne à gauche, de gauche à droite puis ligne suivante pour les 4 premières. Pour les suivantes (version 2 de l'aplication) la numérotation est adaptée pour des tableaux pour 4,6,8,12 ou 16 cartes. - numeroCaseChoix1 :
le numéro de la case dévoilée en premier, à chaque essai.
Quand on n’a pas encore fait le premier choix, cette variable vaut 0. - numeroCaseChoix2 :
le numéro de la case dévoilée en second, à chaque essai.
On va alors comparer l’image de cette 2° case avec celle de la première - imageDuChoix1 :
le nom de l’image qui est dans la première case choisie,
On la trouve dans la liste listeImagesDeCases à l’index numeroCaseChoix1 - imageDuChoix2 :
le nom de l’image qui est dans la deuxième case choisie,
On la trouve dans la liste listeImagesDeCases à l’index numeroCaseChoix2 - Le tableau est défini par un nombre de colonnes et un nombre de lignes, dans la première version :
NOMBRE_DE_LIGNES = 2
NOMBRE_DE_COLONNES = 2
nombreDeCasesUtilisées = nombre de lignes * nombre de colonnes = 4
Ces variables ne sont pas indispensables dans la première version, mais il vaut mieux les prévoir pour agrandir le tableau. Nous en aurons par ailleurs besoin dans la deuxième version. Dans ce cas, avec les tableaux 3x3 le nombre de cases du tableau peut-être impair et nous distinguerons alors le nombreDeCasesAffichées et le nombreDeCasesUtilisées
Il fauda être vigilant au fait que la longueur des listes d'images et bien égal au nombreDeCasesUtilisées.
Design de l'application :
Le design de l'interafce utilisateur est assez simple :Si vous êtes parti du canevas, il est déjà prêt, sauf pour les trois derniers boutons que vous devez ajouter.
- dans un arrangement tableau (2x2), mettre quatre boutons, et compléter par
- un arrangement horizontal dans lequel on affiche les compteurs du nombre d'essais, d'erreurs et d'images trouvées,
- un arrangement horizontal contenant un bouton pour recommencer une partie et un pour continuer après un mauvais choix,
- et on peut ajouter un arrangement temporaire (debug) dans lequel afficher les résulats intermédiaires comme la liste des images avant et après tirage aléatoire, etc.
Les images téléchargées dans le canevas sont les suivantes (si vous en choisisez d'autres, gardez les mêmes noms et prenez des images de petite taille, par exemple 128 x 128)
Image téléchargées | Nom |
back.png | image cachée ou dos de la carte, affichée au départ |
0.png | image blanche (non utilisée dans la version 1) |
1.png | première image de la liste |
2.png | deuxième image de la liste |
3.png à 8.png | images supplémentaires disponibles |
Les caractéristiques et le rôle des composants sont pécisés ci-dessous :
Composant | Groupe | Nom | Rôle fonctionnel |
Screen1 |
|
||
Arrangement tableau | Disposition | Argangement_tableau1 | Encapsule les boutons (ou cartes)
|
Bouton | Interface utilisateur | BoutonCase1 | Bouton n°1 (dans l'arrangement tableau précédent)
|
Bouton | Interface utilisateur | BoutonCase2 | bouton n°2 (idem précédent) | Bouton | Interface utilisateur | BoutonCase3 | bouton n°3 (idem précédent) | Bouton | Interface utilisateur | BoutonCase4 | bouton n°4 (idem précédent)
|
Arrangement horizontal |
Disposition | Arrangement_HorizontalNombres | Encapsule les labels d'affichage des nombres et de leurs étiquettes
|
Label | Interface utilisateur | LabelNombreEssais | Label contenant le nombre d'essais
|
Label | Interface utilisateur | LabelEssais | Label contenant l'étiquette du nombre d'essais
|
Label | Interface utilisateur | LabelNombreErreurs | Label contenant le nombre d'erreurs
|
Label | Interface utilisateur | LabelEssais | Label contenant l'étiquette du nombre d'erreurs
|
Label | Interface utilisateur | LabelNombreEssais | Label contenant le nombre d'images déjà trouvées
|
Label | Interface utilisateur | LabelEssais | Label contenant l'étiquette du nombre d'images trouvées
|
Arrangement horizontal |
Disposition | Arrangement_Hor_reprise | Pour les boutons de nouvelle partie ou après un mauvais choix
|
Bouton | Interface utilisateur | BoutonRecommencer | Réinitialise pour une nouvelle partie
|
Bouton | Interface utilisateur | BoutonContinuerApresUneErreur | Masque les deux images choisies et réactive le choix
|
Arrangement horizontal |
Disposition | Arrangement_Debug | Affichage des informations intermédiaires dans la phase de mise au point |
Label | Interface utilisateur | LabelListeImages | permet d'afficher la liste des images avant tirage au sort. |
Label | Interface utilisateur | LabelListeCases | permet d'afficher la liste des images après tirage au sort. |
Notificateur | Interface utilisateur | Notificateur1 | permet d'afficher les messages. |
Son | Medias | Notificateur1 | permet de faire vibrer le téléphone en cas d'erreur de choix. |
Programmation :
La programmation du comportement de l'application avec les blocs, consiste à coder sa réaction aux évènements. On reprend donc simplement le diagramme de flux vu plus haut, avec les évènements suivants :Evènement | Comportement à coder |
Quand Screen1.Initialize |
Le code associé à l'évènement de démarrage, consiste simplement à appeler la procédure de démarrage d'une partie.Elle va
|
Quand BoutonRecommencer.Clic | idem précédent |
Quand BoutonCase1.Clic Quand BoutonCase2.Clic Quand BoutonCase3.Clic Quand BoutonCase4.Clic Ce code est dupliqué pour les 3 autres boutons en remplaçant le 1 par 2, 3 et 4 aux deux endroits où il est utilisé. Que l'on voit mieux en coupant : |
Le code associé au clic sur un bouton - si ce bouton est activé - est décrit dans le diagramme de flux analysé plus haut.
Dans la décomposition des fonctions, on cherche à séparer
|
Quand BoutonContinuerApresErreur | Ce bouton est affiché lorsque les 2 images choisies ne correspondent pas (mauvais choix). Il faut alors laisser le temps au joeur de voir les cartes avant de les masquer et de continuer en réactivant les cartes cachées pour autoriser les clics. |
Structure générale du code :
Au total, il n'y a que 14 lignes de code dans les scripts d'évènements : c'est très peu!
L'essentiel du code est dans des procédures : on a séparé l'utilisation des fonctions (leur appel) de leur réalisation.
C'est ce que l'on appelle l'abstraction procédurale. C'est très puissant pour garder une vision de haut niveau (14 lignes) et regrouper à un seul endroit les opérations partagées ou compliquées.
Les procédures à coder sont les suivantes :
procédures | paramètres en entrée | en sortie | Comportement à coder | |||||||||||||||||
appelées pour démarrer une partie | ||||||||||||||||||||
demarrer | (cf.diagramme des flux) Cette procédure appelle les 3 suivantes,la procédure cacherLesCases et réinitialise les compteurs et variables. | |||||||||||||||||||
tirerAuSortLesImagesDesCases | cette procédure, appelée par la procédure démarrer commence par construire une liste de paires coprenant des paires d'images listeImagesARepartirDansLesCases puis les répartit de façon aléatoire dans la listeImagesDeCases | |||||||||||||||||||
initBoutonsCases | cette procédure, appelée par la procédure démarrer met à jour la largeur et la hauteur des cases en fonction du nombre de lignes et colonnes. Elle n'est utile que si vous ajoutez des cases. | |||||||||||||||||||
activerLesCasesCachées | cette procédure, appelée par la procédure démarrer et dans le script de l'évènement quand BoutonContinuerAPresUneErreur.clic active les cases cachées ou les rend cliquables pour la suite du jeu. | |||||||||||||||||||
pour modifier les cases ou boutons | ||||||||||||||||||||
cacherLesCases | ||||||||||||||||||||
désactiverLesCases | Cette procédure est appelée en cours de partie, par la procédure mauvaisChoix quand le joueur ne doit plus cliquer sur aucune case. | |||||||||||||||||||
activerLesCasesCachées | Cette procédure est appelée en cours de partie, par la procédure démarrage et dans le script de l'évènement quand BoutonContinuerAPresUneErreur.clic pour reprendre le jeu rendre actives toutes les cases cachées. Les cases visibles correspondent alors aux cartes déjà trouvées et ne sont plus cliquables | |||||||||||||||||||
cacherLaCase | numeroCase | Cette procédure est appelée en cours de partie dans le script de l'évènement permet de masquerune carte découverte avec un mauvais choix.
appelées en cours de partie | choix
| numeroCase
|
| Cette procédure appelée par dans le script des évènements Qaund boutonCase_.Clicanalyse le choix effectué, donné par l'index en paramètre. Si c'est le premier choix, il est stocké dans la variable numeroCaseChoix1 . Si c'est le deuxième choix, il est stocké dans la variable numeroCaseChoix2 et la procédure verifierSiLesDeuxChoixCorrespondent est appelée pour les comparer.
| verifierSiLesDeuxChoixCorrespondent
|
|
| Cette procédure est appelée par la procédure choix pour comparer les images aux index numeroCaseChoix1 et numeroCaseChoix2. Si les deux images correspondent, la procédure bonChoix est appelée, sinon c'est la procédure mauvaisChoix
| bonChoix
|
|
| Cette procédure est appelée par la procédure verifierSiLesDeuxChoixCorrespondent s'ils correspondent. Les variables de choix numeroCaseChoix1 et numeroCaseChoix2sont remises à 0. Le nombre d'images trouves est augmenté de 2 et si toutes les images ont été trouvées, Le jouer est prévenu qu'il a gagné.
| mauvaixChoix
|
|
| Cette procédure est appelée par la procédure verifierSiLesDeuxChoixCorrespondent s'ils ne correspondent pas. Les cases sont toutes désactivées, et le vibreur prévient le joueur que le choix n'est pas bon. Le bouton de reprise est affiché et l'application reste en attente pour permettre au jouer de mémoriser son dernier choix. (La partie reprend quan il clique sur le bouon)
| |
Code:
Nous examinerons dans l'ordre :- la déclaration des variables,
- les évènements de démarrage d'une aprtie et la procédure de démarrage correspondante,
- les procédures qui modient les propriétés des boutons (y compris celles qui sont appelées en cours de partie)
- l'évènement " clic sur bouton " avec les instructions spécifiques à ce bouton,
- les procédures d'analyse du choix
- enfin l'évènement de reprise du jeu après un choix erronné.
Les variables : Les principales variables sont :
- la listeImagesARepartirDansLesCases : c'est la liste des images avant répartition dans les cases. Cette liste est construite
Evènements de démarrage d'une partie :
Procédure démarrer :
Procédure tirerAuSortLesImagesDesCases :
Le tirage au sort des cartes consiste à :
- mettre des paires d'images identiques dans la liste listeImagesARepartirDansLesCases. La longueur de la liste doit être égale au nombre de cases.
- initialiser la liste listeImagesDeCases à une liste vide,
- puis dans une boucle sur le nombre de cases :
- tirer au sort une image de la première liste,
- l'ajouter à la seconde liste,
- et la retirer de la première liste (pour que cette image ne soit pas tirée plusieurs fois).
Procédure initBoutonsCases :
Cette procédure calcule la largeur des cases en fonction du nombre de lignes et colonnes.
Pour l'instant, elle n'est pas utile si on a mis la bonne largeur et la bonne hauteur dans la phase de design. Mais elle le sera quand changera le nombre de lignes ou de colonnes pour ajouter des cases.
Procédure cacherLesCases :
Cette procédure fixe l'image de fond des boutons à l'image d'une carte cachée.
Procédure activerLesCasesCachées :
Cette procédure active les boutons cachés, en mettant à vrai leur propriété "activé".
Les cases dont l'image est visible ont été trouvées, il ne faut donc pas les activer.
Procédure désactiverLesCases:
Cette procédure qui désactive tous les boutons est appelée pendant la partie. On la traite ici car elle fait partie du groupe qui manipule les propriéts des boutons.
Procédure cacherLaCase:
De même, cette procédure fait partie du groupe qui manipule les propriétés des boutons.
Evènements BoutonCase_.clic :
Lorsqu'un bouton est cliqué, on affiche l'image correspondant à son index dans la liste des images et il est désactivé (pour ne plus être cliquable).
Ensuite, on appelle la procédure choix, avec le numéro du bouton, pour analyser la réponse. Cette proécédure est spcifique à chque bouton car le nom du bouton et le numéro changent à chaque bouton.
Cet évènement est dupliqué pour autant de boutons en changeant à chque fois le numéro et le nom des boutons.
Procédure choix(numeroCase):
Cette procédure est appelée après un clic sur n'importe quel bouton (actif) avec le numéro en paramètre.
Selon qu'il s'agit de la première image ou de la seconde dans un essai, le comportement n'est pas le même :
- Si c'est la première image numeroCaseChoix1 = 0
Alors on met cette variable au numero de la case cliquée : numeroCaseChoix1 = numeroCase et on attend l'évènement suivant, - Sinon, c'est la seconde image, alors :
- on met à jour le numéro de la 2° variable : numeroCaseChoix2 = numeroCase
- et on appelle la procédure verifierLesDeuxchoixCorrespondent
Procédure verifierSiLesDeuxChoixCorrespondent :
Cette procédure ajoute 1 au nombre d'essais, puis récupère le nom des images dans la liste listeImagesDeCases aux index numeroCaseChoix1 et numeroCaseChoix2.
- Si les images sont les mêmes elle appelle la procédure bonChoix
- Sinon elle appelle la procédure mauvaisChoix
Procédure bonChoix:
Cette procédure appelée en cas de bon choix,
- elle ajoute 2 au nombre de cases trouvées,
- si ce nombre est égal au nombre de cases, un message indique au joueur qu'il a gagné et le bouton recommencer est rendu visible,
- les numéros des dernières cases choisies sont remis à 0
Procédure mauvaisChoix:
Cette procédure appelée en cas de mauvais choix laisse le temps au joueur de voir les cartes :
- les cases sont désactivées (jusqu'à la reprise après erreur),
- l'appareil vibre une demi-seconde,
- le nombre d'erreurs est augmenté de 1,
- le bouton permettant de continuer après une erreur est rendu visible.
Evènement Quand BoutonContinuerApresUneErreur.clic : Ce bouton est visible après une erreur. Il permet de reprendre le jeu. Sur clic :
- les cases qui viennet d'être choisies sont cachées,
- toutes les cases cachées sont réactivées (rendues cliquables),
- les numéros de cartes choisies listeImagesDeCases aux index numeroCaseChoix1 et numeroCaseChoix2 sont remis à 0,
- le bouton est rendu invisible.
Vue générale du code de l'application
Transférer l'application sur le portable:
Dans la phase de développement, vous aurez généralement effectué les tests avec le portable en mode "connecté". C'est pratique car les modifications du programme depuis le PC sont immédiatement répercutées sur le téléphone. N'oubliez pas de télécharger l'application sur le téléphone : dans l'onglet "construire" en haut à gauche de la fenêtre, sélectionnez"App (Donnez le code QR pour fichier .apk)" et sur votre prtable lancez l'aI2 companion et scannez le QR code.Après quelques dizaines de secondes, il vous proposera d'installer l'application. Autorisez et validez cette installation (paramètres de sécurité). L'application est alors installée en permanence et vous pourez vous en servir hors connection.Améliorez cette application
Passez de 4 à 6 images- ajoutez une ligne au tabeau, 3 au lieu de 2 et ajoutez deux boutons et leurs évènements
- complétez Toutes les procédures qui parcourent la liste des boutons : initBouonCases,créerListeImagesAREpartirDansCases,cacherLesCases, DesactiverLesCases, cacherLaCase
Question :
Quel est l'inconvénient de cette méthode quand on veut passer à 16 cases ?
On va voir une solution dans la version2