If you're seeing this message, it means we're having trouble loading external resources on our website.

Si vous avez un filtre web, veuillez vous assurer que les domaines *. kastatic.org et *. kasandbox.org sont autorisés.

Contenu principal

Grille de tuiles

La première étape du jeu de "Memory" est le mélange aléatoire de toutes les tuiles, puis leur disposition en grille rectangulaire, faces cachées, pour qu'on ne puisse pas voir où sont les images.

Tuiles faces cachées

Pour commencer notre programmation du jeu, préoccupons-nous juste de créer les tuiles faces cachées. Nous déterminerons comment implémenter les images plus tard.
La "tuile" est un objet suffisamment important dans le jeu de "Memory", pour que nous utilisions une conception orientée objet pour définir cet objet Tile, et ainsi créer plusieurs instances de celui-ci. Nous pourrons alors associer deux propriétés (la position et l'image), et un comportement (retourner la tuile, face dessus ou face dessous), à chaque Tiles.
Pour commencer, nous allons définir la fonction constructeur de Tile. Étant donné que nous ne traitons pas encore les images, nous allons juste lui passer les arguments x et y. Nous allons aussi enregistrer la largeur (une constante) (width en anglais) de la tuile, dans une propriété de l'objet.
var Tile = function(x, y) {
    this.x = x;
    this.y = y;
    this.width = 70;
};
Maintenant que nous avons défini le constructeur, nous pouvons utiliser une boucle pour créer des tuiles aux coordonnées x et y appropriées. En fait, nous allons utiliser deux boucles for (une boucle for imbriquée) pour faciliter la génération des coordonnées d'une grille.
Nous commençons par initialiser un tableau tiles vide :
var tiles = [];
Notre boucle extérieure itère sur le nombre de colonnes que nous souhaitons, notre boucle intérieure sur le nombre de lignes. Ainsi, chaque nouvelle Tile est initialisée avec un x et un y, qui correspondent à une ligne et à une colonne.
var NUM_COLS = 5;
var NUM_ROWS = 4;
for (var i = 0; i < NUM_COLS; i++) {
    for (var j = 0; j < NUM_ROWS; j++) {
        tiles.push(new Tile(i * 78 + 10, j * 78 + 40));
    }
}
Mais, oh, il est difficile de savoir si les tuiles seront bien placées, car nous ne possédons encore aucun code nous permettant de les dessiner ! En fait, nous aurions dû peut-être commencer par cela. Quelquefois, en programmation, il n'est pas toujours évident de savoir par où commencer. Ajoutons une méthode à l'objet Tile, pour dessiner une tuile face cachée sur la zone de dessin. Nous allons dessiner un rectangle arrondi, avec une jolie feuille de Khan sur le dessus, aux coordonnées qui lui ont été assignées.
Tile.prototype.drawFaceDown = function() {
    fill(214, 247, 202);
    strokeWeight(2);
    rect(this.x, this.y, this.width, this.width, 10);
    image(getImage("avatars/leaf-green"), this.x, this.y, this.width, this.width);
};
Et maintenant, nous pouvons vérifier l'apparence de nos tuiles. Ajoutons une nouvelle boucle for, parcourant les tuiles, pour appeler la méthode de dessin :
for (var i = 0; i < tiles.length; i++) {
    tiles[i].drawFaceDown();
}
Voici à quoi ressemble notre programme, avec ce code. Essayez de bidouiller les différents nombres utilisés dans la boucle for imbriquée, pour voir comment les changements ont un impact sur la grille, ou essayez de modifier le dessin (un logo différent, peut-être ?) :

Tuiles faces visibles

Maintenant que nous avons notre grille de tuiles faces cachées, attaquons-nous à un problème plus délicat : leur assigner à chacune une image, de telle manière qu'il y en ait deux de chaque, distribuées aléatoirement dans le tableau. Il y a probablement plusieurs moyens d'accomplir cela, mais voici ce que je suggère :
  1. Nous créons un tableau des images possibles, en utilisant la fonction getImage, pour les sélectionner dans notre bibliothèque.
  2. Nous n'aurons besoin que de 10 images pour les faces de nos 20 tuiles, donc nous créons un nouveau tableau, contenant 2 copies, de 10 images sélectionnées aléatoirement, du premier tableau.
  3. Nous mélangeons aléatoirement les images sélectionnées de ce nouveau tableau, pour qu'à l'intérieur, les paires d'images ne soient plus placées côte à côte.
  4. Dans la boucle for imbriquée, dans laquelle nous créons les tuiles, nous allons assigner une image de ce tableau à chaque tuile.
Ces étapes ne vous semblent peut-être pas encore très claires. Codons-les, pour voir à quoi cela ressemble
Étape 1 : Nous créons un tableau des images possibles, en utilisant la fonction getImage, pour les sélectionner dans notre bibliothèque :
var faces = [
    getImage("avatars/leafers-seed"),
    getImage("avatars/leafers-seedling"),
    getImage("avatars/leafers-sapling"),
    getImage("avatars/leafers-tree"),
    getImage("avatars/leafers-ultimate"),
    getImage("avatars/marcimus"),
    getImage("avatars/mr-pants"),
    getImage("avatars/mr-pink"),
    getImage("avatars/old-spice-man"),
    getImage("avatars/robot_female_1"),
    getImage("avatars/piceratops-tree"),
    getImage("avatars/orange-juice-squid")
];
J'ai choisi un groupe d'avatars, mais vous pouvez changer et prendre des images qui vous plaisent. Ce qui est important est de veiller à ce que ce tableau contienne au moins 10 images, pour qu'on ne soit pas à court d'image pour nos 20 tuiles. Nous pouvons en ajouter beaucoup plus que 10 cependant, pour rendre notre jeu à chaque fois plus varié, car nous restreindrons la liste à la prochaine étape.
Étape 2 : Nous n'aurons besoin que de 10 images pour les faces de nos 20 tuiles, donc nous créons un nouveau tableau, contenant 2 copies, de 10 images sélectionnées aléatoirement, du premier tableau.
Pour faire cela, nous créons une boucle for qui itère 10 fois. À chaque itération, nous sélectionnons aléatoirement un index dans le tableau faces, poussons deux fois l'élément correspondant dans le tableau selected (sélectionnés en français), puis utilisons la méthode splice pour le retirer du tableau faces, afin que nous ne le sélectionnions pas une autre fois. Cette dernière étape est très importante !
var selected = [];
for (var i = 0; i < 10; i++) {
    // Sélectionne aléatoirement un élément du tableau faces
    var randomInd = floor(random(faces.length));
    var face = faces[randomInd];
    // Pousse 2 copies dans le tableau selected
    selected.push(face);
    selected.push(face);
    // Supprime l'élément du tableau faces pour éviter qu'il soit resélectionné
    faces.splice(randomInd, 1);
}
Étape 3 : Nous mélangeons aléatoirement les images sélectionnées de ce nouveau tableau, pour qu'à l'intérieur, les paires d'images ne soient plus placées côte à côte.
Vous devez vous demandez comment on peut mélanger aléatoirement les éléments d'un tableau en JavaScript ? Il existe quelques techniques. Je vais vous montrer ma préférée.
En JavaScript, tous les objets tableau possède une méthode intégrée sort qui trie le tableau dans l'ordre "lexicographique". Ce qui signifie qu'il convertit chaque élément en chaîne de caractère, et les trie comme si elles étaient des mots dans un dictionnaire. Par exemple, regardons comment un tableau de nombres et de lettres serait trié :
var items = ["A", 1, "C", "H", 10, "D", 2];
items.sort();
1,10,2,A,C,D,H
Cet ordre de tri est utile de temps en temps, mais la plupart du temps, on souhaitera trier notre tableau autrement. Par exemple, si nous avions un tableau de nombres, nous voudrions le trier numériquement. C'est pourquoi, la méthode sort accepte un argument facultatif, une fonction de retour, qui est appelée sur chaque paire d'éléments du tableau, et qui retourne une valeur indiquant lequel des deux éléments est le plus grand. Un nombre négatif indique que le premier élément doit être en premier, un nombre positif, que le second élément doit être en premier, et un zéro laisse l'ordre des éléments inchangé.
Pour trier un tableau numériquement, du plus petit au plus grand, nous pouvons passer une fonction retournant a-b.
var nums = [1, 5, 10, 2, 4];
nums.sort(function(a, b) {
    return a-b;
});
// 1,2,4,5,10
OK. Comment utiliser cela pour trier aléatoirement un tableau ? Eh bien, il nous suffit juste de retourner un nombre aléatoire avec cette fonction, un nombre, soit négatif, soit positif. Voici comment procéder, sur notre tableau selected :
selected.sort(function() {
    return 0{,}5 - random();
});
Et nous voici maintenant avec un tableau de 10 paires d'images, triées aléatoirement !
Étape 4 : Dans la boucle for imbriquée, dans laquelle nous créons les tuiles, nous allons assigner une image de ce tableau à chaque tuile.
Nous possédons 20 images dans notre tableau selected, et nous itérons 20 fois, pour instancier les nouvelles tuiles aux coordonnées de la grille. Pour assigner une image à une tuile, utilisons simplement la méthode pop sur le tableau. Cette méthode retire le dernier élément du tableau et le retourne. C'est la manière la plus simple de veiller à ce que nous assignions toutes les images, sans faire de doublons.
for (var i = 0; i < NUM_COLS; i++) {
    for (var j = 0; j < NUM_ROWS; j++) {
        tiles.push(new Tile(i * 78 + 10, j * 78 + 40, selected.pop()));
    }
}
Nous avons donc maintenant théoriquement une image assignée à chaque tuile, mais nous ne les avons pas encore affichées ! Ajoutons une méthode à l'objet Tile, qui va être responsable de l'affichage face visible. Elle va ressembler à celle qui s'occupe de l'affichage face cachée, sauf que la propriété this.face est maintenant passée à la fonction image.
Tile.prototype.drawFaceUp = function() {
    fill(214, 247, 202);
    strokeWeight(2);
    rect(this.x, this.y, this.width, this.width, 10);
    image(this.face, this.x, this.y, this.width, this.width);
};
Pour éviter de répéter du code, nous pourrions en fait ajouter une méthode additionnelle, qui serait responsable du dessin des contours, et appeler cette méthode, au début de chacune des deux méthodes de dessin. Mais nous allons laisser les choses comme elles sont pour l'instant.
Finalement, pour tester tout ce travail, nous pouvons modifier notre boucle for, et appeler drawFaceUp à la place de drawFaceDown :
for (var i = 0; i < tiles.length; i++) {
    tiles[i].drawFaceUp();
}
Et voilà, toutes ensemble ! Redémarrez (Restart) pour voir comment la disposition des tuiles changent à chaque fois.

Vous souhaitez rejoindre la discussion ?

Pas encore de posts.
Vous comprenez l'anglais ? Cliquez ici pour participer à d'autres discussions sur Khan Academy en anglais.