0% found this document useful (0 votes)
50 views9 pages

Lab Week 7 - Implementing Move in The Mazegame

1. The document discusses implementing the ability to move in the MazeGame by creating a command parser class. 2. It describes creating a ParsedInput class to represent parsed user input of a command and arguments, and a Parser class to split user input into a ParsedInput object. 3. The DungeonMaster class is updated to use the new Parser class to interpret user input as a command and arguments, though only the "quit" command is currently implemented.

Uploaded by

ali haider
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
50 views9 pages

Lab Week 7 - Implementing Move in The Mazegame

1. The document discusses implementing the ability to move in the MazeGame by creating a command parser class. 2. It describes creating a ParsedInput class to represent parsed user input of a command and arguments, and a Parser class to split user input into a ParsedInput object. 3. The DungeonMaster class is updated to use the new Parser class to interpret user input as a command and arguments, though only the "quit" command is currently implemented.

Uploaded by

ali haider
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 9

Lab week 7 – Implementing Move in the MazeGame

Explore the codebase


1. Download the “Lab 7” code (this code was discussed in the lecture and has implemented the startup use case).
2. Unzip the code and open up the solution in Eclipse by performing the following steps.
a. Open Eclipse
b. Open the file menu and click import . . .
c. From the dialog box
i. Open the “general” tab
ii. Click “Existing Projects into Workspace”
iii. Click next
d. Click “browse” and navigate that holds the lab 7 code
i. The folder ABOVE the bin and src folders
ii. Make sure the check box is clicked in the “projects” text box
iii. Click “finish”
e. The project should now appear in the “projects explorer” pane on the left of Eclipse
3. Spend some time exploring the code, change the startup location in the HardCodedData class and run the project
to test the results.
4. Create an Enterprise Architect project called Lab 7 and reverse engineer the code to create class diagrams.

Creating a command parser


Before we can get started on implementing commands and adding further functionality to the Maze Game we
need a way of breaking up the user input. Commands have a format of command <argument(s)> i.e.: move
west
So what we need to do is break up our user input from a single string into a number of words, and work out
which are commands and which are arguments. We can assume that the first word encountered in user input
is the command, and what follows are the argument(s). We could even make our command parser a little
more user friendly by dropping off commonly used words that are neither commands nor useful arguments.
ie: if the user typed “go to the north” we could drop to and the.

CRICOS Provider No. 00103D Insert file name here Page 1 of 9


Let’s start by creating a class to represent our input after it has been parsed into command + arguments.
Create a new class in the Control package called ParsedInput and enter the following:
package mazegame.control;

import java.util.ArrayList;

public class ParsedInput {

private String command;


private ArrayList arguments;

public ParsedInput() {
setArguments(new ArrayList());
setCommand("");
}

public ParsedInput(String command, ArrayList arguments){


this.setCommand(command);
this.setArguments(arguments);
}

public String getCommand() {


return command;
}

public void setCommand(String command) {


this.command = command;
}

public ArrayList getArguments() {


return arguments;
}

public void setArguments(ArrayList arguments) {


this.arguments = arguments;
}
}

CRICOS Provider No. 00103D Insert file name here Page 2 of 9


Now create a new class called Parser in the same package with the following code:
package mazegame.control;

import java.util.ArrayList;
import java.util.Arrays;

public class Parser {


private ArrayList<String> dropWords;
private ArrayList<String>validCommands;

public Parser(ArrayList<String> validCommands){


dropWords = new ArrayList<String>(Arrays.asList("an","and","the","this", "to"));
this.validCommands = validCommands;
}

public ParsedInput parse(String rawInput)


{
ParsedInput parsedInput = new ParsedInput();
String lowercaseInput = rawInput.toLowerCase();
ArrayList<String> stringTokens = new
ArrayList<String>(Arrays.asList(lowercaseInput.split(" ")));

for (String token : stringTokens)


{

if (validCommands.contains(token))
{
parsedInput.setCommand(token);
}
else if (!dropWords.contains(token))
parsedInput.getArguments().add(token);
}
return parsedInput;
}
}

So we now have a class which can parse our user input, provided it is given a list of commands when it gets
constructed.

Incorporating Command handling in the DungeonMaster class


Now that we have a parser we need to put it to work. But before we do that we need to make a small change
to our user interface to accommodate retrieving a command from the player.

CRICOS Provider No. 00103D Insert file name here Page 3 of 9


Our IMazeClient interface currently has the following two methods declared:
package mazegame.boundary;

public interface IMazeClient {


public String getReply (String question);
public void playerMessage (String message);
}

We could probably use GetReply for the purpose of retrieving commands from a player, but the method is
really designed to ask players a question. So let’s introduce a new method specifically to capture player
commands.
package mazegame.boundary;

public interface IMazeClient {


public String getReply (String question);
public void playerMessage (String message);
public String getCommand();
}

We can now adjust our SimpleConsoleClient class accordingly:


package mazegame;

import java.util.Scanner;
import mazegame.boundary.IMazeClient;

public class SimpleConsoleClient implements IMazeClient {

public String getReply (String question) {


System.out.println("\n" + question + " ");
Scanner in = new Scanner (System.in);
return in.nextLine();
}

public void playerMessage (String message) {


System.out.print(message);
}

public String getCommand() {


System.out.print ("\n\n>>>\t");
return new Scanner(System.in).nextLine();
}
}

CRICOS Provider No. 00103D Insert file name here Page 4 of 9


Now that our client is setup to retrieve commands from the user we can modify DungeonMaster as follows:
package mazegame.control;

import java.io.IOException;
import java.util.ArrayList;

