INFO-F-101 Programmation Projet 3 Année académique 2009 2010 1 Introduction Reversi 1 est une variante du jeu Othello 2. Son principe est simple : deux joueurs disposent leurs jetons sur un plateau composé de 8 8 cases. Ces jetons ont une face blanche et une face noire. L un des joueurs joue avec les jetons tournés face blanche vers le haut, l autre avec la face noire tournée vers le haut. Le but de ce jeu est de retourner un maximum de jetons de son adversaire. Le joueur gagnant est celui qui a le plus de jetons de sa couleur à la fin de la partie. 1.1 Règles du jeu Au début de la partie, deux jetons de chaque joueur sont déjà positionnés dans le jeu (voir FIG 1). C est le joueur noir qui commence toujours une nouvelle partie. FIG. 1 Grille de départ Les joueurs jouent tour à tour et, à chaque tour, le joueur qui a la main doit placer un de ses jetons de sorte à tenter d enfermer un ou plusieurs jetons de l adversaire entre ce nouveau jeton et un de ses jetons déjà présent sur le plateau de jeu. Une fois les jetons de l adversaire enfermés, il ne reste plus qu à les retourner (voir FIG 2). Par jetons enfermés, on entend tout jeton du joueur adverse se trouvant entre ce nouveau jeton et un autre jeton du joueur, soit verticalement, horizontalement ou en diagonale. Il peut donc y avoir des retournements à faire sur plusieurs directions rien qu en ajoutant un jeton sur le plateau de jeu (voir FIG 3). 1 http ://fr.wikipedia.org/wiki/othello_(jeu) 2 Ce jeu est aussi appelé Lagno sur les distributions linux, dont celles présentes aux salles PC du NO4. Ce projet n est cependant pas une raison suffisante pour aller y jouer au lieu de faire le projet. Par contre si vous finissez le projet à temps... 1
FIG. 2 Après avoir placé le jeton noir, on retourne le jeton blanc enfermé. FIG. 3 Tout jeton du joueur noir se trouvant entre le nouveau jeton du joueur blanc et un autre jeton blanc déjà présent sur la plateau de jeu et ce soit verticalement, horizontalement ou en diagonale, doit être retourné. Autre point important : à chaque fois qu un joueur pose un jeton, il doit au moins retourner un jeton de son adversaire. Si aucun retournement n est engendré par le nouveau jeton du joueur en cours, le joueur doit alors choisir une autre position où mettre son jeton. Si aucune position ne permet au joueur de pouvoir placer son jeton, il passe son tour. De ce fait, la fin de la partie peut avoir lieu si une des deux conditions suivantes est remplie : 1. Toutes les cases du plateau sont remplies. 2. Aucun des deux joueurs ne peut jouer. 2 Utilisation du jeu 1. Au lancement du programme, ce dernier proposera toujours de charger une partie enregistrée dans le fichier de sauvegarde. 2. A chaque étape, le programme demandera successivement aux joueurs blanc et noir en vérifiant si le joueur en cours peut jouer ou non (voir la fin de la Section 1.1) : (a) S ils veulent rajouter un jeton sur le plateau de jeu. Il devra demander de rentrer la position sur la grille de la case où ils désirent placer un de leurs jetons. (b) Si le joueur veut arrêter la partie. (c) Si le joueur veut sauvegarder la partie en cours et arrêter de jouer. 3. Dans le cas 2a : (a) Le programme devra détecter si le joueur peut mettre un jeton à cette position et, si le joueur ne peut pas mettre un jeton à cette position, demander à nouveau au joueur une nouvelle position jusqu à ce que cette dernière soit valide (voir Section 3). 2
(b) Après chaque choix d un des deux joueurs, le programme devra positionner le jeton sur la grille de jeu, retourner les jetons adverses enfermés et afficher la situation de la grille après changement à l écran dans la console. (c) Retour à l étape 2 tant que les joueurs peuvent encore jouer. 4. Dans le cas 2c, le programme devra sauvegarder la partie (voir Section 4). 3 Positions valides pour placer un jeton Un joueur ne peut pas placer un jeton n importe où. Son jeton doit être placé en bord de jeu. Le bord du jeu (voir FIG 4 (a)) est composé de toutes les cases (positions) vides du plateau dont au moins une des cases voisines (voir FIG 4 (b) pour la représentation des cases voisines d une case) est occupée par un jeton (noir ou blanc). (b) Bord (a) FIG. 4 a) Le bord du jeu (en gris). (b) Les 8 voisins d une case (la case remplie d un X). 4 Sauvegarde et lecture sur un fichier Comme dit précédemment, l utilisateur doit pouvoir sauvegarder sa partie sur un fichier et reprendre une partie en cours s il le désire. Cette partie sera stockée dans un fichier : save_game.txt. Le format des informations stockées dans ce fichier doit suivre le canevas suivant : x 5 2 v v v v x o v v v v v x x x v v v v v o x v v v Dans ce canevas d exemple, la première ligne indique la couleur du joueur qui doit jouer à cet instant de la partie (ici x est pour la couleur noire et o pour la couleur blanche). A la seconde ligne, on retrouve le score actuel des joueurs au moment de la sauvegarde : le nombre de jetons de couleur noire suivi du nombre de jetons de couleur blanche. Chacune des lignes qui suivent représente une ligne de la grille de jeu au moment de la sauvegarde. Trois caractères sont utilisés sur ces lignes : 3
v : une case vide x : un jeton noir o : un jeton blanc Il vous faut respecter ce canevas au moment de la sauvegarde d une partie! 4.1 Lecture et écriture dans un fichier Pour écrire ou lire le contenu d un fichier en c++, il vous faut utiliser un flux (du même genre de cin et cout que vous utilisez pour lire ou écrire des données à l écran 3 ). Il vous faudra utiliser la librairie fstream (à inclure dans votre fichier - voir exemple). Si vous voulez lire des informations sur un fichier nommé monfichier.txt, il vous faut créer une variable de flux input avec en paramètre le nom de votre fichier entre guillemets. Par exemple pour créer un flux fin qui permet de lire dans le fichier monfichier.txt : ifstream fin("monfichier.txt"). Pour écrire sur un fichier, on crée une variable flux de sortie : ofstream fou("monfichier.txt"). Voici un exemple d utilisation de ces variables de flux : #include<fstream> using namespace std; int main() { ifstream fin("fichier1.txt"); // ouverture du fichier à lire ofstream fout("fichier2.txt"); // ouverture du fichier à écrire char a; } fin >> a; // lecture d'un caractère sur le fichier de lecture fout << a <<endl; // écriture d'un caractère dans le fichier d'écriture 5 Projet On vous demande de réaliser les fonctions suivantes, où MAX est la taille du plateau de jeu (elle sera égale à 8) : La fonction int retournement(int i, int j, char couleur, char jeu[max][max]) qui va retourner, sur la plateau représenté par jeu, tous les jetons adversaires se trouvant enfermés entre le nouveau jeton à la position (i,j) du joueur et ses jetons déjà positionnés sur le plateau de jeu. Cette fonction renvoie ensuite le nombre de jetons retournés. La fonction bool peutjouer(int i, int j, char jeu[max][max]) qui renvoi true si le joueur peut mettre un jeton à la position (i,j) (ligne, colonne) de la grille de jeu, c est-à-dire que le joueur place son jeton sur le bord du jeu (voir Section 3). Elle renvoie false sinon. Une fonction bool jeupossible(char jeu[max][max], char couleur) qui renvoi true si le joueur ayant la couleur couleur possède au moins une position sur le tableau de jeu où il peut poser son jeton et engendré au moins un retournement. Dans le cas contraire, la fonction retourne false. 3 Ici nous allons lire et écrire des données dans un fichier! 4
La fonction void initialisation(char jeu[max][max], bool save_game, int &score_blanc, int &score_noir, char &tour) dont le comportement dépend de la valeur du paramètre save_game. Si celle-ci vaut false, la fonction doit initialiser la matrice jeu et les paramètres score_blanc, score_noir et tour aux valeurs correspondant au début d une partie (voir Section 4). Si le paramètre save_game vaut true, la fonction doit initialiser la matrice jeu et les paramètres score_blanc, score_noir et tour aux valeurs lues depuis le fichier save_game.txt (on charge donc une partie précédemment sauvegardée). La fonction void sauvegardepartie(char jeu[max][max],int score_blanc, int score_noir, char tour) qui sauvegarde la partie dans le fichier save_game.txt en respectant le canevas de la Section 4. La fonction void affichage(int jeu[max][max], int score_noir, int score_blanc) qui affiche l état du plateau de jeu et le score des joueurs. Exemple : Noir : 5 Blanc : 2 0 1 2 3 4 5 6 7 0 1 2 x o 3 x x x 4 o x 5 6 7 Vous devrez utiliser ces fonctions à partir de votre main() afin de gérer une partie au lancement du programme. 5
Consignes pour la remise du projet À respecter scrupuleusement! 1. Votre projet doit comporter votre nom et votre numéro de groupe. 2. Votre projet doit être dactylographié. Les projets écrits à la main ne seront pas corrigés (0/10). 3. Votre code doit être commenté. 4. Vous devez respecter les modalités de remise suivante : Date de remise : le 2 novembre Lieu : au Secrétariat «étudiants» du Département d Informatique, local 2N8.104 Heure : Avant 16h Le secrétariat ferme à 16h. Après 16h, les projets sont considérés comme en retard, et vous perdez 1 point sur votre note finale (un point supplémentaire par jour de retard). Les projets en retard doivent être déposés dans la caisse prévue à cet effet près du secrétariat. 6