Rapport TP3

Transcription

Rapport TP3
Rapport TP n°3
Code texte :
Gras = nomClasse
Italique = nomMéthode()
Code couleurs :
Classe Game + modification mise en évidence
Classe Room + modification mise en évidence
Classe CommandWords + modification mise en évidence
Classe Parser + modification mise en évidence
Classe GameEngine + modification mise en évidence
Classe UserInterface + modification mise en évidence
Classe GameModel + modification mise en évidence
Classe TextView + modification mise en évidence
Classe Item + modification mise en évidence
Au TP3 :
Classe Player + modification mise en évidence
Classe ItemList + modification mise en évidence
Classe Command + modification mise en évidence
Classe CommandWord + modification mise en évidence
Exercice 7.29
Refactor your project to introduce a separate Player class. A player object should store at least the
current room of the player, but you may also like to store the player’s name or other information.
Nous avons anticipé les exercices en intégrant directement la classe ItemList pour gérer l'inventaire
du personnage.
La classe Player gère la Room dans laquelle se trouve le personnage. Des modifications sont alors
imposées dans les autres classes sur le cheminement des méthodes qui permettent d'agir sur les
Rooms.
import java.util.Stack;
public class Player {
private String playerName;
private int playerCurrentWeight, playerMaxWeight;
private Room currentRoom;
private Stack<Room> walkthroughRoom;
private ItemList inventory;
public Player(String pPlayerName, int pPlayerMaxWeight, Room pCurrentRoom)
{
this.playerName = pPlayerName;
this.playerMaxWeight = pPlayerMaxWeight;
this.playerCurrentWeight = 0;
this.currentRoom = pCurrentRoom;
this.walkthroughRoom = new Stack<Room>();
this.inventory = new ItemList();
}
public String getPlayerName()
{
return playerName;
}
public int getPlayerCurrentWeight()
{
return playerCurrentWeight;
}
public Room getCurrentRoom()
{
return currentRoom;
}
public Room setCurrentRoom(Room pCurrentRoom)
{
return currentRoom = pCurrentRoom;
}
public int getPlayerMaxWeight()
{
return playerMaxWeight;
}
public void setPlayerMaxWeight(int pAddMaxWeight)
{
playerMaxWeight += pAddMaxWeight;
}
public Stack<Room> getWalkthroughRoom()
{
return walkthroughRoom;
}
/**
* @return True if the Stack is empty.
*/
public boolean lookWalkthroughRoom()
{
}
return walkthroughRoom.empty();
/**
* Put a room in the walkthrough Stack.
*/
public void actualiseWalkthroughRoom()
{
walkthroughRoom.push(currentRoom);
}
/**
* @return The last Room of the Stack and delete it in the Stack.
*/
public Room getPreviousRoom()
{
return walkthroughRoom.pop();
}
public boolean canBePickedUp(String pItemName)
{
if (this.playerCurrentWeight + currentRoom.getItem(pItemName).getWeight()
> playerMaxWeight)
return false;
else
return true;
}
public boolean canBeDroped(String pItemName)
{
if (inventory.getItem(pItemName) == null)
return false;
else
return true;
}
public void addItemInventory(String pItemName)
{
playerCurrentWeight = playerCurrentWeight +
currentRoom.getItem(pItemName).getWeight();
inventory.addItem(currentRoom.getItem(pItemName));
}
public void removeItem(String pItemName)
{
playerCurrentWeight = playerCurrentWeight inventory.getItem(pItemName).getWeight();
inventory.removeItem(currentRoom.getItem(pItemName).getNameItem());
}
public ItemList getInventory()
{
return inventory;
}
}
Exercice 7.30
Implement an extension that allows a player to pick up one single item. This includes implementing
two new commands: take and drop.
Ajout des commandes take et drop dans le jeu (dans GameEngine et CommandWords)
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class GameEngine
{
public void take(Command command)
{
if(!command.hasSecondWord()) {
// if there is no second word, we don't know what to do...
gui.println("There isn't this item here.");
return;
}
String takeSecondWord = command.getSecondWord();
if(gameModel.getCurrentRoom().getItem(takeSecondWord) == null)
{
gui.println("There isn't this item here.");
return;
}
if(gameModel.getPlayer().canBePickedUp(takeSecondWord) == false)
{
gui.println("You can't take this item");
return;
}
gameModel.getPlayer().addItemInventory(takeSecondWord);
gameModel.getCurrentRoom().removeItem(takeSecondWord);
gui.println(gameModel.getPlayer().getPlayerName() + " has take " +
takeSecondWord);
}
public void drop(Command command)
{
if(!command.hasSecondWord()) {
// if there is no second word, we don't know what to do...
gui.println("There isn't this item here.");
return;
}
String dropSecondWord = command.getSecondWord();
Item dropItem =
gameModel.getPlayer().getInventory().getItem(dropSecondWord);
if(gameModel.getPlayer().canBeDroped(dropSecondWord) == false)
{
gui.println("You don't have this item");
}
return;
gameModel.getCurrentRoom().addItem(dropItem);
gameModel.getPlayer().removeItem(dropSecondWord);
gui.println(gameModel.getPlayer().getPlayerName() + " has droped " +
dropSecondWord);
}
}
Exercice 7.31
Créer une nouvelle classe ItemList pour gérer une liste d'items et ainsi mutualiser la gestion des
items qui se retrouvait dupliquée dans Room et dans Player. La collection utilisée dans ItemList n'est
pas censée pouvoir être manipulée depuis l'extérieur.
import java.util.HashMap;
import java.util.Set;
public class ItemList {
private HashMap<String, Item> inventory;
public ItemList()
{
this.inventory = new HashMap<String, Item>();
}
public Item getItem(String pItemName)
{
return inventory.get(pItemName);
}
public String getStringInventory()
{
StringBuilder inventoryStringBuilder = new StringBuilder("Inventory :
");
Set<String> keys = inventory.keySet();
for(String items : keys)
inventoryStringBuilder.append(items + ", ");
}
return inventoryStringBuilder.toString();
public void addItem(Item pItem)
{
inventory.put(pItem.getNameItem(), pItem);
}
public void removeItem(String pItem)
{
inventory.remove(pItem);
}
}
public boolean InventoryIsEmpty()
{
return inventory.isEmpty();
}
Exercice 7.32
Add a restriction that allows the player to carry items only up to a specified maximum weight. The
maximum weight a player can carry is an attribute of the player.
Le poids a déjà été géré lors de la création de la classe Player
Exercice 7.33
Implement an items command that prints out all items currently carried and their total weight.
Ajout de la commande items
public void items()
{
if(gameModel.getPlayer().getInventory().InventoryIsEmpty() == true)
{
gui.println("The inventory is empty.");
return;
}
else
gui.println(gameModel.getPlayer().getInventory().getStringInventory()+ "
total weight : " +
gameModel.getPlayer().getPlayerCurrentWeight());
}
Exercice 7.34
Add a magic cookie item to a room. Add an eat cookie command. If a player finds and eats the magic
cookie, it increases the weight that the player can carry. (You might like to modify this slightly to
better fit into your own game scenario.)
Nous avons ajouté, puis changé le nom de l'objet pour rester dans le thème de notre jeu. Nous
l'avons nommé "soul". Il aura pour effet d'augmenter le poids total que le personnage peut
transporter.
La méthode eat() a donc dû être modifiée. La méthode comporte maintenant un paramètre dans sa
signature.
public void eat(Command command)
{
if(!command.hasSecondWord()) {
// if there is no second word, we don't know what to do...
gui.println("Eat what ?");
return;
}
String soulString = command.getSecondWord();
if(gameModel.getPlayer().getInventory().getItem(soulString) !=
gameModel.getPlayer().getInventory().getItem("soul"))
{
}
}
gui.println("You can't eat it !");
return;
if(gameModel.getPlayer().getInventory().getItem(soulString) == null)
{
gui.println("You don't have any souls !");
return;
}
else
{
gameModel.getPlayer().getInventory().removeItem("soul");
gameModel.getPlayer().setPlayerMaxWeight(15);
gui.println("Yuki can now bring a total weight of : " +
gameModel.getPlayer().getPlayerMaxWeight());
return;
}
Exercice 7.35
Apprentissage : enum, values()
Enum est une classe qui contient un ensemble de valeurs que peut prendre la classe. Mais elle peut
tout de même contenir des méthodes et des constructeurs.
La méthode values() retourne un tableau qui contient toutes les valeurs de la classe enum définie.
Exercice 7.35.1
Review the source code of the zuul-with-enums-v1 project to see how it uses the CommandWord
type. The classes Command, CommandWords, Game, and Parser have all been adapted from the
zuul-better version to accommodate this change. Check that the program still works as you would
expect.
public void interpretCommand(String commandLine)
{
Command command = parser.getCommand(commandLine);
CommandWord commandWord = command.getCommandWord();
if(command.isUnknown()) {
gui.println("I don't know what you mean…");
return;
}
if (commandWord == CommandWord.HELP)
printHelp(command);
else if (commandWord == CommandWord.GO)
goRoom(command);
else if (commandWord == CommandWord.BACK)
goBack(command);
else if (commandWord == CommandWord.LOOK)
look(command);
}
else if (commandWord ==
use(command);
else if (commandWord ==
test(command);
else if (commandWord ==
take(command);
else if (commandWord ==
drop(command);
else if (commandWord ==
items(command);
else if (commandWord ==
endGame(command);
CommandWord.EAT)
CommandWord.TEST)
CommandWord.TAKE)
CommandWord.DROP)
CommandWord.ITEMS)
CommandWord.QUIT)
import java.util.HashMap;
public class CommandWords
{
private HashMap<String, CommandWord> validCommands;
/**
* Constructor - initialise the command words.
*/
public CommandWords()
{
validCommands = new HashMap<String, CommandWord>();
validCommands.put("go", CommandWord.GO);
validCommands.put("quit", CommandWord.QUIT);
validCommands.put("help", CommandWord.HELP);
validCommands.put("look", CommandWord.LOOK);
validCommands.put("eat", CommandWord.EAT);
validCommands.put("back", CommandWord.BACK);
validCommands.put("test", CommandWord.TEST);
validCommands.put("take", CommandWord.TAKE);
validCommands.put("drop", CommandWord.DROP);
validCommands.put("items", CommandWord.ITEMS);
}
public CommandWord getCommandWord(String commandWord)
{
CommandWord command = validCommands.get(commandWord);
if(command != null)
return command;
else
return CommandWord.UNKNOWN;
}
/**
* Check whether a given String is a valid command word.
* @return true if a given string is a valid command,
* false if it isn't.
*/
public boolean isCommand(String aString)
{
return validCommands.containsKey(aString);
}
/**
}
* @return The list of commands.
*/
public String getCommandList()
{
StringBuilder vCommand = new StringBuilder();
for(String command : validCommands.keySet()) {
vCommand.append(command+" ");
}
return vCommand.toString();
}
public class Command
{
private CommandWord commandWord;
private String secondWord;
/**
* Create a command object. First and second word must be supplied, but
* either one (or both) can be null.
* @param firstWord The first word of the command. Null if the command
*
was not recognised.
* @param secondWord The second word of the command.
*/
public Command(CommandWord firstWord, String secondWord)
{
commandWord = firstWord;
this.secondWord = secondWord;
}
/**
* Return the command word (the first word) of this command. If the
* command was not understood, the result is null.
* @return The command word.
*/
public CommandWord getCommandWord()
{
return commandWord;
}
/**
* See "Returns" comment.
* @return The second word of this command. Returns null if there was no
* second word.
*/
public String getSecondWord()
{
return secondWord;
}
/**
* See "Returns" comment.
* @return true if this command was not understood.
*/
public boolean isUnknown()
{
return (commandWord == CommandWord.UNKNOWN);
}
}
/**
* See "Returns" comment.
* @return true if the command has a second word.
*/
public boolean hasSecondWord()
{
return (secondWord != null);
}
import java.util.StringTokenizer;
public class Parser
{
private CommandWords commands;
// holds all valid command words
/**
* Create a parser to read from the terminal window.
*/
public Parser()
{
commands = new CommandWords();
}
/**
* Get a new command from the user. The command is read by
* parsing the 'inputLine'.
*/
public Command getCommand(String inputLine)
{
//String inputLine = "";
// will hold the full input line
String word1;
String word2;
StringTokenizer tokenizer = new StringTokenizer(inputLine);
if(tokenizer.hasMoreTokens())
word1 = tokenizer.nextToken();
else
word1 = null;
if(tokenizer.hasMoreTokens())
word2 = tokenizer.nextToken();
else
word2 = null;
// get first word
// get second word
// note: we just ignore the rest of the input line.
// Now check whether this word is known. If so, create a command
// with it. If not, create a "null" command (for unknown command).
}
return new Command(commands.getCommandWord(word1), word2);
/**
* @return The list of commands.
*/
public String showCommands()
{
}
}
return commands.getCommandList();
Exercice 7.35.2
En s'inspirant de processCommand() de la classe Game dans zuul-with-enums-v1, remplacer dans
interpreteCommand() de la classe GameEngine dans son jeu la suite de if else par un switch (autorisé
sur un type énuméré !) ; tout recompiler : il ne doit y avoir aucun warning.
public void interpretCommand(String commandLine)
{
gui.println(commandLine);
Command command = parser.getCommand(commandLine);
CommandWord commandWord = command.getCommandWord();
switch(commandWord)
{
case UNKNOWN : gui.println("I don't know what you mean...");
break;
case HELP : printHelp();
break;
case GO : goRoom(command);
break;
case BACK : goBackRoom(command);
break;
case LOOK : look();
break;
case EAT : eat(command);
break;
case TEST : test(command);
break;
case TAKE : take(command);
break;
case DROP : drop(command);
break;
case ITEMS : items();
break;
case QUIT : endGame();
break;
}
}
Apprentissage : switch
Le switch permet de faire plusieurs tests sur une variable. À chaque test correspond d'autres
instructions si le test est positif. Puis le break permet de sortir du switch.
Exercice 7.35.3
Génération de la progdoc et de l’userdoc
javadoc -d progdoc -author -version -private -linksource *.java
javadoc -d userdoc -author -version *.java
Exercice 7.37
‘Translate’ the game to use different command words from go and quit for the GO and QUIT
commands. These could be from a real language or just made up words. Do you only have to edit the
CommandWords class to make this change work?
public CommandWords()
{
validCommands = new HashMap<String, CommandWord>();
validCommands.put("go", CommandWord.GO);
validCommands.put("aller", CommandWord.GO);
validCommands.put("quit", CommandWord.QUIT);
validCommands.put("quitter", CommandWord.QUIT);
validCommands.put("help", CommandWord.HELP);
validCommands.put("aide", CommandWord.HELP);
validCommands.put("look", CommandWord.LOOK);
validCommands.put("regarder", CommandWord.LOOK);
validCommands.put("eat", CommandWord.EAT);
validCommands.put("manger", CommandWord.EAT);
validCommands.put("back", CommandWord.BACK);
validCommands.put("retour", CommandWord.BACK);
validCommands.put("test", CommandWord.TEST);
validCommands.put("take", CommandWord.TAKE);
validCommands.put("prendre", CommandWord.TAKE);
validCommands.put("drop", CommandWord.DROP);
validCommands.put("jeter", CommandWord.DROP);
validCommands.put("items", Command
}
Dans le constructeur de CommandWords, on attribut des String qui correspondront chacune à une
commande. On peut donc attribuer plusieurs String différentes sur la même commande. Comme par
exemple, deux mots de langues différentes.
Aucune autre modification est nécessaire.
Exercice 7.38
Choose a different command instead of help and check that it works correctly. After you have made
your changes, what do you notice about the welcome message that is printed when the game starts?
Le message de début de jeu ne prend pas compte les modifications si on change la commande d'aide.
Exercice 7.40
Add your own look command to zuul-with-enums-v2. Do you only need to change the
CommandWord type?
Après les modifications de CommandWord, il faut changer les instructions permettant de rentrer les
valeurs de CommandWord dans CommandWords.
public enum CommandWord {
GO("go"), QUIT("quit"), HELP("help"), LOOK("look"), EAT("eat"), BACK("back"),
TEST("test"), TAKE("take"), DROP("drop"), ITEMS("items"), UNKNOWN("?");
private String commandString;
/**
* Initialise with the corresponding command word.
* @param commandWord The command string.
*/
CommandWord(String commandString)
{
this.commandString = commandString;
}
}
/**
* @return The command word as a string.
*/
public String toString()
{
return commandString;
}
public CommandWords()
{
validCommands = new HashMap<String, CommandWord>();
for(CommandWord command : CommandWord.values())
if(command != CommandWord.UNKNOWN)
validCommands.put(command.toString(), command);
}
Exercice 7.41
Change the word associated with the help command in CommandWord. Is this change automatically
reflected in the welcome text when you start the game? Take a look at the printWelcome method in
the Game class to see how this has been achieved.
public String getWelcomeString()
{
StringBuilder welcomeString = new StringBuilder();
welcomeString.append("\nWelcome in X's mind\nDungeon Mind is the adventure
of a poor boy"+
"\nType "+CommandWord.HELP.toString()+" if you need help.
\n"+player.getCurrentRoom().getLongDescription()+
"\n").append("Your command words are : "+parser.showCommands());
return welcomeString.toString();
}