Academia.eduAcademia.edu

Sylvain Archenault Yves Houpert INTRODUCTION

III. UTILISATION DU POLYMORPHISME : Les interfaces dans le jeu de dames

Sylvain Archenault Yves Houpert Projet Informatique : Langage Java : Jeu De Dames en Java Projet GM3 Mai 2005 Chapitre 1 INTRODUCTION Le projet qui nous a été confié est de réaliser un jeu de dames en Java. Le but de ce projet est d’utiliser habilement les concepts de la programmation objet, c’est à dire l’héritage entre les classes, la gestion des interfaces ou des classes abstraites , etc...Nous avons déjà réalisé un jeu de dames en langage C au semestre dernier et il a été donc très intéressant de pouvoir remarquer les différences de programmation entre une programmation séquentielle et une programmation objet. Pour bien répondre au problème, nous allons d’abord présenter les différentes classes qui été nécessaires à la réalisation du jeu de dames . Dans une autre partie, nous parlerons plus précisément du polymorphisme propre aux langages objets. Nous le verrons ici plus particulièrement en action avec le Java. Enfin,nous exposerons les différents problèmes que nous avons rencontré lors de la programmation et comment nous y avons remédié. -1- Chapitre 2 LES CLASSES Les classes sont la base de la programmation objet . Nous avons eu besoin d’utiliser plusieurs classes dans ce projet avec par exemple des relations d’héritage entre elles ( nous verrons ceci plus précisément dans la partie 3 ). Nous allons tout d’abord exposer les différentes classes créées pour la conception du jeu. Ensuite, nous illustrerons nos explications par un graphisme réalisé à l’aide du logiciel Umbrello pour bien comprendre la composition des classes ainsi que leurs différentes relations. 2.1 Liste de toutes les classes créées – l a classe Arbitre : La classe Arbitre est la classe qui contrôle le déroulement du jeu. C’est l’Arbitre qui vérifie que la partie n’est pas terminée, si un coup est valable. Il détermine aussi les coups obligatoires, etc.. – la classe Plateau : La classe Plateau décrit le plateau du jeu de dames. – la classe Case : La classe Case est une classe abstraite décrivant une case du plateau du jeu de dames. Cette classe hérite de la classe JComponent puisqu’on souhaite l’ajouter à un JPanel. On va donc redéfinir les méthodes d’affichages. On implémentera également l’interface MouseListener car on veut gérer les cliques et les déplacements de la souris. – la classe CaseBlanche : La classe CaseBlanche décrit une case blanche du jeu de dames. Cette case est bien sûr inactive car les pions ne se déplacent que sur les cases noires. – la classe CaseNoire : La classe CaseNoire décrit une case noire du jeu. Contrairement aux cases blanches, elles sont actives. – la classe Rafle : La classe Rafle est une des classes importantes du jeu. En effet, elle permet de calculer la rafle maximale et de la signaler au joueur. Expliquons ceci plus en détails : La classe Rafle symbolise un coup d’une rafle effectuée au jeu de dames. Une rafle au jeu de dames est donc symbolisée par une liste de Rafle. Chaque élément (objet) contient la case du début du coup, la case prise ( c’est à dire la case du dernier pion pris ) du coup précédent et un vecteur contenant la liste des cases suivantes possibles. En effet, il se peut que pour une case donnée, on ait la possibilité d’obtenir plusieurs autres coups possibles. – La classe HistoriqueCoup : Cette classe sert bien sûr à gérer l’historique des coups. – la classe Piece : La classe Piece est une autre classe abstraite. Elle symbolise une pièce du jeu. En l’occurrence ici, il s’agira soit d’un pion, soit d’une dame. -2- II. LES CLASSES : Les classes représentées par un graphisme UML – la classe Pion : La classe Pion symbolise un pion du jeu de dames. – la classe Dames : La classe Dame représente une dame. Elle est un peu plus complexe que la classe pion car le déplacement d’une dame est plus difficile à étudier que celui d’un pion. – la classe Joueur : A nouveau une classe abstraite. Elle décrit un joueur du jeu. Ce joueur peut aussi bien être un humain que l’ordinateur. – la classe Humain : La classe Humain décrit un joueur du type Humain. – la classe Ordinateur : La classe Ordinateur représente bien sûr un joueur contrôlé par l’ordinateur pendant la partie. – la classe JeuDeDamesWindow : Cette classe hérite de la classe JComponent comme la classe Case vu précédemment. Elle gère le fenêtre du jeu de dames et l’affichage des composants de la fenêtre. – la classe NouvellePartieWindow : Comme son nom l’indique, la classe NouvellePartie décrit la fenêtre permettant de commencer une nouvelle partie. – la classe APropos : C’est la classe qui décrit la fenêtre APropos. Cette fenêtre donne des renseignements sur le jeu ; ses concepteurs par exemple ou d’autres indications. Nous allons maintenant illustré toutes ces informations par un diagramme de classes qui rendra les explications de ce paragraphe plus claire. 2.2 Les classes représentées par un graphisme UML Cette idée d’utiliser le logiciel Umbrello nous a permis d’obtenir une programmation très structurée. En effet, nous avons eu la possibilité d’illustrer toutes les classes avec leurs attributs et leurs méthodes. Nous avons pu facilement remarquer les différents liens que nous devions instaurer entre les classes . 2.2.1 Le diagramme des classes Nous avons également réaliser des scénarios représentant les différentes possibilités de jeu que nous offraient par exemple la gestion d’une rafle. Cette pratique nous a permis de trouver les différentes méthodes de chaque classe d’une manière optimale et très structurée. Pour plus d’informations sur les classes, ainsi que leurs méthodes et attributs, nous avons généré une documentation à l’aide de javadoc ; elle est disponible sur : http ://gm.insa-rouen.fr/~archenas/projets/JeuDeDames/Doc/. -3- II. LES CLASSES : Les classes représentées par un graphisme UML -4- II. LES CLASSES : Les classes représentées par un graphisme UML -5- II. LES CLASSES : Les classes représentées par un graphisme UML -6- Chapitre 3 UTILISATION DU POLYMORPHISME Le projet a été réalisé de manière à ce que les atouts de la programmation objet soient utilisés habilement et mis en valeurs. Nous allons voir dans cette partie comment nous nous en sommes servis et quels sont leurs caractéristiques au niveau du jeu de dames. 3.1 L’héritage dans le jeu de dames On sait que l’héritage permet la construction et l’extension par affinage des applications. Dans ce projet, nous avons trois grands exemples d’héritage : 3.1.1 Les classes CaseNoire et CaseBlanche qui héritent de la classe Case Il nous est apparu évident d’utiliser l’héritage pour gérer les cases du plateau. En effet, les cases noires et les cases blanches se comportent différemment, tout en ayant des caractéristiques communes. Le plateau du jeu de dames possèdent à la fois des cases blanches et noires. Nous avons donc décidé de créer une classe abstraite Case dont dérive les classes CaseNoire et CaseBlanche. De ce fait, Plateau est simplement un tableau de Case. Le polymorphisme nous permet donc de spécifier un comportement différent pour les cases blanches et les cases noires du manière très simple. Illustrons cela. A l’initialisation du plateau, nous attribuons à chaque élément du tableau une CaseBlanche ou une CaseNoire suivant sa position. C’est ici le seul moment dans le programme où nous allons différencier les cases par leur positions. En effet, dans la suite de l’exécution, c’est le polymorphisme qui se chargera de différencier les cases blanches des cases noires. Prenons l’exemple de l’affichage des cases. Nous avons défini dans la classe Case la méthode abstraite paintComponent() qui est appelée par Java lorsque la case doit être affichée ou bien repeinte. Dans les classes dérivées CaseNoire et CaseBlanche nous avons donc redéfini cette méthode pour que l’affichage des cases soit différent. Dans paintComponent() de la classe CaseNoire, nous dessinons un carré noir, alors que dans CaseBlanche nous dessinons un carré blanc. Nous avons donc réussi à afficher le damier d’un manière très facile grâce au polymorphisme. Il est important de remarquer que la classe Case peut être réutilisée dans la réalisation d’un autre jeu puisque celle-ci reste très générale et offre les méthodes de bases pour le gestion des cases d’un jeu. Nous pourrions, par exemple la réutiliser dans un jeu d’échec ou d’othello. -7- III. UTILISATION DU POLYMORPHISME : L’héritage dans le jeu de dames 3.1.2 Les classes Humain et Ordinateur qui héritent de la classe Joueur Nous avons vu dans le précédent chapitre que c’est une instance de la classe arbitre qui contrôle le jeu et l’interaction entre les joueurs. Nous avons décidé là aussi, d’utiliser le polymorphisme pour la modélisation des joueurs. Nous avons donc créé une classe abstraite Joueur qui décrit d’une manière générale un joueur du jeu de dames. Nous avons ensuite créé deux classes dérivées Ordinateur et Humain, celles-ci plus spécifiques. L’application du polymorphisme dans ce cas se traduit par la méthode jouer() qui permet au Joueur de jouer. En effet, s’il s’agit d’un humain ou d’un joueur contrôlé par l’ordinateur, la méthode doit être différente. Nous avons donc créé un méthode abstraite jouer() dans la classe Joueur, que nous avons défini différemment dans les classes Humain et Ordinateur. De cette façon, l’arbitre ne se préoccupe pas si les joueurs sont des humains ou des joueurs contrôlés par l’ordinateur. D’un autre côté, la méthode gérant la création des pièces est commune aux deux types de joueurs. Nous avons donc créé une méthode debut() qui créer les pièces du joueur. Ceci apporte donc une grande facilité de programmation, ainsi qu’une meilleure clarté. De la même manière que pour la classe Case, nous avons essayé de rendre la classe Joueur la plus portable possible, c’est à dire qu’on ait la possibilité de la réutiliser dans d’autres programmes. 3.1.3 Les classes Pions et Dames qui héritent toutes les deux de la classe Piece Ce choix semble donc également très pertinent pour la gestion des pièces. En effet, nous pouvons utiliser les mêmes méthodes pour par exemple retourner la couleur de la pièce ou sa position. Ces méthodes sont tout à fait indépendantes des pions ou des dames. Nous n’avons pas besoin d’utiliser de boucle if comme en programmation séquentielle car nous pouvons généraliser les méthodes en utilisant la classe abstraite Piece. Là où la programmation objet prend tout son sens, est lorsque nous souhaitons calculer les coups obligatoires, ou encore vérifier qu’un coup est valide. En effet, en programmation séquentielle, nous devions différencier les cas des dames ou des pions, ici nous avons simplement à redéfinir la méthode abstraite de la classe Piece dans les sous-classes Pions et Dames pour avoir un traitement particulier. Illustrons ceci par deux exemples pertinents : – Vérification de la validité d’un coup isCoupValide() Lorsque le joueur veut effectuer un coup, il clique sur la case de la pièce qu’il souhaite déplacer, puis clique sur la case d’arrivée du coup. Afin de vérifier si le coup est possible, nous avons implémenté la méthode isCoupValide(). C’est une méthode abstraite dans la classe Piece, que nous avons définie dans les classes Pions et Dames. Il est évident que les règles de déplacements diffèrent pour les pions et les dames. Nous l’avons donc programmée d’une manière différente dans chaque classe. Mais, lorsque nous vérifions si un coup est valide nous appelons la méthode isCoupValide() de la classe Piece, c’est ensuite Java qui choisit d’appeler la méthode de la classe Pion ou de la classe Dame suivant le cas. Ceci nous permet donc de gérer les pions et les dames du jeu de la même manière. – Calcul du coup obligatoire : Lors que l’on souhaite calculer le coup obligatoire pour un joueur, nous parcourons la liste des pièces qu’il possède. Il est important de noter que la liste des pièces du joueur est stockée dans un Vecteur. Pour chaque pièce, nous appelons la méthode coupObligatoire(), qui renvoie le coup obligatoire pour la pièce en question si il existe. Il est bien évident que le coup obligatoire est différent pour les pions et les dames. Mais grâce au polymorphisme, nous ne faisons aucune différence. Le polymorphisme apporte donc ici une très grande simplicité de programmation. Comme pour les deux classes abstraites précédentes, la classe Piece est réutilisable pour la modélisation d’autres pièces. Nous avons présenté ici que quelques exemples d’héritage et de polymorphisme, il y a bien évidemment d’autres cas où le polymorphisme intervient. -8- III. UTILISATION DU POLYMORPHISME : Les interfaces dans le jeu de dames 3.2 Les interfaces dans le jeu de dames Dans le projet nous n’avons pas programmé d’interfaces. Mais nous avons tout de même utilisé des interfaces fournies par la langage Java, il s’agit principalement de l’interface MouseListener. Cette interface permet de gérer les événements de la souris. Nous avons implémenté cette interface dans la classe CaseNoire. En effet nous voulons intercepter les clics de la souris sur la case, en effet c’est par ce biais que le joueur peut sélectionner une pièce. Ensuite nous voulons également connaître quand la souris entre ou sort d’une case pour pouvoir mettre en sur-brillance cette case. En effet, un fois que le joueur a sélectionné une case, c’est-à-dire une pièce, dès que la souris entre dans une autre case, alors on la met en sur-brillance si le coup est réalisable. -9- Chapitre 4 LES DIFFICULTÉS RENCONTRES LORS DU PROJET 4.1 La rafle maximale Une des difficultés majeures du projet a été de calculer les coups obligatoires. Rappelons brièvement les règles du jeu de dames. La prise prioritaire est celle où il y a le plus de pions à prendre (la dame compte pour un pion), Le joueur doit obligatoire effectuer la prise prioritaire. Il se peut qu’il existe plusieurs prises prioritaires possibles. Pour calculer les coups obligatoires, nous calculons pour chaque pièce le coup prioritaire, et ne retenons à la fin que les coups qui permettent de prendre le maximum de pions. Pour modéliser une rafle, nous avons choisis d’écrire une classe Rafle ayant les attributs suivant : – (CaseNoire) caseDebut : C’est la case du début de la rafle. – (CaseNoire) casePrise : C’est la case prise au coup précédent. – (Vector) casesSuivantes : C’est la liste des Rafles pouvant ensuite être effectuées. La classe possède d’autre attributs, mais nous nous intéressons ici qu’au principaux. Une rafle est alors modélisée par une suite de Rafle. Illustrons ces propos par un exemple simple. Si nous voulons symboliser le coup A,1 - C,3 avec un pion pris en B,2, nous allons donc avoir un premier objet r1 de type Rafle qui aura comme attribut (caseDebut : A1, CasePrise : null, casesSuivantes : r2 ). L’objet r2 est également du type Rafle et a pour attribut (caseDebut : C3, casePrise : B2, casesSuivantes : null). 4.2 4.2.1 Les problèmes liés à la partie graphique du projet Déplacement des pièces Au début du projet, nous souhaitions déplacer les pièces du jeu par un principe de glisserdéposer. Mais nous n’y sommes pas parvenus. En effet la méthode MouseDragged() de l’interface MouseMotionListener, ne nous paraissait pas bien adaptée à notre problème. Il aurait fallu redéfinir le glisser-déposer pour la pièce. Nous n’avons pas eu le temps de nous pencher sur ce problème. Ensuite nous avons eu l’idée de déplacer la pièce de manière à ce qu’elle suive la souris. C’està-dire que lorsque le joueur clique sur une pièce, la pièce suit le mouvement de la souris (mouseMove()). Puis lorsque l’utilisateur clique à nouveau, nous gérons le coup effectué. Mais ceci pose problème, en effet, comme la pièce se trouve constamment sous la souris, c’est la pièce qui reçoit l’événement mouseClicked(). Or, dans le programme, c’est la case qui est censée gérer les cliques de souris. Une astuce possible pour résoudre le problème serait de changer le curseur de la souris, c’est à dire d’attribuer à la souris la forme de la pièce. - 10 - IV. LES DIFFICULTÉS RENCONTRES LORS DU PROJET : Les problèmes liés à la partie graphique du projet 4.2.2 Redimensionnement de la fenêtre La fenêtre du Jeu de Dames ne réagit pas bien au redimensionnement. En effet, le plateau reste toujours à la même position alors qu’il serait mieux qu’il se déplace au centre de la fenêtre. Ensuite la taille des cases du plateau est toujours la même quelque soit la résolution de l’écran, il serait plus agréable que celle-ci s’adapte à la résolution de l’écran. - 11 - Chapitre 5 CONCLUSION Ce jeu de dame en langage Java fut très intéressant à concevoir et à programmer. Ce projet nous a permis de bien comprendre les qualités de la programmation objet. Nous avons essayé d’utiliser au mieux ses caractéristiques tels que l’héritage ou les classes abstraites. Ces propriétés de la programmation sont très pratiques et permettent une bien meilleure conception et réalisation du projet. Nous avons pu remarqué ces qualités car nous avions déjà réalisé un jeu de dames en C. La programmation du jeu de dames en Java, nous a donc permis de nous rendre compte de la différence entre ces deux modes de programmation. Il nous est apparu bien plus facile de concevoir le programme en Java qu’en C. De plus, nous sommes rendus compte que les classes abstraites pourront être facilement réutilisable dans d’autres projets, chose qui serait beaucoup plus difficile avec les fonctions écrites en C. Au début du projet, nous avons trouvé les différentes classes et méthodes à créer grâce à l’utilisation de scénarios et de diagrammes de classes. Cette démarche permet d’avoir une réflexion structurée tout au long de la programmation. Au niveau des améliorations possibles du projet, il serait très intéressant de pouvoir mettre le jeu en réseau. Il serait également plus agréable que l’interface graphique soit plus chaleureuse. Pour le confort du jeu, il serait intéressant d’améliorer le jeu de l’ordinateur.