Aller au contenu

Une grille de jeu cliquable

Les instructions de cette page reposent sur l'utilisation de Processing et de ses dérivés comme p5, dans une version transposée en python.

Le notebook support utilise la bibliothèque p5 dans la version proposée par le site basthon.fr. Aucun pré-requis lié aux fonctions de p5 n'est attendu.

Dans toute cette page, le terme grille peut désigner :
- soit un tableau de tableaux, ces derniers étant tous de même dimension,
- soit une représentation graphique, sous la forme d'un rectangle composé de cases disposées en lignes et colonnes.

1. Représenter une grille à l'aide d'un tableau

1.1 Lecture du programme

Lire le programme du notebook support et décrire le lien entre la valeur de la variable grille et l'affichage réalisé.

1.2 Modifications de la grille

Quelles valeurs de la variable grille permettent d'obtenir les affichages suivants ?
(tester en exécutant le programme après modification de la valeur de la variable grille)
a) b) c)

1.3 Analyse

Lorsque l'on exécute ce programme :

  • De quelle couleur sont les cases correspondant à des 0 dans la variable grille ?
  • Quelles sont les dimensions de l'affichage réalisé ?
  • Que représente la variable lignes pour la grille affichée ?
  • Que représente la variable taille pour la grille affichée ?

1.4 Description de fonctions

Les fonctions fill, rect, color, stroke, strokeWeight sont des fonctions de la bibliothèque p5.

  • Proposer une description du rôle de la fonction fill().
  • Proposer une description du rôle de la fonction rect().
  • Modifier les paramètres des fonctions color, stroke, strokeWeight et observer les effets produits. Proposer une description du rôle de chacune de ces fonctions.

1.5 Modification du programme

Modifier le programme pour que l'affichage réalisé soit le suivant : ​

2. Une grille de jeu cliquable

