2018sp-cs117-stage2-Commands.pdf

Name CS117 Project Stage 02: Commands – Page 1

Project Stage 02: Commands

Currently, there are only three commands possible in our game: go, help, and quit. Obviously you will want to add additional commands to the game. In this stage, we will learn how to add commands to our game.

1 Introduction

In order to specify the commands that will be available in our game and how the game will respond to each command, we will use a technique from software engineering. It is becoming more and more common in industry to use behavior driven development (BDD) techniques to specify how a program should behave. The goal of behavior driven development is to develop a clear understanding of how software behaves. It also has the added bonus of enumerating what to test.

BDD specifies the behavior of software using scenarios and uses a particular format. To make this concrete, let’s look at an example:

QUIT Scenario #1:

GIVEN :

WHEN : "quit" is entered

THEN : appropriate message is displayed (thanks for playing)

and : program quits

The first thing to note is that the scenario is given a description (“QUIT Scenario #1”) that is short enough that it can be used to refer to when discussing the behaviors of the command. Each scenario consists of three parts:

• Given describes the initial context of the behavior: what is required for this behavior to be applicable. This part often consists of several short statements connected with and or or. If the behavior is always applicable, like it is for QUIT, this will be empty.

• When describes what event occurs that causes the behavior to be triggered. In the case of our game, this will almost always be some command typed at the prompt by the user. (You can see why we think it is a good way to describe commands in our game.)

• Then describes what happens in the game as a result of the trigger described above. This part often consists of several short statements connected with and or or.

Since every scenario consists of all three parts, these are often referred to as GWTs. We will be writing GWTs to help us specify the behavior of each of the commands in the game. In the beginning, we will provide GWTs for your commands. In the end, you will be writing them yourself.

2 Exploring GWTs

To make this clearer, let us specify the other two commands that are already implemented in our game. With each one, run the game and see if the behavior matches what is described:

HELP Scenario #1:

GIVEN :

WHEN : "help" is entered

THEN : available commands are displayed

Name CS117 Project Stage 02: Commands – Page 2

Here’s one for the “go” command:

GO Scenario #3: Exit exists

GIVEN : there is an exit in the given direction

WHEN : "go direction" is entered

THEN : player’s current room is changed to the room in the given direction

and : the current room’s points are added to the player’s score

and : player’s current location is displayed

Notice that in this scenario the command word is followed by a second word. We used a generic term for the direction in the command that was issued. Many of our commands will require multiple words. If the player had just entered “go” without a direction, we would have a different scenario:

GO Scenario #1: No direction specified

GIVEN :

WHEN : "go" is entered

THEN : appropriate message is displayed (which direction?)

Furthermore, if the player asks to go in a direction where there is no exit:

GO Scenario #2: No exit exists

GIVEN : there is no exit in the given direction

WHEN : "go direction" is entered

THEN : appropriate message is displayed (no door)

Now the “go” command is fully specified and we can move on.

3 Implementation

The next thing we are going to do is to learn how to add commands to your project.

3.1 Adding Your First Command

Let’s look at what it would take to add a new command to our game: the look command. The purpose of look is merely to print out the description of the room and exits again. Let’s start by writing a GWT for it:

LOOK Scenario #1:

GIVEN :

WHEN : "look" is entered

THEN : player’s current location is displayed

Since look is a single word command that always succeeds, this should be the only scenario we need. To get started implementing look, identify all the locations in the code that will need to be changed in

order to add a look command. How many are there? In order to add a look command to your game you need to do the following:

1. Add look as a new command word by adding it to the array of known words in the validCommands array in the CommandWords class. Execute the game and type the command look. What happens?

Name CS117 Project Stage 02: Commands – Page 3

2. Implement an action for the look command by adding a private method in the Game class with the following signature. For now, this method should simply call the printLocationInformation method. We will keep its implementation separate so that we can enhance its functionality later.

1 /∗ ∗ 2 ∗ P r i n t s o u t t h e l o c a t i o n i n f o r m a t i o n . 3 ∗/ 4 private void look()

3. Add a case for the look command in the processCommand method of the Game class that calls the method you wrote in part (2).

4. Test your game and be sure that your new command is complete. One good way to do this is go to back through all of the GTWs that have already been specified and tested and make sure that they all work. When you are sure that it is, commit and push your changes.

3.2 Removing Implicit Coupling

In one of the early labs, you were asked to make improvements to your text adventure game making it possible to add additional directions of movement. The changes you made fixed an example of explicit coupling. The coupling was obvious because of the public fields in the Room class. This code base also has an even worse form of coupling: implicit coupling. Implicit coupling is a situation when one class depends on the internal information of another, but this dependence is not immediately obvious. In our current game, we notice this when we test the getting help scenario. Do you notice that it does not include our newly added look command? We want to fix this now.

Since the CommandWords class is responsible for the command words, it should also be responsible for generating a String containing all the command words that we can then use the Game class. Let’s do this now.

1. Add the following method to the CommandWords class:

1 /∗ ∗ 2 ∗ R e t u r n s a l i s t o f t h e a v a i l a b l e commands , o f t h e f o r m : 3 ∗ Your command w o r d s a r e : 4 ∗ l o o k g o q u i t h e l p 5 ∗ 6 ∗ @ r e t u r n A s t r i n g c o n t a i n i n g t h e l i s t o f a v a i l a b l e commands . 7 ∗/ 8 public static String getCommandString ()

2. In the Game class, when the user asks for help, we should use this new method as part of providing that help.

3.3 Removing String Comparison

To further enhance our project, we would like to remove some of the string comparisons that our game is currently doing. String comparisons are very inefficient and tend to be error-prone as many beginning (and advanced) programmers forget that they cannot use == to compare strings. In order to do this we need to change the CommandWords class where the valid list of commands is stored, and the Game class

Name CS117 Project Stage 02: Commands – Page 4

where the processCommand method explicitly compares each command word. We are going to do this using enumerations.

Start by adding an enumeration to the project called CommandEnum. Your enumeration should include values for each valid command. Include a field for the text (in all lower case) that would be entered by the person playing the game.

Great! Now let’s refactor the game to use this new enumeration:

1. Change the implementation of validCommands from an array of string to define valid commands to a map between strings and CommandEnum objects. This will make it easy to convert the command typed by a user into its corresponding enumerated type value. You should put the commands into the HashMap in the static initializer of the CommandWords class. HINT: You can do this without CommandWords knowing what the commands are.

2. Modify any methods that were using the array to now use the map. Use the compiler to help you identify every place that the validCommands is used.

3. Add a method to the CommandWords class which will convert a String into a CommandEnum object. It should have the following signature:

1 /∗ ∗ 2 ∗ C o n v e r t s a S t r i n g i n t o a CommandEnum o b j e c t . 3 ∗ 4 ∗ @param t h e S t r i n g The S t r i n g c o n t a i n i n g t h e command word . 5 ∗ @ r e t u r n The CommandEnum o b j e c t r e p r e s e n t i n g t h e command , o r n u l l i f

t h e command d o e s n o t e x i s t . 6 ∗/ 7 public static CommandEnum getCommand(String theString)

4. Change the implementation of Command so that the “command word” is now a CommandEnum object instead of a String. You should change the commandWord field, the constructors, and the accessor.

5. In the Reader class, we need to change the implementation of the getCommand method in the Reader to use the CommandEnum instead of a String. Be careful here because word1 is what was entered on the command line and must remain a String. (HINT: Didn’t you write a method that converts a String into a CommandEnum? You have the opportunity to simplify some code here too.)

6. Modify the processCommand method of Game to use a switch command instead of if-else statements.

When you are done, test your program to be sure that it works the same as it did before you started (HINT: the GWTs can help here) and then commit and push your changes. When you do this, make sure that the new CommandEnum.java file gets added to the repository.

3.4 Adding More Commands

All this refactoring has left us in a great place for adding additional commands. We have started you off by providing GWTs that fully specify the behavior each command in a text file in your “documents” folder.1

Implement each of the following commands using the provided GWTs:

1Notice that this is a text file, not a Word document. You can open this file up using gedit on the school machines. Notepad++ is a powerful text editor for Windows which you can download and install for free from https://notepad-plus-plus.org/.

Name CS117 Project Stage 02: Commands – Page 5

Command Description

status Prints out current state of the game including the player’s score, the number of turns that the player has used so far, and the complete description of the current room.

back Takes the player into the previous room he/she was in. To keep it simple, your back command only has to remember the last place the player was, not the entire path the player took through the game. Be sure to think about what happens if the player enters ’back’ more than once or before moving for the first time. HINT: Why not update the previous room whenever the current room is updated?

4 Finishing

When you are ready double check that you have been using good style (HINT: use Checkstyle to help you) and that all the code you have implemented is properly documented. Be sure that all of your changes are commited and pushed to Github.

Instead of uploading an archive of your project, you will be uploading a commit marker called an secure hash algorithm (SHA). Every commit in GitHub has a SHA marker attached to it. When you are happy with your submission, commit and push your changes to GitHub. Go to the GitHub website and check to make sure your last commit has made it to the server. Now copy the commit link by right-clicking on the “Latest commit” and selecting “Copy Link Location” (see figure):

Once you have copied the link, go to the submission page on Moodle and paste it into the sub- mission text area. The link that you get will read something like: https://github.com/kings-cs/ CS117-S16-JumpMaria/commit/2076ab47397891666d11a2474208f24e73fe576d. Don’t forget to “Submit Assignment”.