import mazegame.SimpleConsoleClient;
import mazegame.boundary.IMazeClient;
import mazegame.boundary.IMazeData;
import mazegame.entity.Player;

public class DungeonMaster {


private IMazeClient gameClient;
private IMazeData gameData;
private Player thePlayer;
private boolean continueGame;
private ArrayList<String> commands;
private Parser theParser;

public DungeonMaster(IMazeData gameData, IMazeClient gameClient) {


this.gameData = gameData;
this.gameClient = gameClient;
this.continueGame = true;
commands = new ArrayList<String>();
commands.add("quit");
commands.add("move");
theParser = new Parser (commands);
}

public void printWelcome() {


gameClient.playerMessage(gameData.getWelcomeMessage());
}

public void setupPlayer() {


String playerName = gameClient.getReply("What name do you choose to be known by?");
thePlayer = new Player(playerName);
gameClient.playerMessage("Welcome " + playerName + "\n\n");
gameClient.playerMessage("You find yourself looking at ");
gameClient.playerMessage(gameData.getStartingLocation().getDescription());

// gameClient.getReply("<<Hit Enter to exit>>");


}

public void runGame() {


printWelcome();
setupPlayer();
while (continueGame) {
continueGame = processPlayerTurn();
}
}

public boolean processPlayerTurn() {


ParsedInput userInput = theParser.parse(gameClient.getCommand());
if (commands.contains(userInput.getCommand())) {
if (userInput.getCommand().equals("quit"))
return false;

CRICOS Provider No. 00103D Insert file name here Page 5 of 9


if (userInput.getCommand().equals("move")) {
gameClient.playerMessage("You entered the move command");
return true;
}
}
gameClient.playerMessage("We don't recognise that command - try again!");
return true;
}
}

Build your code and run it. You should be able to test it out as follows:

So our game can now interpret commands, but other than quit, it doesn’t really do anything. Furthermore, our
DungeonMaster class is starting to get very messy and may require refactoring. This will be dealt with next
week when we discuss the Command design pattern.

Implementing the Move Player command


Our RAD describes a Move Party User Story:

 “Move Party - players specify the direction in which they wish their party to move. If an available exit exists in the
direction specified, the system updates the player's party location and returns a description of the new location”

At this stage we have decided to leave parties out so we rewrite the user story as:

 “Move Player - players specify the direction in which they wish to move. If an available exit exists in the direction
specified, the system updates the player's location and returns a description of the new location”

CRICOS Provider No. 00103D Insert file name here Page 6 of 9


Let’s implement this user story by first changing the Player class as follows:

package mazegame.entity;

public class Player extends Character {

private Location currentLocation;

public Player() {
}

public Player(String name) {


super (name);
}

public Location getCurrentLocation() {


return currentLocation;
}

public void setCurrentLocation(Location currentLocation) {


this.currentLocation = currentLocation;
}

Now we amend the SetupPlayer method in DungeonMaster as follows:

public void setupPlayer() {


String playerName = gameClient.getReply("What name do you choose to be known by?");
thePlayer = new Player(playerName);
thePlayer.setCurrentLocation(gameData.getStartingLocation());
gameClient.playerMessage("Welcome " + playerName + "\n\n");
gameClient.playerMessage("You find yourself looking at ");
gameClient.playerMessage(gameData.getStartingLocation().getDescription());

// gameClient.getReply("<<Hit Enter to exit>>");

CRICOS Provider No. 00103D Insert file name here Page 7 of 9


Next we need to change the Location class so we can retrieve an Exit.

package mazegame.entity;

import java.util.HashMap;

public class Location {


private HashMap exits;
private String description;
private String label;

public Location () { }

public Location (String description, String label) {


this.setDescription(description);
this.setLabel(label);
exits = new HashMap();
}

public boolean addExit (String exitLabel, Exit theExit) {


if (exits.containsKey(exitLabel))
return false;
exits.put(exitLabel, theExit);
return true;
}

public Exit getExit(String exitLabel) {


return (Exit) exits.get(exitLabel);
}

public String getDescription() {


return description;
}

public void setDescription(String description) {


this.description = description;
}

public String getLabel() {


return label;
}

public void setLabel(String label) {


this.label = label;
}

CRICOS Provider No. 00103D Insert file name here Page 8 of 9


Now that we have our Location class setup to retrieve an Exit we can amend the DungeonMaster class to accommodate
player movement. Amend the ProcessPlayerTurn and implement a new method called processMove in DungeonMaster
as follows:

public boolean processPlayerTurn() {


ParsedInput userInput = theParser.parse(gameClient.getCommand());
if (commands.contains(userInput.getCommand())) {
if (userInput.getCommand().equals("quit"))
return false;
if (userInput.getCommand().equals("move")) {
processMove(userInput);
return true;
}
}
gameClient.playerMessage("We don't recognise that command - try again!");
return true;
}

private void processMove(ParsedInput userInput) {


String exitLabel = (String) userInput.getArguments().get(0);
Exit desiredExit = thePlayer.getCurrentLocation().getExit(exitLabel);
if (desiredExit == null) {
gameClient.playerMessage("There is no exit there . . . try moving somewhere
else");
return;
}
thePlayer.setCurrentLocation(desiredExit.getDestination());
gameClient.playerMessage("You find yourself looking at ");
gameClient.playerMessage(thePlayer.getCurrentLocation().getDescription());

Run the game and type “move west” to verify the result. At this point we have implemented player movement but it is very
crude. You might like to think about how this might be improved from a usability perspective with some play testing (for
example creating a ToString method in Location including both the name of the Location and the Description and then
printing that to the user might be better than just the Location description alone). But this is left as a further optional
exercise for you.

CRICOS Provider No. 00103D Insert file name here Page 9 of 9

You might also like