Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Add a TransporterRoom class to your project (exercise 6e: 11.8 ). Start with the code shown on page 6e: 412 /of the book. The TransporterRoom

  1. Add a TransporterRoom class to your project (exercise 6e: 11.8 ). Start with the code shown on page 6e: 412 /of the book.
    • The TransporterRoom will need access to the Scenario in order to return a random room as an exit. Add a Scenario field.
    • Add a constructor. It should take a description and scenario as parameters and initialize appropriately.
    • The findRandomRoom method can call getRandomRoom on the scenario.
    • You should also override the Room's getExitString method to print something appropriate for a transporter room.
  2. Don't forget to add a TransporterRoom to your game scenario.
    • See the sample run of a game with a transporter room.
  3. Test your program to make sure it works as expected!
  4. Document your changes.
    • For any changed classes, be sure your name is in the @author list and update the version.
    • As you add and update methods make sure each method has a comment header that correctly describes its behavior, including javadoc tags @param and @return as appropriate.

image text in transcribed

image text in transcribed

Command.java

/** * This class is part of the "World of Zuul" application. * "World of Zuul" is a very simple, text based adventure game. * * This class holds information about a command that was issued by the user. * A command currently consists of two strings: a command word and a second * word (for example, if the command was "take map", then the two strings * obviously are "take" and "map"). * * The way this is used is: Commands are already checked for being valid * command words. If the user entered an invalid command (a word that is not * known) then the command word is . * * If the command had only one word, then the second word is . * * @author Michael Klling and David J. Barnes * @version 2016.02.29 */ public class Command { private String 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(String 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 String getCommandWord() { return commandWord; } /** * @return The second word of this command. Returns null if there was no * second word. */ public String getSecondWord() { return secondWord; } /** * @return true if this command was not understood. */ public boolean isUnknown() { return (commandWord == null); } /** * @return true if the command has a second word. */ public boolean hasSecondWord() { return (secondWord != null); } command words.java 
public class CommandWords { // a constant array that holds all valid command words private static final String[] validCommands = { "go", "quit", "help" , "look" , "cook" }; /** * Constructor - initialise the command words. */ public CommandWords() { // nothing to do at the moment... } /** * Check whether a given String is a valid command word. * @return true if it is, false if it isn't. */ public boolean isCommand(String aString) { for(int i = 0; i  

Game.java

public class Game { private Parser parser; private Room currentRoom; private Item item; /** * Create the game and initialise its internal map. */ public Game() { createRooms(); parser = new Parser(); } /** * Create all the rooms and link their exits together. */ private void createRooms() { Room outside, livingroom, ritanroom, ramiroom, bathroom ,bedroom; Item picture; // create the rooms outside = new Room("outside the house"); bedroom = new Room("in main bedroom"); rroom = new Room("in the R's room"); riroom = new Room("in the Ri's room"); livingroom = new Room("in a family room"); bathroom = new Room("in the bathroom"); picture = new Item("family picture",2); livingroom.additem(picture); // initialise room exits outside.setExit("north",livingroom ); bedroom.setExit("east", livingroom); bathroom.setExit("west", livingroom); bathroom.setExit("north", riroom); bathroom.setExit("south", rroom); riroom.setExit("south", bathroom); rroom.setExit("north", bathroom); livingroom.setExit("south",outside); livingroom.setExit("west",bedroom); livingroom.setExit("east",bathroom); currentRoom = outside; // start game outside } /** * Main play routine. Loops until end of play. */ public void play() { printWelcome(); // Enter the main command loop. Here we repeatedly read commands and // execute them until the game is over. boolean finished = false; while (! finished) { Command command = parser.getCommand(); finished = processCommand(command); } System.out.println("Thank you for having fun together. Good bye."); } /** * Print out the opening message for the player. */ private void printWelcome() { System.out.println(); System.out.println("Welcome to the my house!"); System.out.println("feel free to walk around."); System.out.println("ask 'help' if you need help."); System.out.println(); System.out.println(currentRoom.getLongDescription()); } /** * Given a command, process (that is: execute) the command. * @param command The command to be processed. * @return true If the command ends the game, false otherwise. */ private boolean processCommand(Command command) { boolean wantToQuit = false; if(command.isUnknown()) { System.out.println("I don't know what you mean..."); return false; } String commandWord = command.getCommandWord(); if (commandWord.equals("help")) { printHelp(); } else if (commandWord.equals("go")) { goRoom(command); } else if (commandWord.equals("look")) { look(); } else if (commandWord.equals("cook")) { cook(); } else if (commandWord.equals("quit")) { wantToQuit = quit(command); } // else command not recognised. return wantToQuit; } // implementations of user commands: /** * Print out some help information. * Here we print some stupid, cryptic message and a list of the * command words. */ private void printHelp() { System.out.println("we are having fun gathering , making food , playing game "); System.out.println("at the house."); System.out.println(); System.out.println("Your command words are:"); System.out.println(parser.showCommands()); } /** * Try to in to one direction. If there is an exit, enter the new * room, otherwise print an error message. */ private void goRoom(Command command) { if(!command.hasSecondWord()) { // if there is no second word, we don't know where to go... System.out.println("Go where?"); return; } String direction = command.getSecondWord(); // Try to leave current room. Room nextRoom = currentRoom.getExit(direction); if (nextRoom == null) { System.out.println("There is no door!"); } else { currentRoom = nextRoom; System.out.println(currentRoom.getLongDescription()); } } /** * this method print getlong description */ private void look () { System.out.println(currentRoom.getLongDescription()); } /** * this method print lets make your favorite desh */ private void cook () { System.out.println ("lets make your favorite desh"); } /** * "Quit" was entered. Check the rest of the command to see * whether we really quit the game. * @return true, if this command quits the game, false otherwise. */ private boolean quit(Command command) { if(command.hasSecondWord()) { System.out.println("Quit what?"); return false; } else { return true; // signal that we want to quit } } }
} 

Room .JAva

public class Room { private String description; private HashMap exits; // stores exits of this room. private Item item; /** * Create a room described "description". Initially, it has * no exits. "description" is something like "a kitchen" or * "an open court yard". * @param description The room's description. */ public Room(String description) { this.description = description; exits = new HashMap(); this.item = item; } /** * Define an exit from this room. * @param direction The direction of the exit. * @param neighbor The room to which the exit leads. */ public void setExit(String direction, Room neighbor) { exits.put(direction, neighbor); } /** * @return The short description of the room * (the one that was defined in the constructor). */ public String getShortDescription() { return description; } /** * Return a description of the room in the form: * You are in the kitchen. * Exits: north west * @return A long description of this room */ public String getLongDescription() { if (item != null){ return "You are " + description + ". " + getExitString()+ item.getLongdescription(); } return "You are " + description + ". " + getExitString(); } /** * Return a string describing the room's exits, for example * "Exits: north west". * @return Details of the room's exits. */ private String getExitString() { String returnString = "Exits:"; Set keys = exits.keySet(); for(String exit : keys) { returnString += " " + exit; } return returnString; } /** * Return the room that is reached if we go from this room in direction * "direction". If there is no room in that direction, return null. * @param direction The exit's direction. * @return The room in the given direction. */ public Room getExit(String direction) { return exits.get(direction); } /** * create a variety of items */ public void additem(Item item){ // this.item = item; } }

Parser

ublic class Parser { private CommandWords commands; // holds all valid command words private Scanner reader; // source of command input /** * Create a parser to read from the terminal window. */ public Parser() { commands = new CommandWords(); reader = new Scanner(System.in); } /** * @return The next command from the user. */ public Command getCommand() { String inputLine; // will hold the full input line String word1 = null; String word2 = null; System.out.print("> "); // print prompt inputLine = reader.nextLine(); // Find up to two words on the line. Scanner tokenizer = new Scanner(inputLine); if(tokenizer.hasNext()) { word1 = tokenizer.next(); // get first word if(tokenizer.hasNext()) { word2 = tokenizer.next(); // 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). if(commands.isCommand(word1)) { return new Command(word1, word2); } else { return new Command(null, word2); } } /** * Print out a list of valid command words. */ public String showCommands() { String commandList =""; commandList =commands.getCommandList(); return commandList; } }
Figure 11.8 Access levels: private, protected, and public public Client SomeClass private Subclass1 Subclass 2 protected In Java, this rule is not as clear-cut as described here, because Java includes an additional level of vis- ibility, called package level, but with no associated keyword. We will not discuss this further, and it is more general to consider protected access as intended for the special relationship between superclass and subclass. 11.11 Another example of inheritance with overricing 4 11 412 Chapter 11 More about Inheritance implemented in the go Room method. In this method, we used the following statement as the central section of code: nextRoom = currentRoom.getExit (direction); This statement retrieves from the current room the neighboring room in the direction we want to go. To add our magic transportation, we could modify this in a form similar to the following: if(current Room.getName().equals("Transporter room")) { nextRoom = get RandomRoom(); The question, therefore, is: Can we find a solution that does not require a change to the com- mand implementation each time we add a new transporter room? Following is our next idea. We can add a method is Transporter Room in the Room class. This way, the Game object does not need to remember all the transporter roomsthe rooms themselves do. When rooms are created, they could receive a boolean flag indicating whether a given room is a transporter room. The goRoom method could then use the following code segment: if(current Room.isTransporter Room()) { nextRoom = get RandomRoom(); else { nextRoom = current Room.getExit (direction): else { nextRoom = currentRoom.getExit (direction): The idea here is simple: we just check whether we are in the transporter room. If we are, then we find the next room by getting a random room (of course, we have to implement the get RandomRoom method somehow); otherwise, we just do the same as before. While this solution works, it has several drawbacks. The first is that it is a bad idea to use text strings, such as the room's name, to identify the room. Imagine that someone wanted to translate your game into another languagesay, to German. They might change the names of the rooms "Transporter room" becomes "Transporter raum"-and suddenly the game does not work any more! This is a clear case of a maintainability problem. The second solution, which is slightly better, would be to use an instance variable instead of the room's name to identify the transporter room. Similar to this: Now we can add as many transporter rooms as we like; there is no need for any more changes to the Game class. However, the Room class has an extra field whose value is really needed only because of the nature of one or two of the instances. Special-case code such as this is a typical indicator of a weakness in class design. This approach also does not scale well should we decide to introduce further sorts of special rooms, each requiring its own flag field and accessor method." With inheritance, we can do better and implement a solution that is even more flexible than this one. We can implement a class Transporter Room as a subclass of class Room. In this new class, we override the getExit method and change its implementation so that it returns a random room: public class TransporterRoom extends Room if(current Room == transporterRoom) { nextRoom = getRandomRoom(): else { nextRoom = current Room.getExit (direction): *Return a random room, independent of the direction parameter. * @param direction Ignored. @return A random room. public Room getExit(String direction) This time, we assume that we have an instance variable transporter Room of class Room, where we store the reference to our transporter room. Now the check is independent of the room's name. That is a bit better. return findRandomRoom(); There is still a case for further improvement, though. We can understand the shortcomings of this solution when we think about another maintenance change. Imagine that we want to add two more transporter rooms, so that our game has three different transporter locations. Choose a random room @return A random room. private Room findRandomRoom) A very nice aspect of our existing design was that we could set up the floor plan in a single spot, and the rest of the game was completely independent of it. We could easily change the layout of the rooms, and everything would still work-high score for maintainability! With our current solution, though, this is broken. If we add two new transporter rooms, we have to add two more instance variables or an array (to store references to those rooms). and we have to modify our goRoom method to add a check for those rooms. In terms of easy changeability, we have gone backwards. ... // implementation omitted We might also think of using instanceof, but the point here is that none of these ideas is the best Make sure that you understand why a test for reference equality is the most appropriate here. Figure 11.8 Access levels: private, protected, and public public Client SomeClass private Subclass1 Subclass 2 protected In Java, this rule is not as clear-cut as described here, because Java includes an additional level of vis- ibility, called package level, but with no associated keyword. We will not discuss this further, and it is more general to consider protected access as intended for the special relationship between superclass and subclass. 11.11 Another example of inheritance with overricing 4 11 412 Chapter 11 More about Inheritance implemented in the go Room method. In this method, we used the following statement as the central section of code: nextRoom = currentRoom.getExit (direction); This statement retrieves from the current room the neighboring room in the direction we want to go. To add our magic transportation, we could modify this in a form similar to the following: if(current Room.getName().equals("Transporter room")) { nextRoom = get RandomRoom(); The question, therefore, is: Can we find a solution that does not require a change to the com- mand implementation each time we add a new transporter room? Following is our next idea. We can add a method is Transporter Room in the Room class. This way, the Game object does not need to remember all the transporter roomsthe rooms themselves do. When rooms are created, they could receive a boolean flag indicating whether a given room is a transporter room. The goRoom method could then use the following code segment: if(current Room.isTransporter Room()) { nextRoom = get RandomRoom(); else { nextRoom = current Room.getExit (direction): else { nextRoom = currentRoom.getExit (direction): The idea here is simple: we just check whether we are in the transporter room. If we are, then we find the next room by getting a random room (of course, we have to implement the get RandomRoom method somehow); otherwise, we just do the same as before. While this solution works, it has several drawbacks. The first is that it is a bad idea to use text strings, such as the room's name, to identify the room. Imagine that someone wanted to translate your game into another languagesay, to German. They might change the names of the rooms "Transporter room" becomes "Transporter raum"-and suddenly the game does not work any more! This is a clear case of a maintainability problem. The second solution, which is slightly better, would be to use an instance variable instead of the room's name to identify the transporter room. Similar to this: Now we can add as many transporter rooms as we like; there is no need for any more changes to the Game class. However, the Room class has an extra field whose value is really needed only because of the nature of one or two of the instances. Special-case code such as this is a typical indicator of a weakness in class design. This approach also does not scale well should we decide to introduce further sorts of special rooms, each requiring its own flag field and accessor method." With inheritance, we can do better and implement a solution that is even more flexible than this one. We can implement a class Transporter Room as a subclass of class Room. In this new class, we override the getExit method and change its implementation so that it returns a random room: public class TransporterRoom extends Room if(current Room == transporterRoom) { nextRoom = getRandomRoom(): else { nextRoom = current Room.getExit (direction): *Return a random room, independent of the direction parameter. * @param direction Ignored. @return A random room. public Room getExit(String direction) This time, we assume that we have an instance variable transporter Room of class Room, where we store the reference to our transporter room. Now the check is independent of the room's name. That is a bit better. return findRandomRoom(); There is still a case for further improvement, though. We can understand the shortcomings of this solution when we think about another maintenance change. Imagine that we want to add two more transporter rooms, so that our game has three different transporter locations. Choose a random room @return A random room. private Room findRandomRoom) A very nice aspect of our existing design was that we could set up the floor plan in a single spot, and the rest of the game was completely independent of it. We could easily change the layout of the rooms, and everything would still work-high score for maintainability! With our current solution, though, this is broken. If we add two new transporter rooms, we have to add two more instance variables or an array (to store references to those rooms). and we have to modify our goRoom method to add a check for those rooms. In terms of easy changeability, we have gone backwards. ... // implementation omitted We might also think of using instanceof, but the point here is that none of these ideas is the best Make sure that you understand why a test for reference equality is the most appropriate here

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Hands-On Database

Authors: Steve Conger

2nd Edition

0133024415, 978-0133024418

More Books

Students also viewed these Databases questions