Projet PASCAL Bataille navale
Transcription
Projet PASCAL Bataille navale
Projet PASCAL Bataille navale Christian BELIN Guillaume ROUILLARD 8 février 2008 Table des matières 1 Architecture des modules 2 Description des modules 2.1 STD . . . . . . . . . . . . . . . . 2.1.1 Types . . . . . . . . . . 2.1.2 Procédures et fonctions 2.2 I/O . . . . . . . . . . . . . . . . 2.3 Place . . . . . . . . . . . . . . 2.4 Joueur . . . . . . . . . . . . . . 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Description du programme principal 4 Choix algorithmiques 4.1 Placement des bateaux . . . . . 4.1.1 Respect des règles . . . 4.1.2 Modification de la grille 4.2 Gestion des dégâts . . . . . . . 4.3 Tour de l’ordinateur . . . . . . 4.3.1 Mode ALEATOIRE . . . . 4.3.2 Mode DIRECTION . . . . 4.3.3 Mode VERROUILLAGE . . 4.4 Alternance des tours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 2 3 3 4 4 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 5 5 5 6 6 6 6 6 5 Mise au point du programme 6 6 Problèmes actuels 7 7 Améliorations - Évolution 7.1 Utilisation des constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.1 Échelle de jeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.2 Modes de jeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7 7 7 1 Introduction Le but de ce projet en PASCAL est de réaliser un jeu de bataille navale opposant un joueur humain contre l’ordinateur. Diverses conditions ont été imposées quant aux règles du jeu, à l’interface graphique et la stratégie de l’ordinateur. Cependant, tout le reste était laissé à l’appréciation du binôme. Nous allons donc voir comment les modules s’articulent autour du programme principal, une présentation succincte de chacun desdits modules, puis une explication des choix algorithmiques réalisés, une réflexion sur la mise au point du programme, la liste des problèmes actuels non résolus, suivie d’une ouverture présentant les améliorations qu’on pourrait apporter au programme. On trouvera en annexe les sources du programme. 1 Architecture des modules STD I/O k 6M Joueur Place Y K Bataille – Bataille est le programme principal, il utilise donc tous les modules. – STD est le module standard qui contient toutes les fonctions de base qui seront utilisées par tous les autres modules. – I/O est le module d’affichage qui s’occupe des grilles et du menu principal. – Place est le module qui permet à l’ordinateur et au joueur humain de placer leurs bateaux sur la grille. – Joueur est le module qui permet de réaliser le tir de l’ordinateur ou de l’humain. 2 2.1 2.1.1 Description des modules STD Types Tous les types et constantes utilisés dans le projet ont été définis dans ce module afin de permettre un accès rapide et universel à ceux-ci. Les types remarquables sont : – T Coordonnees : Ceci est un outil permettant de manipuler à la fois ligne et colonne sous la forme entrée par l’utilisateur pendant la partie (ex : ’A5’). 2 – T Direction : Ce type a été défini pour le placement des bateaux (pour les deux joueurs) et a été réutilisé lors du bombardement par l’ordinateur. – T Statut : Définit si un joueur est humain ou contrôlé par l’ordinateur. Nous reviendrons sur ce point dans la partie concernant les améliorations apportées et/ou à apporter au programme. – T Strategie : La façon (imposée) dont se comporte l’ordinateur lors de son tour nous a incité à utiliser une ”mémoire”, c’est pourquoi la stratégie de l’ordinateur utilisera ce type lors du jeu. – T Bateau : C’est un enregistrement permettant de repérer le bateau sur la grille, de savoir son nom, et son état. – T Flotte : L’ensemble des bateaux à placer sur la grille a été regroupé dans un tableau initialisé dans ce module. – T Case : Une case de la grille peut avoir cinq états différents, il a été décidé de les trier ainsi au sein de ce type énuméré pour tirer parti de cette structure (comparaisons par inégalités, etc.). – T Grille : La grille a été créée avec une bordure de cases à l’état VIDE sur le pourtour comme vu dans le TD 2 du module ”Algorithmique et Programmation 2” (le jeu du ”Puissance 4”). De cette manière, on résout le problème des dépassements hors zone de jeu. – T Joueur : Une manière simple et efficace de regrouper toutes les informations concernant un joueur était d’utiliser un enregistrement. On a ainsi accès à toutes ses données de jeu (statut, grille de jeu, etc.) grâce à une seule variable. 2.1.2 Procédures et fonctions – function est coord : Pour pouvoir utiliser la fonction atoi (voir ci-dessous, cf. TP 7 - Module ”Algorithmique et Programmation 1”) sans tous les contrôles programmés lors du TP, il nous fallait réaliser nous-même ces contrôles dans le seul cadre d’une saisie utilisateur, puisque les données manipulées par les programmes sont forcément valides. – function atoi : C’est la fonction du TP 7 du premier module d’algorithmique, simplifiée pour n’en garder que l’algorithme de conversion, comme expliqué ci-dessus. – procedure ch2coord et function coord2ch : Au vu du type utilisé pour les coordonnées, il nous fallait des fonctions de conversion pour transformer cette chaı̂ne de caractères en un couple d’entiers (une ligne et une colonne), et vice-versa. – function nom bateau : Le type T Bateau n’avait pas besoin de comporter le nom du bateau car il était redondant avec la longueur de celui-ci. Cette fonction permet donc d’associer à une longueur, un nom de bateau. – procedure init grille : La grille est initialisée lors du début de partie, et toutes ses cases reçoivent la valeur VIDE. On peut ensuite placer la flotte. – function est position valable : Cette fonction permet de réaliser les saisies contrôlées de coordonnées afin d’obtenir une position valide sur la grille. – procedure cases bateau : On a besoin de connaı̂tre l’ensemble des cases occupées par un bateau lorsqu’on a une case et qu’on cherche si elle appartient à un bateau ou lorsqu’on a un bateau et qu’on cherche toutes ses cases (pour les mettre à l’état COULE par exemple). – procedure init flotte : Le nombre et le type de bateaux sont définis dans les règles du jeu. Cette procédure permet d’initialiser une variable de type T Flotte à la flotte de départ du joueur. 2.2 I/O - Procédures et fonctions – procedure aff col et procedure aff lig : Ces deux procédures sont uniquement utilisées par la procédure aff grille . – procedure aff grille : Ceci affiche les deux grilles l’une à côté de l’autre en masquant les bateaux non coulés ou non touchés de l’adversaire. 3 – procedure aff menu : Ce sous-programme gère l’affichage du menu et permet à l’utilisateur de recommencer une nouvelle partie après en avoir fini une, comme préconisé dans le sujet. 2.3 Place - Procédures et fonctions – function est placable : Le placement du bateau s’effectue en deux étapes, la première consistant à vérifier s’il ne sort pas de la zone de jeu. – function plact valide : Avant de placer le bateau, il faut encore contrôler si le bateau respecte les règles du jeu vis-à-vis des autres bateaux déjà placés. – procedure placer bateau : Les deux conditions précédentes étant respectées, il faut modifier la grille pour prendre en compte le placement. – procedure placer humain : Grâce à cette procédure, le joueur humain peut choisir l’ordre dans lequel il veut placer ses bateaux et saisir (de manière robuste !) leur position. Le choix du type de saisie (origine et direction) est lié à la construction du type T Bateau et au fait que cette manière d’opérer nous a semblé simple pour l’utilisateur, ainsi que pour le programmeur. – procedure placer ia : Le squelette de la procédure est largement inspiré de placer humain, à ceci près que les saisies ont été remplacées par des tirages aléatoires successifs. Comme il a été conseillé dans le sujet, les bateaux de grande taille sont placés en premier. 2.4 Joueur - Procédures et fonctions – function appartient bateau : Au moment où l’on a touché un bateau, on cherche à savoir duquel il s’agit. – procedure maj grille : Après chaque tir, on change simplement le statut de la case concernée, en détectant également les bateaux coulés. – function est flotte detruite : Pour détecter la fin du jeu, il fallait une fonction, à placer dans la condition de la boucle, qui indique quand un joueur a perdu. – procedure bombarder humain : C’est une des deux procédures principales du jeu, où l’humain va essayer de localiser et détruire l’ensemble de la flotte adverse. La saisie est, encore une fois, robuste. – procedure bombarder ordi : Il s’agit sans nul doute du problème le plus épineux auquel nous avons fait face dans ce projet. La stratégie imposée dans le sujet a rapidement conduit à l’utilisation d’une forme de mémoire entre chaque tour. Il fallait évidemment éviter de conserver trop d’informations, mais en même temps être capable de suivre la conduite indiquée. En utilisant simplement une variable de type T Strategie et une variable de type T Coordonnees représentant respectivement le mode de tir en cours et la première case touchée du bateau-cible actuel, nous sommes parvenus au comportement attendu. 3 Description du programme principal - Bataille Le programme principal s’articule en deux parties : une partie d’initialisation qui permet d’affecter toutes les variables concernant les joueurs, et une partie concernant le jeu lui même. La partie initialisation couvre les affectations de deux variables de type T Joueur (statut : IA ou HUMAIN, nom, initialisation de la grille, initialisation et placement de la flotte). La stratégie de l’ordinateur est aussi initialisée ici (à ALEATOIRE). 4 La partie du jeu lui-même est constituée d’une boucle se prolongeant jusqu’à ce qu’un des deux joueurs n’aie plus de bateaux en jeu. L’alternance des joueurs est gérées avec un booléen changeant de valeur à chaque tour, booléen qui indexe également le tableau des joueurs. Le joueur humain peut abandonner la partie à tout moment en entrant simplement ’00’ à la place des coordonnées d’une attaque. 4 4.1 4.1.1 Choix algorithmiques Placement des bateaux Respect des règles La principale difficulté de l’algorithme réside dans les règles de placement d’un bateau par rapport aux autres : ”deux bateaux ne peuvent pas se toucher par les côtés mais ils peuvent se toucher par les coins”. La zone de détection n’est pas alors un carré ou un rectangle, mais une forme englobant le bateau : Le rectangle à bords pleins représente le bateau, le rectangle à longs pointillés représente la zone qui est balayée et les deux cases d’extrémités sont examinées séparément. La difficulté a été de trouver une manière de balayer les cases de manière efficace, en factorisant le plus possible le code. La zone rectangulaire reçoit donc des limites à gauche, à droite, en haut et en bas, en fonction de la longueur du bateau, de ses coordonnées d’origine et de sa direction. 4.1.2 Modification de la grille Toujours dans un souci de factorisation maximale du code pour un rendement maximal, le placement du bateau sur la grille est une simple boucle Pour. Comme le bateau peut avoir quatre directions différentes, un Selon affecte deux variables d’incrémentation des lignes et des colonnes. 4.2 Gestion des dégâts Lors du tir sur un bateau, il est important de savoir quel bateau a été touché, s’il a été coulé et où en est la flotte dans sa totalité. La grille ne comporte aucune information sur les bateaux, et le type T Bateau ne contient pas toutes les cases sur lesquelles le bateau se trouve. Il est donc nécessaire 5 d’utiliser une fonction permettant de retrouver à quel bateau appartient telle case de la grille. À l’aide des données stockées dans la variable affectée au bateau, on peut facilement obtenir la liste des cases, et ensuite rechercher dans celle-ci pour chacun des bateaux de la flotte. Un compteur du nombre de cases intactes par bateau permet de passer leur statut à COULE lors du dernier tir. 4.3 4.3.1 Tour de l’ordinateur Mode ALEATOIRE En mode aléatoire, l’ordinateur recherche simplement une case sur laquelle il n’a pas déjà tiré. S’il se trouve qu’il atteint une cible, il enregistre les coordonnées du tir et passe en mode DIRECTION. 4.3.2 Mode DIRECTION Rechercher toujours de la même manière dans quel sens est orienté le bateau pourrait conduire à une exploitation de cette faiblesse de la part du joueur. L’ordinateur va donc tirer aléatoirement sur les cases adjacentes et non déjà testées. Une fois qu’il a trouvé une autre case, il passe en mode VERROUILLAGE. Si le bateau ne fait que deux cases, on repasse directement en mode ALEATOIRE, puisque le bateau est maintenant coulé. 4.3.3 Mode VERROUILLAGE Une fois la direction connue, l’ordinateur continue à la suivre jusqu’à arriver à un bord ou tirer sur une case EAU. Si le bateau n’est pas encore coulé, il lui faut donc faire demi-tour, remonter les cases touchées précédemment, et ce, jusqu’à la première case non encore découverte. Une fois le bateau envoyé par le fond, l’ordinateur repasse en stratégie ALEATOIRE. 4.4 Alternance des tours Comme vu précédemment, les deux profils des joueurs sont stockés dans un tableau indexé par un booléen. Lorsque ce booléen change d’état (à la fin de chaque tour), on change aussi de joueur, donc de grille, de flotte, de stratégie, etc. ! 5 Mise au point du programme Après une lecture complète et approfondie du sujet, nous avons chercher à cerner plus précisément le problème, localiser les points qui allaient nous poser problème, tout en gardant une vision d’ensemble. Nous avons utilisé pour ceci la méthode des raffinages, sur quelques niveaux pour dégrossir. De ce point nous avons pu commencer à définir de manière quasi-définitive les types que nous allions utiliser (ceux-ci n’ont en effet connu que très peu de changement par la suite). Une fois la structure des données déterminée, nous avons défini de manière plus précise le fonctionnement des outils qui allaient nous permettre de manipuler celles-ci. Les sous-programmes ont été séparés en un certain nombre de modules, par catégorie de fonctionnalité (affichage, placement, etc.). Nous ferons remarquer qu’à l’origine, il y avait deux modules Human et Machine qui ont ensuite fusionné pour donner le module Joueur concernant la phase de jeu proprement dite. Le travail avait été réparti par module, mais en fin de compte, nous avons tous les deux participé au développement de chaque module, chose importante pour embrasser le projet dans sa globalité. Les programmes de tests des modules ont été réalisés au fur et à mesure du développement de ceux-ci afin d’assurer une continuité du suivi et d’éviter des pertes de temps trop importantes. 6 6 Problèmes actuels L’ordinateur n’arrive pas à placer ses bateaux sur la première ligne de la grille (numérotée 0), malgré une procédure aléatoire de placement. De même, l’ordinateur n’arrive pas non plus à tirer sur cette même première ligne, rendant les cases de bateaux situées sur cette ligne invulnérables. Un problème sans doute lié avec les deux précédents est le fait que l’ordinateur ne change pas de stratégie lorsqu’il touche une case d’un bateau située sur la deuxième ligne (numérotée 1). Lorsque l’humain coule un bateau, le changement d’état de TOUCHE vers COULE ne se fait pas. Ceci semble lié à la variable de type T Flotte et à son initialisation. Nous avons passé de nombreuses heures sur ces problèmes sans pour autant arriver à les résoudre. 7 7.1 7.1.1 Améliorations - Évolution Utilisation des constantes Échelle de jeu La modification des constantes MAX LIGNES et MAX COLONNES lors de la compilation permet de changer la taille de la grille. Il est à observer que ces modifications entraı̂nent que le format du type T Coordonnees doit voir sa longueur actualisée pour suivre les nouveaux standards de taille (si on a plus de dix lignes, il faut pouvoir saisir plus de 2 caractères pour faire référence à une case). Le nombre de colonnes ne pourra néanmoins dépasser vingt-six, à moins de définir de nouveaux symboles pour accéder à ces colonnes, rendant alors l’opération sensiblement plus compliquée. La flotte utilisée par les deux joueurs peut être facilement éditée dans le module STD pour changer le nombre de bateaux en vue de l’adaptation à la nouvelle taille de la grille, la taille desdits bateaux ainsi que leur nom. 7.1.2 Modes de jeu À l’aide d’un certain nombre de transformations, on pourrait modifier les règles de placement des bateaux les uns par rapport aux autres, pour les espacer plus sur une grille plus grande, par exemple. Les règles d’alternance des tours variant d’un individu à l’autre, il ne paraı̂t pas incohérent d’implanter ces différentes versions et de proposer à l’utilisateur d’en choisir une au début de la partie (tirer trois fois à l’affilée, rejouer après avoir touché, etc.). Dans une optique de renouveau du genre, on pourrait envisager l’inclusion de nouveaux types d’armes affectant une plus grande zone de jeu en échange d’un temps de rechargement plus important ou la nécessité de la présence d’un vaisseau capital. Transformer la bataille navale en deux dimensions en une bataille spatiale à trois dimensions n’est pas non plus une tâche impossible. En effet, la plupart des algorithmes qui ont été implémentés peuvent sans trop de peine s’adapter à trois dimensions. Le seul obstacle à cette réalisation est actuellement le format de représentation graphique. 7 Conclusion Ce projet PASCAL conclut donc le deuxième module ”Algorithmique et Programmation”. Il nous a permis de peaufiner nos connaissances en programmation pour ceux qui n’étaient pas trop familiers avec ce domaine, et d’acquérir de l’expérience supplémentaire ainsi qu’une certaine familiarité avec ce langage pour les autres. Le sujet du projet restait accessible à tous tout en recelant suffisamment de difficultés pour poser des problèmes intéressants. La réutilisation d’une fonction du TP nous montre l’importance d’une implémentation soigneuse et portable, permettant une exportation rapide et simple dans des problèmes de nature totalement différente. Nous avons aussi réutilisé plusieurs autres astuces vues en TP et en TD afin de gagner du temps et de simplifier les algorithmes. Ce projet a aussi été une occasion particulière d’effectuer un travail en équipe avec quelqu’un que l’on connaı̂t et dont les connaissances différentes dans le domaine permettent d’apporter un autre éclairage. En outre, ce sujet a mis en évidence l’importance de la programmation par contrat lors d’une conduite de projet. Les conditions posées pour la réalisation du projet donnent un aperçu des conditions de travail en entreprise et apprend à gérer avec précaution les ressources, le temps, et tout ce qui en fait un projet semblable à ceux sur lesquels nous seront amenés à travailler, tout en restant à notre échelle de temps et de connaissances. Nous tenons à vous remercier d’avoir lu ce rapport dans son intégralité. Christian BELIN <[email protected]> Guillaume ROUILLARD <[email protected]> 8