La grille de jeu est composée de cases initialement toutes oranges. En cliquant sur une case on modifie sa couleur et celle de ses voisines (c'est à dire les cases ayant un côté en commun). Chaque case est alternativement orange ou bleue. L'objectif est de rendre la totalité de la grille bleue.

Les étapes proposées permettent, à partir du notebook support, d'aboutir au jeu décrit ci-dessus.

2.1 Configuration initiale de la grille

Quelle grille permet de démarrer avec un jeu ne comportant que des cases oranges ? Modifier la valeur de la variable grille.

2.2 Victoire

Créer une fonction gagne qui prend en paramètre une grille et renvoie True si la grille ne comporte que des 1, et False sinon.

Vérifier que la fonction passe les tests suivants :

assert(gagne([[1,1,1], [1,1,1], [1,1,1], [1,1,1]]))
assert(not gagne([[1,1,1], [1,1,0], [1,1,1]]))

Aide : une proposition à compléter
1
2
3
4
5
6
def gagne(grille):
    for ... in grille :
        for ... in ... :
            if ... != 1 :
                return False
    return True

2.3 Inversion

Créer une fonction change_case(ligne, colonne, grille) qui prend en paramètres un indice de ligne, un indice de colonne et une grille (ne comportant que des 0 et des 1), et qui modifie la valeur de grille[ligne][colonne] en lui affectant la valeur 0 si sa valeur était 1, et en lui affectant la valeur 1 si sa valeur était 0. Cette fonction ne renvoie rien.

2.4 Dans quelle case est le clic ?

Lors d'un clic sur la grille avec la souris, on pourra récupérer les coordonnées du point cliqué. À partir de ces coordonnées, on a besoin de déterminer dans quelle case de la grille se trouve le point cliqué. On suppose que l'affichage est réalisé dans une fenêtre de dimensions 400 x 400, et que la grille est carrée.

Par exemple, avec une grille de 4 lignes et 4 colonnes :
- le clic aux coordonnées (50, 50) devra être associé aux valeurs (0, 0), (ligne d'indice 0, colonne d'indice 0)
- le clic aux coordonnées (250, 150) devra être associé aux valeurs (1, 2) : (ligne d'indice 1, colonne d'indice 2)
- le clic aux coordonnées (250, 350) devra être associé aux valeurs (3, 2) : (ligne d'indice 3, colonne d'indice 2).

Compléter la fonction suivante :

def pixel_vers_grille(x, y, dimension_grille):
    """
    renvoie les indices de ligne et de colonne dans une grille carrée 
    (de dimension dimension_grille) de la case qui contient 
    le pixel de coordonnées (x,y) 
    """
    # taille d'une case, en pixels
    taille_pixels = int(400 / dimension_grille)      
    return (... // ..., ... // ...)

Vérifier que la fonction passe les tests suivants :

assert(pixel_vers_grille(50, 50, 4) == (0, 0))
assert(pixel_vers_grille(250, 150, 4) == (1, 2))
assert(pixel_vers_grille(250, 350, 4) == (3, 2))

2.5 Rassemblement des voisins

Lors du clic sur une case, la couleur de cette case et celle de ses voisines doit s'inverser. On souhaite écrire une fonction voisins(ligne, colonne, dimension_grille) qui prend en paramètres un indice de ligne, un indice de colonne et la dimension d'une grille carrée. Cette fonction renvoie une liste composée des couples des indices de ligne et de colonne de chaque case voisine.

Une case peut avoir de 2 à 4 voisins : les cases dans les coins n'en ont que 2, les cases hors des bords en ont 4.
À quelles conditions portant sur ligneet colonne une case possède-t-elle une voisine à gauche ? À droite ? Au-dessus ? Au dessous ?

Vérifier que la fonction passe les tests suivants (la fonction sorted est utilisée dans les tests pour valider les listes contenant les bons couples indépendamment de l'ordre de ces couples) :

assert(sorted(voisins(3, 3, 4)) == [(2, 3), (3, 2)]
assert(sorted(voisins(1, 3, 4)) == [(0, 3), (1, 2), (2, 3)]
assert(sorted(voisins(1, 1, 4)) == [(0, 1), (1, 0), (1, 2), (2, 1)]
Aide : une proposition à compléter
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def voisins(ligne, colonne, dimension_grille):
    liste_voisins = ...

    # gauche 
    if colonne ... :
            liste_voisins.append((... , colonne - 1))

    # droite 
    if colonne ... :
        liste_voisins.append((... , ...))

    # haut 
    if ligne ... :
        liste_voisins.append((... , colonne))

    # bas :
    if ligne < ... :
        liste_voisins.append((..., ...))

    return ...

2.6 Actions à réaliser au clic de souris

La version de p5 utilisée propose un booléen mouseIsPressed qui vaut True lorsque la souris est cliquée. On peut lire les coordonnées de la souris dans la fenêtre de tracé grâce aux variables mouseXet mouseY.

La fonction souris_cliquee suivante :

  • permet de stocker les coordonnées de la souris à chaque clic, en vérifiant que l'on ne prend pas en compte deux fois de suite le même clic ;
  • inverse la couleur de la case cliquée en utilisant les fonctions pixel_vers_grille et change_case ;
  • détermine la liste des cases voisines de la case cliquée en utilisant la fonction voisins puis parcourt cette liste pour changer la couleur de chaque case voisine en utilisant à nouveau la fonction change_case ;
def souris_cliquee():
    if mouseIsPressed:
        if (mouseX, mouseY) != souris[-1]:
            souris.append((mouseX, mouseY))

            ligne, colonne = pixel_vers_grille(int(mouseX), int(mouseY), DIMENSION)
            change_case(ligne, colonne, grille)

            for case in voisins(ligne, colonne, DIMENSION):
                ligne_case, colonne_case = case
                change_case(ligne_case, colonne_case, grille)

Copier cette fonction, ainsi que toutes les fonctions écrites dans cette partie 2 (2.1 à 2.6) dans une cellule du notebook, au-dessus de la cellule qui contient les fonctions setup, draw et run.

2.7 Finalisation

La fonction souris_cliquee utilise une liste nommée souris et une constante nommée DIMENSION qui sont définies au début de la cellule qui contient les fonctions setup, draw et run.

# à insérer juste après l'initialisation de grille
DIMENSION = len(grille)
souris = [(0, 0)]

Enfin, la fonction draw (qui est exécutée en boucle après l'exécution de setup) est à compléter pour prendre en compte l'interaction avec la souris, et vérifier après chaque clic si la partie est gagnée. C'est la fonction draw qui fait appel à celles précédemment définies.

def draw():
    affiche_grille(grille)
    souris_cliquee()
    if gagne(grille):
        affiche_grille(grille)
        stop()

Tester le jeu obtenu en exécutant la cellule qui contient les fonctions setup, draw et run.

2.8 Compléments

Proposer des fonctionnalités supplémentaires :

  • créer un compteur de clics qui compte le nombre de clics joués avant la victoire ;
  • afficher en cas de victoire un message de félicitation, ainsi que le nombre de coups joués ; (l'intruction text(message, x, y) permet d'afficher le texte de la variable message à partir des coordonnées (x, y))