TP 2 : le puissance 4
🎯 Objectifs
- Premier jeu en C
- Manipuler les fichiers header (.h)
🔧 Matériel nécessaire
- Ordinateur avec compilateur gcc
- CodeBlocks/VS Code
Règles du puissance 4
L’objectif du puissance 4 est d’aligner quatre jetons sur une grille verticale composée de 6 lignes et 7 colonnes. Deux joueurs s’affrontent en tour par tour en plaçant un jeton dans une colonne. Lorsqu’un joueur aligne quatre jetons horizontalement, verticalement ou diagonalement, il remporte la partie. Si toutes les cases sont remplies sans qu’un joueur n’ait réussi à aligner quatre jetons, alors la partie est déclarée nulle.
Fichier header
Sur Arche, vous trouverez un fichier header nommé puissance4.h. Créez un projet sous CodeBlocks et y ajouter ce fichier.
#include <stdio.h>
#include <stdlib.h>
#define LIGNES 6
#define COLONNES 7
enum jeton {CROIX=1, ROND=2};
typedef struct {
char pseudo[20];
enum jeton couleur;
} joueur;
//Prototypes de fonctions
void afficher_plateau(int tab[LIGNES][COLONNES]);
int combien_dans_colonne(int tab[LIGNES][COLONNES],int col);
int empiler(int tab[LIGNES][COLONNES], int col, int couleur);
int combien_dans_direction(int tab[LIGNES][COLONNES], int couleur, int col, int d_l ,int d_c);
int test_ligne(int tab[LIGNES][COLONNES], int couleur, int col);
int test_colonne(int tab[LIGNES][COLONNES], int couleur, int col);
int test_diagonales(int tab[LIGNES][COLONNES], int couleur, int col);
int test_tout(int tab[LIGNES][COLONNES], int couleur, int col);
Dans ce TP, on ne se concentre pas sur le rendu graphique du jeu, l’affichage se fera directement dans la console. Pour différencier les jetons, on utilisera les symboles x (CROIX) et o (ROND) à la place des couleurs jaune et rouge.
Note
La syntaxe #define NOM valeur permet la création de macros. À la compilation, toutes les occurences de NOM dans le programme sont remplacées par valeur.
Tip
Pensez à utiliser des macros pour les constantes de vos programmes. Cela permet de diminuer le nombre de variables utilisées en mémoire.
Q1. Déclarez dans ce fichier un tableau d’entiers composé de 6 lignes et 7 colonnes nommé plateau.
On considère le codage suivant :
- 0 : case vide
- 1 : jeton CROIX
- 2 : jeton ROND
Affichage de la grille
Q2. Créez un fichier utilitaires.c qui va contenir toutes vos fonctions utiles.
Q3. Écrivez une fonction de prototype void afficher_plateau(int tab[LIGNES][COLONNES]); qui permet d’afficher le plateau de jeu selon la représentation suivante.
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | |x| | |
| | |x|o|o| | |
---------------
1 2 3 4 5 6 7
Warning
La ligne d’indice 0 du plateau correspond à la ligne du bas.
Q4. Créez un fichier puissance4.c contenant une fonction main() qui permet de tester votre fonction d’affichage.
Note
Pensez à importer votre ficher puissance4.h avec le mot clé #include.
Empilement des jetons
Afin d’empiler correctement les jetons, il est utile de connaître le nombre de jetons déjà présents dans une colonne.
Q5. Écrivez une fonction de prototype int combien_dans_colonne(int tab[LIGNES][COLONNES], int col); qui renvoie le nombre de jetons déjà présents dans la colonne col du tableau tab.
Q6. Écrivez une fonction de prototype int empiler(int tab[LIGNES][COLONNES], int col, int couleur); qui empile un jeton de couleur couleur dans la colonne col du tableau tab. Elle doit renvoyer 1 si l’empilage a été effectué, 0 si l’opération n’est pas faisable.
Note
Lorsque que l’on passe un tableau en argument, on y passe en réalité son adresse. Ainsi, lorsque l’on modifie le tableau à l’intérieur de la fonction, la variable est modifiée à l’extérieur également, ce qui explique que l’on ne renvoie pas la valeur du tableau.
Boucle de jeu
Q7. Modifiez la fonction main() afin de permettre à deux joueurs de jouer l’un après l’autre indéfiniment après avoir renseigné leurs pseudos. Pour l’instant, on ne vérifie pas si l’un des joueurs a gagné.
Note
Pensez à redemander une colonne au joueur tant qu’il ne renseigne pas une colonne jouable.
Vérification de succès
On va maintenant implémenter les différentes fonctions permettant de vérifier si un alignement de quatre jetons de la même couleur a été complété.
Tip
Si l’on vérifie les alignements à chaque coup, alors un des quatre jetons d’un alignement gagant est forcément le dernier jeton joué.
Q8. Écrivez une fonction de prototype int combien_dans_direction(int tab[LIGNES][COLONNES], int couleur, int col, int d_l, int d_c) qui compte le nombre de jetons successifs de couleur couleur dans la direction donnée par (d_l, d_c) depuis la position du dernier jeton joué en colonne col. On ne compte pas le jeton d’où l’on part.
Pour le plateau tab suivant :
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | |x|x|x| | |
| | |x|o|o|o| |
---------------
1 2 3 4 5 6 7
le code
int c1, c2, c3;
c1 = combien_dans_direction(tab, 1, 3, 0, 1);
c2 = combien_dans_direction(tab, 2, 6, 0, -1);
c3 = combien_dans_direction(tab, 1, 4, -1, -1);
printf("%d, %d, %d", c1, c2, c3);
affiche
2, 2, 1
Warning
Veillez à garder vos indices dans les limites du tableau.
Alignement horizontal
Q9. Écrivez une fonction de prototype int test_ligne(int tab[LIGNES][COLONNES], int couleur, int col); qui renvoie 1 si un alignement de quatre jetons de couleur couleur est présent sur la ligne du dernier jeton joué en colonne col. Sinon, elle renvoie 0.
Alignement vertical
Q10. Écrivez une fonction de prototype int test_colonne(int tab[LIGNES][COLONNES], int couleur, int col); qui renvoie 1 si un alignement de quatre jetons de couleur couleur est présent en colonne col. Sinon, elle renvoie 0.
Alignement diagonal
Q11. Écrivez une fonction de prototype int test_diagonales(int tab[LIGNES][COLONNES], int couleur, int col); qui renvoie 1 si un alignement de quatre jetons de couleur couleur est présent dans au moins une des diagonales passant par le dernier jeton joué en colonne col. Sinon, elle renvoie 0.
Synthèse des tests
Q12. Écrivez une fonction de prototype int test_tout(int tab[LIGNES][COLONNES], int couleur, int col); qui renvoie 1 si un alignement de quatre jetons de couleur couleur passant par le dernier jeton joué en colonne col est présent dans le tableau tab. Sinon, elle renvoie 0.
Programme final
Q13. Modifiez votre fonction main() pour obtenir le comportement suivant :
- au lancement du jeu, les joueurs renseignent leurs pseudos ;
- lorsqu’un joueur gagne :
- il est félicité par le programme ;
- son pseudo est ajouté au fichier texte
gagnants.txt;
- à la fin d’une partie, qu’elle soit nulle ou non, on propose de lancer une nouvelle partie.
Pour les plus téméraires
Proposez un algorithme de décision qui suggère une colonne à jouer pour un tableau et une couleur donnés. Votre algorithme doit pouvoir battre un joueur jouant de façon aléatoire.