DS sokoban_v4
Transcription
DS sokoban_v4
DUT 2A 2012-2013 26/10/2012 DS cpt JAVA Durée: 2 heures. Documents (notes et polycopiés) autorisés La rigueur et la propreté seront prises en compte dans l'évaluation. Les questions posées sont en grande partie indépendantes les unes des autres. Vous penserez à garder les mêmes noms pour les méthodes et les attributs. Pour plus de facilité dans l'écriture, les attributs sont supposés public. Vous pouvez commenter votre code dès que vous jugerez utiles certaines explications. Dans ce DS, on souhaite modéliser un jeu de type Sokoban. Il s'agit d'un jeu vidéo à base de Puzzle inventé au Japon. Dans ce jeu, le joueur contrôle un personnage qui se déplace dans un entrepôt. Cet entrepôt contient plusieurs caisses et le personnage doit les amener à leur destination en les poussant au cours de son déplacement. La difficulté réside dans le fait que le personnage ne peut pas tirer les caisses et peut donc se retrouver bloqué quand les caisses se trouvent devant un obstacle (que ce soit un mur ou une autre caisse). Personnage Caisses Destination Ce sujet vous propose • dans un premier temps d'établir les bases de test permettant de vérifier que le jeu fonctionne correctement (partie 2) ; • dans un second temps, de modéliser le jeu en complétant des classes fournies (partie 3) ; • puis dans une troisième étape de structurer votre application à l'aide d'une approche MVC (partie 4). 1 – Présentation des classes de Jeu Le premier objectif de ce sujet va consister à examiner le squelette des classes de Jeu fournies (cf annexes 1 et 2). 1/5 Le package game fourni contient deux classes : • • la classe Point qui a pour objectif de représenter des positions dans l’entrepôt ; la classe Entrepot qui décrit l’entrepôt à un instant donné. La classe Point Cette classe contient deux attributs x et y correspondant à une position dans l'entrepôt. La classe Point a pour objectif de gérer facilement des coordonnées. Ses attributs sont déclarés en public pour simplifier l'utilisation de la classe (cf annexe 1). La classe Entrepôt La classe Entrepot a pour objectif de représenter la situation du jeu (cf annexe 2). Cette classe est caractérisée par plusieurs attributs • un attribut laby qui décrit la configuration de l’entrepôt. laby est un tableau à deux dimensions d'entiers. La case du tableau d'indice [i][j] correspond au contenu de la position (i,j) de l'entrepôt. Elle prend ses valeurs parmi les constantes entières MUR (quand il y a un mur sur la case), VID (quand la case est vide) et CAI (quand la case contient une caisse); • un attribut heros de type Point qui décrit la position du héros dans l’entrepôt; • un tableau destination de Point correspondant aux différents lieux de destination des caisses. La classe Entrepot propose aussi plusieurs méthodes • un constructeur vide donné qui construit un entrepôt initial. • une méthode donnée int[] nextPos(int direction) qui fournit les variations de coordonnées de la case de destination en fonction de la direction passée en paramètre (un entier correspondant à une des constantes NORD, SUD, EST ou OUEST). Cette méthode permet de construire facilement les coordonnées de la case de destination en fonction d'une direction donnée. ◦ Par exemple, pour la direction Nord, la méthode nextPos retourne (0,-1) et la case à laquelle on arrive en partant de la case (8,10) et en suivant la direction Nord sera (8+0,10-1) = (8,9) . Plusieurs méthodes à compléter ◦ une méthode deplacePJ destinée à déplacer le personnage (et les caisses de l’entrepôt que le personnage parviendra à pousser) en fonction de la position du personnage et de la direction de son déplacement. • ◦ une méthode fin qui détecte la fin du jeu et retourne un booléen. Ce booléen vaut vrai si et seulement si toutes les caisses du labyrinthe sont sur un point de destination. Ces méthodes seront à compléter dans la partie 3. La première étape du DS va consister à bâtir des tests. 2- Classe Test Validité d'un niveau On souhaite vérifier que le niveau est un niveau valide. Pour cela, il faut vérifier à chaque instance de jeu que le nombre de caisses d'un niveau correspond effectivement au nombre de destinations. 2/5 Q1 - Pensez vous plutôt utiliser un test unitaire ou une assertion ? Expliquez la différence et justifiez. Q2 - Écrivez le test / l'assertion correspondante et précisez où et comment l'insérer dans les classes fournies. Validité de la méthode deplacerPersonnage Lorsqu'un personnage se déplace dans une direction donnée, plusieurs cas peuvent se produire. Il peut se déplacer sans problème si la case de destination est vide. Si un mur se trouve devant lui, le personnage ne peut pas se déplacer. Enfin, si une caisse est devant lui, il avance et pousse la caisse sauf si un obstacle l'en empêche (un mur ou une autre caisse). Si le déplacement de la caisse n'est pas possible le personnage ne peut pas avancer et rien n'est déplacé. On ne s’intéressera qu'aux déplacements vers la direction NORD, les autres déplacements étant supposés gérés de manière analogue. Nous allons tout d'abord nous intéresser au moyen de vérifier le bon comportement de la méthode déplacer à l'aide de tests unitaires. Q3 – Écrivez le test correspondant au cas où le héros avance vers une case vide en prenant soin de vérifier toutes les conséquences de l'action effectuée. Vous déclarerez la classe de test et y insérerez la méthode de test. Q4 – Décrivez les tests unitaires permettant de vérifier les autres cas qui pourraient se produire pour la méthode deplacePJ. Désormais, on ne demande plus d’écrire les tests en java, mais de décrire rapidement (un dessin ou une ligne peuvent suffire) les différentes situations à tester et les résultats attendus à vérifier. Tests à l'exécution On souhaite vérifier à l’exécution que le programme fonctionne correctement et que le personnage ne se trouve jamais à la même position qu'un mur ou qu'une caisse. Q5 - Écrire l'assertion correspondante. Q6 – Où cette assertion doit-elle être placée dans le programme (éventuellement à plusieurs endroits)? (Précisez le nom de la classe et les lignes). Justifiez en quelques mots votre réponse. 3 - Construction classe Entrepôt En pensant aux réponses données aux questions précédentes, complétez la classe Entrepot. Q7 - Écrire la méthode fin() qui permet de tester la fin de partie. Cette méthode renvoie vrai si et seulement si chaque caisse est placée sur une case de destination – on supposera qu'il y a bien un nombre de caisses égal au nombre de destinations (assuré par votre réponse à la question 2). Q8 - Écrire la méthode déplacerPj() qui permet de déplacer un personnage en utilisant la méthode direct et en prenant en compte les différents cas qui peuvent se présenter. 4 - Modèle-Vue-Controleur Cette partie va consister à greffer une interface graphique et un contrôleur pour permettre de jouer avec le clavier. L'application sera structurée selon une approche MVC. 3/5 Modèle Q9 – Quelle classe constitue le Modèle ? La classe Point doit-elle hériter de Observable ? La classe Entrepot doit-elle hériter de Observable ? Justifiez vos réponses Q10 - Indépendamment de la vue, comment faut-il modifier le modèle pour que les vues se mettent correctement à jour ? Où doivent se faire ces modifications dans le code qui vous a été fourni ? Vue Dans un package vue, on souhaite développer une vue graphique héritant d'un JPanel. Le début de la classe vous est fourni en Annexe (cf annexe 4). On souhaite que le constructeur de la classe VueGraphique gère entièrement le lien entre le modèle et la vue. le main (cf annexe 3) doit s'écrire de la manière suivante et n'est pas modifiable. package main; import game.Entrepot; import vue.Controleur; import vue.VueGraphique; public class Principale { public static void main(String[] args) { //creation de l'entrepot Entrepot j=new Entrepot(); //creation et ajout de la vue VueGraphique vg=new VueGraphique(j); //recuperation du controleur associé Controleur c=vg.getControleur(); //activation du controleur c.active(); } } Q11 - Écrivez le constructeur de la classe VueGraphique qui créé la JFrame, l'affiche et fait le lien avec le modèle. Q12 – Écrivez le contenu de la méthode update de la classe VueGraphique. Controleur On souhaite pouvoir gérer plusieurs Contrôleurs selon le même modèle. Pour cela on propose l'interface Controleur avec la méthode abstraite void active() qui active le contrôleur. Cette méthode active() aura bien entendu un fonctionnement différent en fonction du type de contrôleur (cf annexe 5). Q13 - Écrire une classe CText qui implémente Controleur, qui demande lorsqu'elle est activée un entier correspondant à la direction souhaitée du personnage et qui déplace le personnage. On fournit la classe CClavier correspondant à Controleur construit à partir d'un KeyListener(cf annexe 6). On souhaite ajouter une méthode getControleur dans la classe 4/5 VueGraphique. Cette méthode retourne un Controleur en lien avec la vue. Q14 - Ecrire la méthode getControleur de Vuegraphique qui retourne un contrôleur CClavier adapté et la méthode active() de CClavier qui ajoute le KeyListener à la vue. Lancement Supposons que toutes vos classes se situent dans un fichier sokoban.jar sans point d’accès et que les packages correspondent aux packages présentés dans le sujet. Q15 - Comment lancer l’exécution de la classe Principale située dans le package main ? 5/5