xxxxxxxxxx
# Rappels
Le module `interface_grille` - qui s'appuie sur `matplotlib` - permet de créer une interface graphique :
- composée d'une grille à maillage carré ;
- dont chaque case peut comporter (ou pas) :
- une couleur de <span style="color:blue;">fond</span>,
- du <span style="color:blue;">texte</span>,
- des <span style="color:blue;">murs</span> séparateurs,
- une <span style="color:blue;">image</span> ;
- qui peut écouter quelques <span style="color:blue;">évènements</span> (sélection d'un objet à la souris, clic souris et appui sur une touche du clavier) ;
- qui dispose d'une <span style="color:blue;">sortie textuelle</span> ;
- qui peut effectuer des <span style="color:blue;">animations</span>.
On rappelle que les instructions de création de la grille diffèrent un peu selon l'environnement de travail (basthon, jupyter ou autre), ici ce sont celles pour basthon qui sont utilisées.
**On s'intéresse dans ce notebook à l'écoute des <span style="color:blue;">évènements</span>.**
# 0 : Rappels
Dans le notebook sur les <span style="color:blue;">textes</span>, nous avons vu comment déplacer un personnage sur une carte. Pour cela on utilisait une fonction `deplacer` qui :
- prenait en paramètres :
- les matrices et dictionnaires représentant le plateau de jeu,
- la vue réalisant l'affichage,
- modifiait certaines valeurs des matrices ou dictionnaires,
- actualisait l'affichage.
```
-------------- -------------------
| matrices | | actualisation des |
| & dicos |\ ----->| matrices & dicos |
-------------- \ ----------- / -------------------
--->| fonction |/
| | puis
--->| deplacer |\
-------------- / ----------- \ -------------------
| vue |/ ----->| actualisation de |
-------------- | l'affichage |
-------------------
```
Il est important de comprendre que quel que soit le «jeu» utilisant l'interface grille, ce schéma resterait valable pour toute autre fonction effectuant des «actions de jeu». Par exemple une fonction qui changerait des couleurs de fond, qui détruirait ou ajouterait des murs, qui rendrait visibles ou invisibles certaines images etc.
**Finalement pour un jeu qui évolue au fil des différents tours de jeu et dont le «plateau de jeu» est modélisé en mémoire par des matrices et dictionnaires, on obtient le schéma plus général suivant :**
```
------------------- -------------------
| plateau de jeu = | | actualisation des |
| matrices & dicos |\ ----->| matrices & dicos |
------------------- \ ------------ / -------------------
--->| fonction |/
| "action | puis
--->| de jeu" |\
------------------- / ------------ \ -------------------
| vue |/ ----->| actualisation de |
------------------- | l'affichage |
-------------------
```
Le module interface_grille
- qui s'appuie sur matplotlib
- permet de créer une interface graphique :
On rappelle que les instructions de création de la grille diffèrent un peu selon l'environnement de travail (basthon, jupyter ou autre), ici ce sont celles pour basthon qui sont utilisées.
On s'intéresse dans ce notebook à l'écoute des évènements.
Dans le notebook sur les textes, nous avons vu comment déplacer un personnage sur une carte. Pour cela on utilisait une fonction deplacer
qui :
-------------- -------------------
| matrices | | actualisation des |
| & dicos |\ ----->| matrices & dicos |
-------------- \ ----------- / -------------------
--->| fonction |/
| | puis
--->| deplacer |\
-------------- / ----------- \ -------------------
| vue |/ ----->| actualisation de |
-------------- | l'affichage |
-------------------
Il est important de comprendre que quel que soit le «jeu» utilisant l'interface grille, ce schéma resterait valable pour toute autre fonction effectuant des «actions de jeu». Par exemple une fonction qui changerait des couleurs de fond, qui détruirait ou ajouterait des murs, qui rendrait visibles ou invisibles certaines images etc.
Finalement pour un jeu qui évolue au fil des différents tours de jeu et dont le «plateau de jeu» est modélisé en mémoire par des matrices et dictionnaires, on obtient le schéma plus général suivant :
------------------- -------------------
| plateau de jeu = | | actualisation des |
| matrices & dicos |\ ----->| matrices & dicos |
------------------- \ ------------ / -------------------
--->| fonction |/
| "action | puis
--->| de jeu" |\
------------------- / ------------ \ -------------------
| vue |/ ----->| actualisation de |
------------------- | l'affichage |
-------------------
xxxxxxxxxx
# I : Comprendre ce qu'est la gestion d'<span style="color:blue;">évènements</span>
Considérons une grille correspondant - par exemple - à un jeu auquel on souhaiterait jouer en utilisant :
- la souris : par exemple en faisant des clics sur certaines cases,
- le clavier : par exemple en appuyant sur les flèches du clavier ou des lettres.
Pour le programme informatique, les interactions clavier et souris sont appelés des <span style="color:blue;">évènements</span>.
En première approche on peut faire l'analyse ci-dessous :
```
----------------------------- ------------
| Evènement sur la grille : | | Action |
| - souris | ----------> | de |
| - clavier | | jeu |
----------------------------- ------------
```
En réfléchissant davantage, on réalise que selon l'évènement effectué à la souris ou au clavier et selon l'état du plateau de jeu à ce moment là, l'action de jeu à réaliser peut changer.
**Il faut donc des fonctions qui vont «gérer» les évènements en décidant - selon les évènements et l'état du plateau de jeu - quelles fonctions «action de jeu» effectuer. Finalement on obtient le schéma suivant :**
```
-------------------
| plateau de jeu = | -------------------
| matrices & dicos |\ | actualisation des |
------------------- \ ----->| matrices & dicos |
\ ------------ ------------ / -------------------
------------------- --->| fonction | choisit | fonction |/
| évènement |------>|gestionnaire|--------->| "action | puis
------------------- --->| d'évènement| | de jeu" |\
/ ------------ ------------ \ -------------------
------------------- / ----->| actualisation de |
| vue |/ | l'affichage |
------------------- -------------------
```
**Enfin, il faut savoir qu'une instruction spécifique (*binding* ou *liaison*) doit être effectuée afin d'associer un type d'évènement à la fonction gestionnaire qui le prend en charge. Cela permet, dès que cet évènement survient, de déclencher *automatiquement* un appel à la fonction gestionnaire.**
Considérons une grille correspondant - par exemple - à un jeu auquel on souhaiterait jouer en utilisant :
Pour le programme informatique, les interactions clavier et souris sont appelés des évènements.
En première approche on peut faire l'analyse ci-dessous :
----------------------------- ------------
| Evènement sur la grille : | | Action |
| - souris | ----------> | de |
| - clavier | | jeu |
----------------------------- ------------
En réfléchissant davantage, on réalise que selon l'évènement effectué à la souris ou au clavier et selon l'état du plateau de jeu à ce moment là, l'action de jeu à réaliser peut changer.
Il faut donc des fonctions qui vont «gérer» les évènements en décidant - selon les évènements et l'état du plateau de jeu - quelles fonctions «action de jeu» effectuer. Finalement on obtient le schéma suivant :
-------------------
| plateau de jeu = | -------------------
| matrices & dicos |\ | actualisation des |
------------------- \ ----->| matrices & dicos |
\ ------------ ------------ / -------------------
------------------- --->| fonction | choisit | fonction |/
| évènement |------>|gestionnaire|--------->| "action | puis
------------------- --->| d'évènement| | de jeu" |\
/ ------------ ------------ \ -------------------
------------------- / ----->| actualisation de |
| vue |/ | l'affichage |
------------------- -------------------
Enfin, il faut savoir qu'une instruction spécifique (binding ou liaison) doit être effectuée afin d'associer un type d'évènement à la fonction gestionnaire qui le prend en charge. Cela permet, dès que cet évènement survient, de déclencher automatiquement un appel à la fonction gestionnaire.
xxxxxxxxxx
# II : Quels sont les <span style="color:blue;">évènements</span> gérés dans une `vue` ?
vue
?¶xxxxxxxxxx
Les instances de la classe `Vue` gèrent cinq évènements. Les informations associées à ces cinq évènements sont passées en paramètre à la fonction gestionnaire sous forme de dictionnaire :
- `'appui_touche'` :
- Déclenché lorsqu'une touche du clavier est pressée,
- Voici l'évènement passé en paramètre à la fonction gestionnaire lors de l'appui sur la touche «e minuscule» 32.67 secondes après le lancement de l'interface graphique alors que la souris survole la case d'indice de ligne 2 et d'indice de colonne 3 :
- `{'moment': 32.67, 'evenement': 'appui_touche', 'touche': 'e', 'lig': 2, 'col': 3}`
- `'fin_appui_touche'`
- Déclenché lorsqu'une touche du clavier est relâchée,
- Voici l'évènement passé en paramètre à la fonction gestionnaire lors du relâchement de la touche «e minuscule» 33.25 secondes après le lancement de l'interface graphique alors que la souris survole la case d'indice de ligne 2 et d'indice de colonne 3 :
- `{'moment': 33.25, 'evenement': 'appui_touche', 'touche': 'e', 'lig': 2, 'col': 3}`
- `'selection_objet'`
- Déclenché lorsqu'un clic de souris est effectué sur un objet (`'fond'`, `'texte'`, `'mur'` ou `'image'`) **visible**,
- Voici l'évènement passé en paramètre à la fonction gestionnaire lors d'un clic avec le bouton gauche sur le `'texte'` de la case d'indice de ligne 3 et d'indice de colonne 0, 12.17 secondes après le lancement de l'interface graphique :
- `{'moment': 12.17, 'evenement': 'selection_objet', 'objet': 'texte', 'bouton': 'gauche', 'touche': None, 'lig': 3, 'col': 0}`
- Si une touche du clavier est pressée en même temps que le clic, le caractère de cette touche est associé à la clé `'touche'` du dictionnaire.
- Si l'objet est `'mur'`, le dictionnaire comprend en plus une clef `'d'` (pour «direction») à laquelle est associée la direction du mur (`'N'`, `'E'`, `'S'` ou `'O'`).
- `'clic_souris'`
- Déclenché lorsqu'un clic de souris est effectué sur la grille,
- Voici l'évènement passé en paramètre à la fonction gestionnaire lors d'un clic avec le bouton droit sur la case d'indice de ligne 2 et d'indice de colonne 2, 125.78 secondes après le lancement de l'interface graphique et tout en pressant la touche «k minuscule» :
- `{'moment': 125.78, 'evenement': 'clic_souris', 'bouton': 'droit', 'touche': 'k', 'lig': 2, 'col': 2}`
- Si le clic est effectué sur un objet **visible**, l'évènement `selection_objet` est également déclenché.
- Si le clic n'est pas effectué sur un objet **visible**, l'évènement `clic_souris` est seul à être déclenché.
- `'fin_clic_souris'`
- Déclenché lorsqu'un clic de souris sur la grille se termine,
- Voici l'évènement passé en paramètre à la fonction gestionnaire lors de la fin d'un clic avec le bouton droit sur la case d'indice de ligne 2 et d'indice de colonne 2, 126.34 secondes après le lancement de l'interface graphique et tout en pressant la touche «k minuscule» :
- `{'moment': 126.34, 'evenement': 'fin_clic_souris', 'bouton': 'droit', 'touche': 'k', 'lig': 2, 'col': 2}`
*Remarque : avez-vous compris la différence entre `'clic_souris'` et `'selection_objet'` ?*
Les instances de la classe Vue
gèrent cinq évènements. Les informations associées à ces cinq évènements sont passées en paramètre à la fonction gestionnaire sous forme de dictionnaire :
'appui_touche'
:
{'moment': 32.67, 'evenement': 'appui_touche', 'touche': 'e', 'lig': 2, 'col': 3}
'fin_appui_touche'
{'moment': 33.25, 'evenement': 'appui_touche', 'touche': 'e', 'lig': 2, 'col': 3}
'selection_objet'
'fond'
, 'texte'
, 'mur'
ou 'image'
) visible,'texte'
de la case d'indice de ligne 3 et d'indice de colonne 0, 12.17 secondes après le lancement de l'interface graphique :{'moment': 12.17, 'evenement': 'selection_objet', 'objet': 'texte', 'bouton': 'gauche', 'touche': None, 'lig': 3, 'col': 0}
'touche'
du dictionnaire.'mur'
, le dictionnaire comprend en plus une clef 'd'
(pour «direction») à laquelle est associée la direction du mur ('N'
, 'E'
, 'S'
ou 'O'
).'clic_souris'
{'moment': 125.78, 'evenement': 'clic_souris', 'bouton': 'droit', 'touche': 'k', 'lig': 2, 'col': 2}
selection_objet
est également déclenché.clic_souris
est seul à être déclenché.'fin_clic_souris'
{'moment': 126.34, 'evenement': 'fin_clic_souris', 'bouton': 'droit', 'touche': 'k', 'lig': 2, 'col': 2}
Remarque : avez-vous compris la différence entre 'clic_souris'
et 'selection_objet'
?
xxxxxxxxxx
*Question 1 :*
Exécutez les deux cellules de code ci-dessous puis déclenchez des évènements avec votre clavier et votre souris.
Observez le contenu du dictionnaire `evenements` qui s'affiche dans la zone textuelle.
En particulier :
- on fera quelques clics sur les cases sans fond ni texte pour observer la différence entre `'selection_objet'` et `'clic_souris'`,
- on fera des clics prolongés ou des appuis sur les touches prolongés pour observer la différence entre `'clic_souris'` et `'fin_clic_souris'` ainsi qu'entre `'appui_touche'` et `'fin_appui_touche'`.
Question 1 :
Exécutez les deux cellules de code ci-dessous puis déclenchez des évènements avec votre clavier et votre souris.
Observez le contenu du dictionnaire evenements
qui s'affiche dans la zone textuelle.
En particulier :
'selection_objet'
et 'clic_souris'
,'clic_souris'
et 'fin_clic_souris'
ainsi qu'entre 'appui_touche'
et 'fin_appui_touche'
.xxxxxxxxxx
import interface_grille as ig
from random import randint,choice
NB_LIG = 5
NB_COL = 4
vue = ig.Vue(NB_LIG, NB_COL, env='basthon', utiliser_zonetexte = True)
ig.plt.show()
def afficher_cases(vue):
global NB_LIG, NB_COL
for lig in range(NB_LIG):
for col in range(NB_COL):
couleur = (randint(0,255), randint(0, 255), randint(0, 255))
vue.mg('fond', lig, col, ci = couleur, v = True)
vue.mg('mur', lig, col, d = 'O', v = True)
vue.mg('mur', lig, col, d = 'N', v = True)
vue.mg('texte', lig, col, t = choice('ABCEDF'), tp = 36, v = True)
for lig in range(NB_LIG):
vue.mg('mur', lig, NB_COL-1, d = 'E', v = True)
for col in range(NB_COL):
vue.mg('mur', NB_LIG-1, col, d = 'S', v = True)
vue.mg('fond', 2, 1, v = False)
vue.mg('fond', 2, 2, v = False)
vue.mg('texte', 2, 1, v = False)
vue.mg('texte', 2, 2, v = False)
afficher_cases(vue)
xxxxxxxxxx
#################################################
# Définition des fonctions gestionnaires avec leurs trois paramètres
# ici, elles affichent juste le contenu du dictionnaire evenement et le contenu de argument
#################################################
def afficher_message(vue, message):
vue.mzt( texte = message, couleur_texte = (0, 0, 255), taille_police = 14)
def gestionnaire_appui_touche(vue, evenement, argument):
afficher_message(vue, str(evenement) + '\n\n' + argument)
def gestionnaire_fin_appui_touche(vue, evenement, argument):
afficher_message(vue, str(evenement) + '\n\n' + argument)
def gestionnaire_selection_objet(vue, evenement, argument):
afficher_message(vue, str(evenement) + '\n\n' + argument)
def gestionnaire_clic_souris(vue, evenement, argument):
afficher_message(vue, str(evenement) + '\n\n' + argument)
def gestionnaire_fin_clic_souris(vue, evenement, argument):
afficher_message(vue, str(evenement) + '\n\n' + argument)
#################################################
# Bindings (ou liaisons) entre les évènements et leurs gestionnaires
#################################################
vue.lier_evenement('appui_touche', gestionnaire_appui_touche, activer = True, argument = 'chauve-souris' )
vue.lier_evenement('fin_appui_touche', gestionnaire_fin_appui_touche, activer = True, argument = 'chat' )
vue.lier_evenement('clic_souris', gestionnaire_clic_souris, activer = True, argument = 'chameau' )
vue.lier_evenement('fin_clic_souris', gestionnaire_fin_clic_souris, activer = True, argument = 'chacal' )
vue.lier_evenement('selection_objet', gestionnaire_selection_objet, activer = True, argument = 'chamois' )
xxxxxxxxxx
# III : Effectuer la liaison entre un évènement et sa fonction gestionnaire
On utilise la méthode `lier_evenement(evenement, gestionnaire, activer, argument)` où :
- `evenement` est une chaîne de caractères désignant l'évènement que l'on souhaite prendre en charge (`'appui_touche'`, `'fin_appui_touche'`, `'selection_objet'`, `'clic_souris'` ou `'fin_clic_souris'`.
- `gestionnaire` est la fonction gestionnaire d'évènement.
- `activer` indique si l'on souhaite commencer à écouter l'évènement (`True`) ou si l'on souhaite terminer l'écoute de l'évènement (`False`).
- `argument` est un argument qui permet de passer des informations supplémentaires à la fonction gestionnaire. Pour un jeu, `argument` sera typiquement constitué des informations relatives au plateau de jeu (matrices, dictionnaires etc.).
Il est important de noter que la fonction gestionnaire devra **systématiquement** avoir trois paramètres :
- `vue` qui correspond à la `vue` utilisée pour l'interface graphique (instance de la classe `Vue`),
- `evenement` qui correspond au dictionnaire de l'évènement déclencheur (voir II),
- `argument` qui correspond à l'argument indiqué lors de la liaison (éventuellement `None` si il n'y en a pas besoin).
On utilise la méthode lier_evenement(evenement, gestionnaire, activer, argument)
où :
evenement
est une chaîne de caractères désignant l'évènement que l'on souhaite prendre en charge ('appui_touche'
, 'fin_appui_touche'
, 'selection_objet'
, 'clic_souris'
ou 'fin_clic_souris'
.
gestionnaire
est la fonction gestionnaire d'évènement.
activer
indique si l'on souhaite commencer à écouter l'évènement (True
) ou si l'on souhaite terminer l'écoute de l'évènement (False
).
argument
est un argument qui permet de passer des informations supplémentaires à la fonction gestionnaire. Pour un jeu, argument
sera typiquement constitué des informations relatives au plateau de jeu (matrices, dictionnaires etc.).
Il est important de noter que la fonction gestionnaire devra systématiquement avoir trois paramètres :
vue
qui correspond à la vue
utilisée pour l'interface graphique (instance de la classe Vue
),evenement
qui correspond au dictionnaire de l'évènement déclencheur (voir II),argument
qui correspond à l'argument indiqué lors de la liaison (éventuellement None
si il n'y en a pas besoin).xxxxxxxxxx
# IV : Un premier exemple passant du mode «fonctionnel» au mode «évènementiel»
La cellule de code ci-dessous permet d'obtenir un «jeu» dans lequel un singe doit rejoindre la case en bas à droite de la grille en récoltant des fruits. L'objectif est d'obtenir le plus de points possibles sachant que :
- une fraise rapporte 3 points,
- une poire rapporte 5 points,
- une grappe de raison rapporte 8 points,
- une banane rapporte 10 points.
Le singe ne peut se déplacer que vers le bas ou vers la droite.
<br/>
---
Le «plateau de jeu» `plateau` est un dictionnaire contenant :
- la matrice mémorisant les positions des différents fruits,
- l'indice de ligne de la position du singe,
- l'indice de colonne de la position du singe,
- le score obtenu au fur et à mesure par le singe.
Au fur et à mesure des déplacements du singe chacun des quatre éléments du plateau de jeu est susceptible d'évoluer.
Regrouper ces quatre éléments dans un seul objet (ici un dictionnaire) permet de les passer de façon très simple en argument aux fonctions, et cela permet aussi de faciliter le travail de notre cerveau (quand on code, on sait que TOUTES les informations qui modélisent l'état du plateau de jeu sont contenues dans la variable `plateau`).
En classe de terminale, on pourrait créer une classe `Plateau` ...
<br/>
---
Les variables globales (dont les noms sont en `MAJUSCULES`) sont les constantes correspondent à des informations qui ne changent pas au cours du jeu.
<br/>
---
Pour jouer il suffit :
- d'exécuter l'instruction `vue, plateau = nouvelle_partie()`
- puis d'exécuter l'instruction `bas(vue, plateau)` ou `droite(vue, plateau)` selon le déplacement souhaité.
La cellule de code ci-dessous permet d'obtenir un «jeu» dans lequel un singe doit rejoindre la case en bas à droite de la grille en récoltant des fruits. L'objectif est d'obtenir le plus de points possibles sachant que :
Le singe ne peut se déplacer que vers le bas ou vers la droite.
Le «plateau de jeu» plateau
est un dictionnaire contenant :
Au fur et à mesure des déplacements du singe chacun des quatre éléments du plateau de jeu est susceptible d'évoluer.
Regrouper ces quatre éléments dans un seul objet (ici un dictionnaire) permet de les passer de façon très simple en argument aux fonctions, et cela permet aussi de faciliter le travail de notre cerveau (quand on code, on sait que TOUTES les informations qui modélisent l'état du plateau de jeu sont contenues dans la variable plateau
).
En classe de terminale, on pourrait créer une classe Plateau
...
Les variables globales (dont les noms sont en MAJUSCULES
) sont les constantes correspondent à des informations qui ne changent pas au cours du jeu.
Pour jouer il suffit :
d'exécuter l'instruction vue, plateau = nouvelle_partie()
puis d'exécuter l'instruction bas(vue, plateau)
ou droite(vue, plateau)
selon le déplacement souhaité.
xxxxxxxxxx
import interface_grille as ig
from random import randint, choices
NB_LIG = 10
NB_COL = 10
FRAISE, POIRE, RAISIN, BANANE, SINGE = '🍓', '🍐', '🍇', '🍌', '🐒'
COULEURS = {FRAISE: (255, 35, 35), POIRE: (35, 155, 35), RAISIN: (45, 25, 125), BANANE:(255, 255, 45), SINGE:(155, 145, 112)}
POINTS = {FRAISE: 3, POIRE: 5, RAISIN: 8, BANANE : 10, None: 0}
def matrice_initiale():
"""Renvoie une matrice modélisant la répartition initiale des fruits sur la grille."""
global NB_LIG, NB_COL, FRAISE, POIRE, RAISIN, BANANE
mat = [[choices([FRAISE, POIRE, RAISIN, BANANE, None], weights = [1, 1, 1, 1, 10])[0] for _ in range(NB_COL)] for __ in range(NB_LIG)]
mat[0][0] = None
mat[NB_LIG-1][NB_COL-1] = None
return mat
def affichage(vue, plateau):
"""Affiche la grille et la zone de texte conformément à l'état du plateau de jeu."""
global NB_LIG, NB_COL, SINGE, COULEURS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
for lig in range(NB_LIG):
for col in range(NB_COL):
vue.mg('fond', lig, col, ci = (145, 243, 187), v = True)
if mat_fruits[lig][col] is not None:
vue.mg('texte', lig, col, tp = 25, t = mat_fruits[lig][col], c = COULEURS[mat_fruits[lig][col]], v = True)
else:
vue.mg('texte', lig, col, v = False)
vue.mg('fond', 0, 0, ci = (235, 124, 176))
vue.mg('fond', NB_LIG-1, NB_COL-1, ci = (235, 124, 176))
vue.mg('texte', lig_singe, col_singe, tp = 30, c = COULEURS[SINGE], t = SINGE, v = True)
vue.mzt(t = 'SCORE : ' + str(score), tp = 50, ct = (43, 56, 195), cf = (105, 203, 147))
if lig_singe == NB_LIG-1 and col_singe == NB_COL-1:
vue.mzt(t = 'PARTIE FINIE AVEC UN SCORE DE : ' + str(score) + ' !!!', tp = 50, ct = (43, 56, 195), cf = (105, 203, 147))
def bas(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un déplacement vers le bas est effectué.
"""
global NB_LIG, POINTS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
if lig_singe < NB_LIG - 1:
lig_singe = lig_singe + 1
score = score + POINTS[mat_fruits[lig_singe][col_singe]]
mat_fruits[lig_singe][col_singe] = None
plateau['mat_fruits'], plateau['lig_singe'], plateau['score'] = mat_fruits, lig_singe, score
affichage(vue, plateau)
def droite(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un déplacement vers la droite est effectué.
"""
global NB_COL, POINTS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
if col_singe < NB_COL - 1:
col_singe = col_singe + 1
score = score + POINTS[mat_fruits[lig_singe][col_singe]]
mat_fruits[lig_singe][col_singe] = None
plateau['mat_fruits'], plateau['col_singe'], plateau['score'] = mat_fruits, col_singe, score
affichage(vue, plateau)
def gestion_appui_touche(vue, evenement, argument):
plateau = argument
if evenement[...] == ...:
bas(..., ...)
elif evenement[...] == ...:
droite(..., ...)
def nouvelle_partie():
global NB_LIG, NB_COL
vue = ig.Vue(NB_LIG, NB_COL, env='basthon', police = 'emoji', utiliser_zonetexte = True)
ig.plt.show()
plateau = {'mat_fruits' : matrice_initiale(), 'lig_singe': 0, 'col_singe': 0, 'score': 0}
affichage(vue, plateau)
# rajouter ici la liaison (binding) entre l'évènement `appui_touche` et la fonction `gestion_appui_touche`
return vue, plateau
xxxxxxxxxx
vue, plateau = nouvelle_partie()
xxxxxxxxxx
bas(vue, plateau)
xxxxxxxxxx
droite(vue, plateau)
xxxxxxxxxx
*Question 1 :*
Effectuer une partie de jeu en exécutant successivement plusieurs fois les cellules de code ci-dessus.
*Question 2 :*
- Dans la fonction `nouvelle_partie`, effectuer la liaison entre l'évènement de type `appui_touche` et la fonction gestionnaire `gestion_appui_touche(vue, evenement, argument)`, pour laquelle l'argument passé en argument sera le plateau de jeu,
- Compléter le code de la fonction `gestion_appui_touche` afin :
- qu'un appui sur la touche 2 provoque un déplacement vers le bas,
- qu'un appui sur la touche 6 provoque un déplacement vers la gauche.
*Remarque :* Ne pas oublier de cliquer une fois sur la grille pour rendre possible la détection des appuis sur les touches.
Question 1 :
Effectuer une partie de jeu en exécutant successivement plusieurs fois les cellules de code ci-dessus.
Question 2 :
Dans la fonction nouvelle_partie
, effectuer la liaison entre l'évènement de type appui_touche
et la fonction gestionnaire gestion_appui_touche(vue, evenement, argument)
, pour laquelle l'argument passé en argument sera le plateau de jeu,
Compléter le code de la fonction gestion_appui_touche
afin :
Remarque : Ne pas oublier de cliquer une fois sur la grille pour rendre possible la détection des appuis sur les touches.
xxxxxxxxxx
<details>
<summary style="border:1pt solid slateblue; border-radius:5pt; width:15%; color:slateblue; padding:3px; background-color: lightcyan"> Solution </summary>
<div style="border:1pt solid slateblue; border-radius:5pt; color:slateblue; padding:3px; background-color: lightcyan">
```python
import interface_grille as ig
from random import randint, choices
NB_LIG = 10
NB_COL = 10
FRAISE, POIRE, RAISIN, BANANE, SINGE = '🍓', '🍐', '🍇', '🍌', '🐒'
COULEURS = {FRAISE: (255, 35, 35), POIRE: (35, 155, 35), RAISIN: (45, 25, 125), BANANE:(255, 255, 45), SINGE:(155, 145, 112)}
POINTS = {FRAISE: 3, POIRE: 5, RAISIN: 8, BANANE : 10, None: 0}
def matrice_initiale():
"""Renvoie une matrice modélisant la répartition initiale des fruits sur la grille."""
global NB_LIG, NB_COL, FRAISE, POIRE, RAISIN, BANANE
mat = [[choices([FRAISE, POIRE, RAISIN, BANANE, None], weights = [1, 1, 1, 1, 10])[0] for _ in range(NB_COL)] for __ in range(NB_LIG)]
mat[0][0] = None
mat[NB_LIG-1][NB_COL-1] = None
return mat
def affichage(vue, plateau):
"""Affiche la grille et la zone de texte conformément à l'état du plateau de jeu."""
global NB_LIG, NB_COL, SINGE, COULEURS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
for lig in range(NB_LIG):
for col in range(NB_COL):
vue.mg('fond', lig, col, ci = (145, 243, 187), v = True)
if mat_fruits[lig][col] is not None:
vue.mg('texte', lig, col, tp = 25, t = mat_fruits[lig][col], c = COULEURS[mat_fruits[lig][col]], v = True)
else:
vue.mg('texte', lig, col, v = False)
vue.mg('fond', 0, 0, ci = (235, 124, 176))
vue.mg('fond', NB_LIG-1, NB_COL-1, ci = (235, 124, 176))
vue.mg('texte', lig_singe, col_singe, tp = 30, c = COULEURS[SINGE], t = SINGE, v = True)
vue.mzt(t = 'SCORE : ' + str(score), tp = 50, ct = (43, 56, 195), cf = (105, 203, 147))
if lig_singe == NB_LIG-1 and col_singe == NB_COL-1:
vue.mzt(t = 'PARTIE FINIE AVEC UN SCORE DE : ' + str(score) + ' !!!', tp = 50, ct = (43, 56, 195), cf = (105, 203, 147))
def bas(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un déplacement vers le bas est effectué.
"""
global NB_LIG, POINTS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
if lig_singe < NB_LIG - 1:
lig_singe = lig_singe + 1
score = score + POINTS[mat_fruits[lig_singe][col_singe]]
mat_fruits[lig_singe][col_singe] = None
plateau['mat_fruits'], plateau['lig_singe'], plateau['score'] = mat_fruits, lig_singe, score
affichage(vue, plateau)
def droite(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un déplacement vers la droite est effectué.
"""
global NB_COL, POINTS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
if col_singe < NB_COL - 1:
col_singe = col_singe + 1
score = score + POINTS[mat_fruits[lig_singe][col_singe]]
mat_fruits[lig_singe][col_singe] = None
plateau['mat_fruits'], plateau['col_singe'], plateau['score'] = mat_fruits, col_singe, score
affichage(vue, plateau)
def gestion_appui_touche(vue, evenement, argument):
plateau = argument
if evenement['touche'] == '2':
bas(vue, plateau)
elif evenement['touche'] == '6':
droite(vue, plateau)
def nouvelle_partie():
global NB_LIG, NB_COL
vue = ig.Vue(NB_LIG, NB_COL, env='basthon', police = 'emoji', utiliser_zonetexte = True)
ig.plt.show()
plateau = {'mat_fruits' : matrice_initiale(), 'lig_singe': 0, 'col_singe': 0, 'score': 0}
affichage(vue, plateau)
# rajouter ici la liaison (binding) entre l'évènement `appui_touche` et la fonction `gestion_appui_touche`
vue.lier_evenement('appui_touche', gestion_appui_touche, activer = True, argument = plateau)
return vue, plateau
```
</div>
</details>
import interface_grille as ig
from random import randint, choices
NB_LIG = 10
NB_COL = 10
FRAISE, POIRE, RAISIN, BANANE, SINGE = '🍓', '🍐', '🍇', '🍌', '🐒'
COULEURS = {FRAISE: (255, 35, 35), POIRE: (35, 155, 35), RAISIN: (45, 25, 125), BANANE:(255, 255, 45), SINGE:(155, 145, 112)}
POINTS = {FRAISE: 3, POIRE: 5, RAISIN: 8, BANANE : 10, None: 0}
def matrice_initiale():
"""Renvoie une matrice modélisant la répartition initiale des fruits sur la grille."""
global NB_LIG, NB_COL, FRAISE, POIRE, RAISIN, BANANE
mat = [[choices([FRAISE, POIRE, RAISIN, BANANE, None], weights = [1, 1, 1, 1, 10])[0] for _ in range(NB_COL)] for __ in range(NB_LIG)]
mat[0][0] = None
mat[NB_LIG-1][NB_COL-1] = None
return mat
def affichage(vue, plateau):
"""Affiche la grille et la zone de texte conformément à l'état du plateau de jeu."""
global NB_LIG, NB_COL, SINGE, COULEURS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
for lig in range(NB_LIG):
for col in range(NB_COL):
vue.mg('fond', lig, col, ci = (145, 243, 187), v = True)
if mat_fruits[lig][col] is not None:
vue.mg('texte', lig, col, tp = 25, t = mat_fruits[lig][col], c = COULEURS[mat_fruits[lig][col]], v = True)
else:
vue.mg('texte', lig, col, v = False)
vue.mg('fond', 0, 0, ci = (235, 124, 176))
vue.mg('fond', NB_LIG-1, NB_COL-1, ci = (235, 124, 176))
vue.mg('texte', lig_singe, col_singe, tp = 30, c = COULEURS[SINGE], t = SINGE, v = True)
vue.mzt(t = 'SCORE : ' + str(score), tp = 50, ct = (43, 56, 195), cf = (105, 203, 147))
if lig_singe == NB_LIG-1 and col_singe == NB_COL-1:
vue.mzt(t = 'PARTIE FINIE AVEC UN SCORE DE : ' + str(score) + ' !!!', tp = 50, ct = (43, 56, 195), cf = (105, 203, 147))
def bas(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un déplacement vers le bas est effectué.
"""
global NB_LIG, POINTS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
if lig_singe < NB_LIG - 1:
lig_singe = lig_singe + 1
score = score + POINTS[mat_fruits[lig_singe][col_singe]]
mat_fruits[lig_singe][col_singe] = None
plateau['mat_fruits'], plateau['lig_singe'], plateau['score'] = mat_fruits, lig_singe, score
affichage(vue, plateau)
def droite(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un déplacement vers la droite est effectué.
"""
global NB_COL, POINTS
mat_fruits, lig_singe, col_singe, score = plateau['mat_fruits'], plateau['lig_singe'], plateau['col_singe'], plateau['score']
if col_singe < NB_COL - 1:
col_singe = col_singe + 1
score = score + POINTS[mat_fruits[lig_singe][col_singe]]
mat_fruits[lig_singe][col_singe] = None
plateau['mat_fruits'], plateau['col_singe'], plateau['score'] = mat_fruits, col_singe, score
affichage(vue, plateau)
def gestion_appui_touche(vue, evenement, argument):
plateau = argument
if evenement['touche'] == '2':
bas(vue, plateau)
elif evenement['touche'] == '6':
droite(vue, plateau)
def nouvelle_partie():
global NB_LIG, NB_COL
vue = ig.Vue(NB_LIG, NB_COL, env='basthon', police = 'emoji', utiliser_zonetexte = True)
ig.plt.show()
plateau = {'mat_fruits' : matrice_initiale(), 'lig_singe': 0, 'col_singe': 0, 'score': 0}
affichage(vue, plateau)
# rajouter ici la liaison (binding) entre l'évènement `appui_touche` et la fonction `gestion_appui_touche`
vue.lier_evenement('appui_touche', gestion_appui_touche, activer = True, argument = plateau)
return vue, plateau
xxxxxxxxxx
# IV : Un second exemple passant du mode «fonctionnel» au mode «évènementiel»
La cellule de code ci-dessous permet d'obtenir un «jeu» dans lequel l'utilisateur peut générer des grilles de labyrinthe.
<br/>
---
Le «plateau de jeu» `plateau` est un dictionnaire contenant :
- une matrice indiquant les murs verticaux,
- une matrice indiquant les murs horizontaux,
- un booléen indiquant si les séparations des cases doivent être indiquées :
- une couleur extérieure identique à la couleur intérieure est préférable pour l'export en PNG,
- une couleur extérieure noire est préférable pour savoir où cliquer pour faire apparaître un mur.
Au fur et à mesure de la création du labyrinthe, chacun de ces trois éléments du plateau de jeu est susceptible d'évoluer.
Regrouper ces trois éléments dans un seul objet (ici un dictionnaire) permet de les passer de façon très simple en argument aux fonctions, et cela permet aussi de faciliter le travail de notre cerveau (quand on code, on sait que TOUTES les informations qui modélisent l'état du plateau de jeu sont contenues dans la variable `plateau`).
En classe de terminale, on pourrait créer une classe `Plateau` ...
<br/>
---
Les variables globales (dont les noms sont en `MAJUSCULES`) sont les constantes correspondent à des informations qui ne changent pas au cours du jeu.
<br/>
---
Pour jouer il suffit :
- d'exécuter l'instruction `vue, plateau = nouvelle_partie()`
- puis d'exécuter l'instruction `modifier_mur(vue, plateau, lig, col, direction)` qui va :
- faire apparaître le mur si celui-ci était caché,
- faire disparaître le mur si celui n'était pas caché.
- ou d'exécuter l'instruction `modifier_separations(vue, plateau)` qui va mettre la couleur extérieure des fonds de case :
- identique à la couleur intérieure si la couleur extérieure était en noir,
- en noir si la couleur extérieure était identique à la couleur intérieure.
<br/>
---
*Remarque : La sélection d'objet ne fonctionne que sur les objets ayant la propriété `visible = True`. Donc pour pouvoir être adapté en utilisant uniquement la souris, les murs sont tous visibles **mais** :*
- *les murs qui ne doivent pas être affichés ont une transparence `alpha = 0`,*
- *les murs qui doivent être affichés ont une transparence `alpha = 1`.*
La cellule de code ci-dessous permet d'obtenir un «jeu» dans lequel l'utilisateur peut générer des grilles de labyrinthe.
Le «plateau de jeu» plateau
est un dictionnaire contenant :
Au fur et à mesure de la création du labyrinthe, chacun de ces trois éléments du plateau de jeu est susceptible d'évoluer.
Regrouper ces trois éléments dans un seul objet (ici un dictionnaire) permet de les passer de façon très simple en argument aux fonctions, et cela permet aussi de faciliter le travail de notre cerveau (quand on code, on sait que TOUTES les informations qui modélisent l'état du plateau de jeu sont contenues dans la variable plateau
).
En classe de terminale, on pourrait créer une classe Plateau
...
Les variables globales (dont les noms sont en MAJUSCULES
) sont les constantes correspondent à des informations qui ne changent pas au cours du jeu.
Pour jouer il suffit :
d'exécuter l'instruction vue, plateau = nouvelle_partie()
puis d'exécuter l'instruction modifier_mur(vue, plateau, lig, col, direction)
qui va :
ou d'exécuter l'instruction modifier_separations(vue, plateau)
qui va mettre la couleur extérieure des fonds de case :
Remarque : La sélection d'objet ne fonctionne que sur les objets ayant la propriété visible = True
. Donc pour pouvoir être adapté en utilisant uniquement la souris, les murs sont tous visibles mais :
alpha = 0
,alpha = 1
.xxxxxxxxxx
import interface_grille as ig
from random import randint, choices
NB_LIG = 5
NB_COL = 5
COULEURS = {'mur': (125, 205, 35), 'fond': (215, 255, 175)}
def matrices_initiales():
"""Renvoie deux matrices modélisant les murs horizontaux et verticaux."""
global NB_LIG, NB_COL
murs_h = [[True for col in range(NB_COL)] for lig in range(NB_LIG + 1)]
murs_v = [[True for col in range(NB_COL + 1)] for lig in range(NB_LIG)]
return murs_h, murs_v
def affichage(vue, plateau):
"""Affiche la grille conformément à l'état du plateau de jeu."""
global NB_LIG, NB_COL, COULEURS
murs_h, murs_v, separations = plateau['murs_h'], plateau['murs_v'], plateau['separations']
for lig in range(NB_LIG):
for col in range(NB_COL):
if separations :
vue.mg('fond', lig, col, ci = COULEURS['fond'], ce = (0, 0, 0), v = True)
else:
vue.mg('fond', lig, col, c = COULEURS['fond'], v = True)
if murs_h[lig][col] :
vue.mg('mur', lig, col, d = 'N', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, col, d = 'N', ci = COULEURS['mur'], a = 0, v = True)
if murs_v[lig][col] :
vue.mg('mur', lig, col, d = 'O', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, col, d = 'O', ci = COULEURS['mur'], a = 0, v = True)
for lig in range(NB_LIG):
if murs_v[lig][NB_COL] :
vue.mg('mur', lig, NB_COL - 1, d = 'E', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, NB_COL - 1, d = 'E', ci = COULEURS['mur'], a = 0, v = True)
for col in range(NB_COL):
if murs_h[NB_LIG][col] :
vue.mg('mur', NB_LIG - 1, col, d = 'S', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', NB_LIG - 1, col, d = 'S', ci = COULEURS['mur'], a = 0, v = True)
def modifier_mur(vue, plateau, lig, col, direction):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un mur est modifié.
"""
global NB_LIG, NB_COL
murs_h, murs_v = plateau['murs_h'], plateau['murs_v']
if direction == 'N':
murs_h[lig][col] = not murs_h[lig][col]
elif direction == 'E':
murs_v[lig][col+1] = not murs_v[lig][col+1]
elif direction == 'S':
murs_h[lig+1][col] = not murs_h[lig+1][col]
elif direction == 'O':
murs_v[lig][col] = not murs_v[lig][col]
plateau['murs_h'], plateau['murs_v'] = murs_h, murs_v
affichage(vue, plateau)
def modifier_separations(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage lorsqu'on demande
à changer l'affichage de de la couleur extérieure des fonds de cases.
"""
plateau['separations'] = not plateau['separations']
affichage(vue, plateau)
def gestion_selection_objet(vue, evenement, argument):
plateau = argument
if evenement[...] == ... and evenement[...] == ...:
modifier_mur(..., ..., evenement[...], evenement[...], evenement[...])
def gestion_clic_souris(vue, evenement, plateau):
if evenement[...] == ...:
modifier_separations(..., ...)
def nouvelle_partie():
global NB_LIG, NB_COL
vue = ig.Vue(NB_LIG, NB_COL, env='basthon', utiliser_zonetexte = True)
ig.plt.show()
murs_h, murs_v = matrices_initiales()
plateau = {'murs_h' : murs_h, 'murs_v': murs_v, 'separations': True}
affichage(vue, plateau)
# rajouter ici la liaison (binding) entre l'évènement `selection_objet` et la fonction `gestion_selection_objet`
# rajouter ici la liaison (binding) entre l'évènement `clic_souris` et la fonction `gestion_clic_souris`
return vue, plateau
xxxxxxxxxx
vue, plateau = nouvelle_partie()
xxxxxxxxxx
modifier_mur(vue, plateau, 3, 2, 'O')
modifier_mur(vue, plateau, 4, 2, 'E')
modifier_mur(vue, plateau, 1, 3, 'S')
modifier_mur(vue, plateau, 3, 2, 'N')
xxxxxxxxxx
modifier_separations(vue, plateau)
xxxxxxxxxx
*Question 1 :*
Créer un labyrinthe en exécutant successivement plusieurs fois les cellules de code ci-dessus (on modifiera évidemment les indices de ligne et de colonne ainsi que la direction des murs à supprimer ou à ajouter).
*Question 2 :*
- Dans la fonction `nouvelle_partie`, effectuer la liaison entre :
- l'évènement de type `selection_objet` et la fonction gestionnaire `gestion_selection_objet(vue, evenement, argument)`, pour laquelle l'argument passé en argument sera le plateau de jeu,
- l'évènement de type `clic_souris` et la fonction gestionnaire `gestion_clic_souris(vue, evenement, argument)`, pour laquelle l'argument passé en argument sera le plateau de jeu.
- Compléter le code de la fonction `gestion_selection_objet` afin que la sélection d'un mur avec le bouton gauche de la souris le fasse apparaître ou disparaître.
- Compléter le code de la fonction `gestion_clic_souris` afin qu'un clic de la souris avec le bouton droit de la souris fasse apparaître ou disparaître les séparations entre les fonds des cases.
Question 1 :
Créer un labyrinthe en exécutant successivement plusieurs fois les cellules de code ci-dessus (on modifiera évidemment les indices de ligne et de colonne ainsi que la direction des murs à supprimer ou à ajouter).
Question 2 :
Dans la fonction nouvelle_partie
, effectuer la liaison entre :
selection_objet
et la fonction gestionnaire gestion_selection_objet(vue, evenement, argument)
, pour laquelle l'argument passé en argument sera le plateau de jeu,clic_souris
et la fonction gestionnaire gestion_clic_souris(vue, evenement, argument)
, pour laquelle l'argument passé en argument sera le plateau de jeu.Compléter le code de la fonction gestion_selection_objet
afin que la sélection d'un mur avec le bouton gauche de la souris le fasse apparaître ou disparaître.
Compléter le code de la fonction gestion_clic_souris
afin qu'un clic de la souris avec le bouton droit de la souris fasse apparaître ou disparaître les séparations entre les fonds des cases.
xxxxxxxxxx
<details>
<summary style="border:1pt solid slateblue; border-radius:5pt; width:15%; color:slateblue; padding:3px; background-color: lightcyan"> Solution </summary>
<div style="border:1pt solid slateblue; border-radius:5pt; color:slateblue; padding:3px; background-color: lightcyan">
```python
import interface_grille as ig
from random import randint, choices
NB_LIG = 5
NB_COL = 5
COULEURS = {'mur': (125, 205, 35), 'fond': (215, 255, 175)}
def matrices_initiales():
"""Renvoie deux matrices modélisant les murs horizontaux et verticaux."""
global NB_LIG, NB_COL
murs_h = [[True for col in range(NB_COL)] for lig in range(NB_LIG + 1)]
murs_v = [[True for col in range(NB_COL + 1)] for lig in range(NB_LIG)]
return murs_h, murs_v
def affichage(vue, plateau):
"""Affiche la grille conformément à l'état du plateau de jeu."""
global NB_LIG, NB_COL, COULEURS
murs_h, murs_v, separations = plateau['murs_h'], plateau['murs_v'], plateau['separations']
for lig in range(NB_LIG):
for col in range(NB_COL):
if separations :
vue.mg('fond', lig, col, ci = COULEURS['fond'], ce = (0, 0, 0), v = True)
else:
vue.mg('fond', lig, col, c = COULEURS['fond'], v = True)
if murs_h[lig][col] :
vue.mg('mur', lig, col, d = 'N', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, col, d = 'N', ci = COULEURS['mur'], a = 0, v = True)
if murs_v[lig][col] :
vue.mg('mur', lig, col, d = 'O', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, col, d = 'O', ci = COULEURS['mur'], a = 0, v = True)
for lig in range(NB_LIG):
if murs_v[lig][NB_COL] :
vue.mg('mur', lig, NB_COL - 1, d = 'E', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, NB_COL - 1, d = 'E', ci = COULEURS['mur'], a = 0, v = True)
for col in range(NB_COL):
if murs_h[NB_LIG][col] :
vue.mg('mur', NB_LIG - 1, col, d = 'S', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', NB_LIG - 1, col, d = 'S', ci = COULEURS['mur'], a = 0, v = True)
def modifier_mur(vue, plateau, lig, col, direction):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un mur est modifié.
"""
global NB_LIG, NB_COL
murs_h, murs_v = plateau['murs_h'], plateau['murs_v']
if direction == 'N':
murs_h[lig][col] = not murs_h[lig][col]
elif direction == 'E':
murs_v[lig][col+1] = not murs_v[lig][col+1]
elif direction == 'S':
murs_h[lig+1][col] = not murs_h[lig+1][col]
elif direction == 'O':
murs_v[lig][col] = not murs_v[lig][col]
plateau['murs_h'], plateau['murs_v'] = murs_h, murs_v
affichage(vue, plateau)
def modifier_separations(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage lorsqu'on demande
à changer l'affichage de de la couleur extérieure des fonds de cases.
"""
plateau['separations'] = not plateau['separations']
affichage(vue, plateau)
def gestion_selection_objet(vue, evenement, argument):
plateau = argument
if evenement['bouton'] == 'gauche' and evenement['objet'] == 'mur':
modifier_mur(vue, plateau, evenement['lig'], evenement['col'], evenement['dir'])
def gestion_clic_souris(vue, evenement, plateau):
if evenement['bouton'] == 'droit':
modifier_separations(vue, plateau)
def nouvelle_partie():
global NB_LIG, NB_COL
vue = ig.Vue(NB_LIG, NB_COL, env='basthon', utiliser_zonetexte = True)
ig.plt.show()
murs_h, murs_v = matrices_initiales()
plateau = {'murs_h' : murs_h, 'murs_v': murs_v, 'separations': True}
affichage(vue, plateau)
# rajouter ici la liaison (binding) entre l'évènement `selection_objet` et la fonction `gestion_selection_objet`
vue.lier_evenement('selection_objet', gestion_selection_objet, activer = True, argument = plateau)
# rajouter ici la liaison (binding) entre l'évènement `clic_souris` et la fonction `gestion_clic_souris`
vue.lier_evenement('clic_souris', gestion_clic_souris, activer = True, argument = plateau)
return vue, plateau
```
</div>
</details>
import interface_grille as ig
from random import randint, choices
NB_LIG = 5
NB_COL = 5
COULEURS = {'mur': (125, 205, 35), 'fond': (215, 255, 175)}
def matrices_initiales():
"""Renvoie deux matrices modélisant les murs horizontaux et verticaux."""
global NB_LIG, NB_COL
murs_h = [[True for col in range(NB_COL)] for lig in range(NB_LIG + 1)]
murs_v = [[True for col in range(NB_COL + 1)] for lig in range(NB_LIG)]
return murs_h, murs_v
def affichage(vue, plateau):
"""Affiche la grille conformément à l'état du plateau de jeu."""
global NB_LIG, NB_COL, COULEURS
murs_h, murs_v, separations = plateau['murs_h'], plateau['murs_v'], plateau['separations']
for lig in range(NB_LIG):
for col in range(NB_COL):
if separations :
vue.mg('fond', lig, col, ci = COULEURS['fond'], ce = (0, 0, 0), v = True)
else:
vue.mg('fond', lig, col, c = COULEURS['fond'], v = True)
if murs_h[lig][col] :
vue.mg('mur', lig, col, d = 'N', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, col, d = 'N', ci = COULEURS['mur'], a = 0, v = True)
if murs_v[lig][col] :
vue.mg('mur', lig, col, d = 'O', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, col, d = 'O', ci = COULEURS['mur'], a = 0, v = True)
for lig in range(NB_LIG):
if murs_v[lig][NB_COL] :
vue.mg('mur', lig, NB_COL - 1, d = 'E', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', lig, NB_COL - 1, d = 'E', ci = COULEURS['mur'], a = 0, v = True)
for col in range(NB_COL):
if murs_h[NB_LIG][col] :
vue.mg('mur', NB_LIG - 1, col, d = 'S', ci = COULEURS['mur'], a = 1, v = True)
else:
vue.mg('mur', NB_LIG - 1, col, d = 'S', ci = COULEURS['mur'], a = 0, v = True)
def modifier_mur(vue, plateau, lig, col, direction):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage
lorsqu'un mur est modifié.
"""
global NB_LIG, NB_COL
murs_h, murs_v = plateau['murs_h'], plateau['murs_v']
if direction == 'N':
murs_h[lig][col] = not murs_h[lig][col]
elif direction == 'E':
murs_v[lig][col+1] = not murs_v[lig][col+1]
elif direction == 'S':
murs_h[lig+1][col] = not murs_h[lig+1][col]
elif direction == 'O':
murs_v[lig][col] = not murs_v[lig][col]
plateau['murs_h'], plateau['murs_v'] = murs_h, murs_v
affichage(vue, plateau)
def modifier_separations(vue, plateau):
"""
Modifie l'état du plateau de jeu puis actualise l'affichage lorsqu'on demande
à changer l'affichage de de la couleur extérieure des fonds de cases.
"""
plateau['separations'] = not plateau['separations']
affichage(vue, plateau)
def gestion_selection_objet(vue, evenement, argument):
plateau = argument
if evenement['bouton'] == 'gauche' and evenement['objet'] == 'mur':
modifier_mur(vue, plateau, evenement['lig'], evenement['col'], evenement['dir'])
def gestion_clic_souris(vue, evenement, plateau):
if evenement['bouton'] == 'droit':
modifier_separations(vue, plateau)
def nouvelle_partie():
global NB_LIG, NB_COL
vue = ig.Vue(NB_LIG, NB_COL, env='basthon', utiliser_zonetexte = True)
ig.plt.show()
murs_h, murs_v = matrices_initiales()
plateau = {'murs_h' : murs_h, 'murs_v': murs_v, 'separations': True}
affichage(vue, plateau)
# rajouter ici la liaison (binding) entre l'évènement `selection_objet` et la fonction `gestion_selection_objet`
vue.lier_evenement('selection_objet', gestion_selection_objet, activer = True, argument = plateau)
# rajouter ici la liaison (binding) entre l'évènement `clic_souris` et la fonction `gestion_clic_souris`
vue.lier_evenement('clic_souris', gestion_clic_souris, activer = True, argument = plateau)
return vue, plateau
xxxxxxxxxx
# V : Bugs
L'appui sur certaines touches n'est pas détecté lorsque la combinaison de touches est un raccourci clavier du navigateur :
- Firefox :
- appui sur la touche apostrophe `"'"` ne peut pas être pris en compte (ouvre la recherche rapide de Firefox).
- Chrome :
- rien de détecté à ce jour.
L'appui sur certaines touches n'est pas détecté lorsque la combinaison de touches est un raccourci clavier du navigateur :
Firefox :
"'"
ne peut pas être pris en compte (ouvre la recherche rapide de Firefox).Chrome :