Jeu classique, le démineur |
Le démineur
qui est proposé ici est très simplifié. L'objectif
est de proposer un exemple possible de fonctionnement sans la moindre
fioriture, véritable ligne mélodique propre à des
interprétations y compris lorsque celles-ci permettront de créer
autre chose qu'un démineur... en effet que pourrait-on faire d'autre
à partir d'un démineur ? |
![]() |
TELECHARGER aaaTexte des explications, aaaExecutable (Windows), aaaSource (utilise la librairie Allegro)
|
![]() |
EXPLICATIONS 1. Principe du jeu Il s’agit de
découvrir des mines dans un terrain miné sans déclancher
d’explositon. En général le terrain est représenté
par une grille dont la taille peut éventuellement être dynamique. aaaaaaaaa Sur l'image ci-dessus,
le curseur indique la position du clic. En gris se trouve la zone découverte.
Pour chaque case qui contient un nombre ce nombre indique le nombre de
mines présentes dans les cases adjacentes. L’objectif
est de découvrir si possible toutes les mines dans le temps le
plus court. 2. Mise en forme et initialisation Le terrain est représenté
par une matrice de TY lignes de TX colonnes définies par : Une case sans rien
aura la valeur 0 et une case avec mine aura la valeur MINE définie
par le nombre maximum de cases voisines (huit) plus un : La première fonction est celle de l’initialisation du terrain miné. Elle prend comme paramètres la matrice qui représente le terrain et le nombre de mines à disséminer dedans. aaaaavoid
init_mine(int t[TY][TX], int nb_mines) (3)aaaaafor
(y=0; y<TY; y++) (1) La matrice est premièrement entièrement initialisée avec des valeurs de 0. (2) Ensuite des positions sont obtenues de façon aléatoire et si la position ne contient pas déjà une mine, c’est dire si la valeur à la position est différente de la valeur MINE alors la position prend la valeur MINE qui indique une mine. (3) Il s’agit de comptabiliser pour chaque position le nombre des mines contenues dans les cellules voisines. Pour ce faire la matrice est parcourue entièrement et pour chaque position avec une mine les huit positions voisines sont incrémentées de 1, c’est le rôle de la fonction increment_voisins() : void increment_voisins(int
t[TY][TX],int x, int y) (1) Il faut contrôler
que la position pour x comme pour y est bien dans la matrice. L’initialisation
du jeu se clôt sur un affichage de la matrice. Dans le programme
présenté, nous l’avons centré à l’écran
à l’aide des valeurs DECX et DECY définies de la façon
suivante : La taille des carreaux
est définie par : La fonction d’affichage
dessine une grille centrée à l’écran avec TY*TX
carreaux de TCAR taille, la couleur est verte : 3. Processus du jeu 1) Il n’y a rien à cette case, elle est à 0. Dans ce cas elle passe à -1 pour indiquer qu ’elle est découverte et une recherche récursive sur les cases voisines est lancée. Lorsqu’une case est à -1 rien ne se passe, il n’y a pas d’appel récursif. 2) Il y a une mine dans ce cas la partie est perdue, en général toutes les mines sont alors découvertes et affichées. 3) Si la case est voisine d’une ou plusieurs mines, le nombre de mines voisines de cette case est affiché dans cette case. Deux fonctions réalisent
ces opérations. Une fonction de recherche, récursive dans
le cas 1 et une simple fonction d’affichage des mines dans le cas
2. (1)aaaaaint
cherche(int t[TY][TX],int x,int y) (1) La fonction prend
trois paramètres : la matrice de la zone de jeu et une position
(x,y). (2) Tout d’abord contrôle de la position (x,y) qui doit être dans la matrice. (3) Calcule de la position correspondante à l'écran et récupération des valeurs dans les variables xe, ye. (4) Selon la valeur dans la matrice à la position x,y, plusieurs cas sont possibles, d’où l’utilisation d’un switch. (5) Dans ce premier cas il y a 0 dans la matrice, rien, alors la position est mise à -1 pour indiquer qu’elle est découverte, un rectangle plein vert est dessiné à l’écran. Ensuite les positions adjacentes sont explorées par appels récursifs de la fonction cherche(). Les cas suivants des lignes (6) et (7) vont jouer le rôle de testes d’arrêt. (6) Si la position contient la valeur -1, tout est dit et rien ne se passe. (7) Si la position contient la valeur MINE, la partie est perdue. La variable res est mise à 1. La fonction qui affiche toutes les mines à l’écran est appelée. (8) Dans tous les
autres cas si la position contient un nombre compris entre 1 et 8, ce
qui indique un nombre de mines à proximité, ce nombre est
affiché à l’écran dans la case correspondante
une fois pour toute et la position de la matrice est mise à -1 Pour afficher les mines il suffit de parcourir toute la matrice jeu et dessiner à l’écran par exemple un rectangle rouge plein à chaque position qui contient une mine. Dans le cas ou une mine est couverte par un drapeau (voir gestion des drapeaux ci-dessous) la couleur est bleu cyan pour indiquer une mine trouvée. aaaaavoid
affiche_mines(int t[TY][TX]) Le joueur décide
de placer ou d’enlever un drapeau à une position qu’il
choisit avec un clic droit. Si la case ne contient pas de drapeau un drapeau
est ajouté. Le drapeau est une valeur numérique supérieure
à celle de MINE définit par : Ainsi poser un drapeau
revient à incrémenter de 10 la case concernée dans
la matrice, à l’inverse retirer un drapeau, s’il y
en a un revient à soustraire 10 pour la position concernée. (1)aaaaavoid
drapeaux(int t[TY][TX],int x, int y) (2)aaaaaif
(x>=0 && x<TX && y>=0 && y<TY){ (1) La fonction drapeu prend en paramètres la matrice zone de jeu et une position (donnée par un clic droit. (2) Vérification que la position passée est bien dans la matrice. Ensuite les coordonnées écran sont tout d’abord calculées (3)(4) La valeur
à la position est examinée. Si elle n’est pas déjà
une position découverte (-1) ou s’il n’y a pas de drapeau
( valeur supérieure à MINE) la valeur DRAPEAU (10) est ajoutée. 4. Boucle d’événements (1)aaaaint
stop =0 ; (2)aaaawhile
(!key[KEY_ESC]){ (5)aaaaaaaaaif
(clic&2) (1) Préliminaire à cette boucle, tout d’abord la présence d’une variable « stop » mise à 0 et qui va permettre de bloquer le jeu lorsque la partie sera terminée. Vient plus loin l’initialisation de la matrice jeu avec des mines. Le nombre de mines est ici un dixième par rapport au nombre total des positions dans la matrice. Pour finir la matrice est affichée à l’écran. (2) Le teste d’arrêt de la boucle while est un appuie sur escape. Le premier point est la capture dans la variable clic de l’état de la souris donné par la variable mouse_b. (3) Si il y a clic et si la partie n’est pas terminée, on attend le relâchement du clic, on passe d’une position donnée en pixels à l’écran à une position en coordonnées matrice (soustraire le décalage à gauche et diviser par la taille d’un carreau). (4) S’il s’agit d’un clic gauche, la fonction cherche() est appelée à partir de la position matrice donnée et la variable stop est mise à jour avec la valeur de retour. Dans le cas où il y ait un affichage à l’écran il convient de cacher le curseur de la souris afin qu’il ne gène pas l’affichage sur la partie d’écran qu’il recouvre. (5) S’il s’agit d’un clic droit c’est la fonction de gestion des drapeaux qui est appelée. (6) Appuyer sur la
touche enter permet de réinitialiser le jeu et commencer une nouvelle
partie (initialisation avec mines de la matrice, affichage de la matrice-jeu
à l’écran, mise à 0 de la variable «
stop » de contrôle de la partie. |
![]() |