ulrail.gif

Lab 11: 2-D Arrays

  ur-2c.gif urrail.gif
blrail-nonavbar.gif

Home | Resources | Homeworks | Exams
Lectures | Labs | Contacts | Submit | TAs

br-2a.gif   br-2c.gif brrail.gif
spacer.gif spacer.gif

Objective

This homework will continue to develop the course project, which is the Oregon Trail game.  In this lab, you will develop the MapPrinter class, which will print out the 2-D grid of the Map to the screen.

Files

There are a number files that you need to download for this lab.  Note that these files are stripped-down versions of what you have implemented in previous assignments.  Their purpose here is just to allow you to compile and run the MapPrinter class.

We are not providing any skeleton code for MapPrinter.java, which is what you need to implement.  Note that many of these classes are modified for this lab -- this was done to lower the number of files needed.  To run this lab, execute the Game.java file.  This file creates a map, and prints it out three times; this lab is not interactive. 

Documentation

As with all the course project classes, the documentation for the various parts of this project, including the MapPrinter class, can be found here.

MapPrinter class overview

In this lab, you will be developing a MapPrinter class, which will print out two views the game map (note that the output below has three map printing calls -- the first and the third are the same).  A sample output of the functionality of the MapPrinter class is shown below.

Test of the MapPrinter class

A call to MapPrinter.printMap():
The 'verse map
F


                                 .
                              |  |
                           ^  |  .d
                        |  |  ^  X
                     .  .  ^  .  Sd


A call to MapPrinter.printMap(true):
The 'verse map
F  .  |d .  |  .d .  .  ^  |  .  .
.  ^  .  .  .  ^  .  .  .  .  .  ^
.  .  ^  .  |  ^  .  .  .  .  ^  .
.d ^d |d |  |  .  .  ^  .  .  .  .
|  .  .  ^  ^  .  |  .  .  ^  |  |
.  .  .  |  |  |  .  .  .  ^  |  .d
|d |  .  |d .  |  |  .  |  |  ^  X
.  .  .  |  ^  |  |  .  .  ^  .  Sd


A call to MapPrinter.printMap(false):
The 'verse map
F


                                 .
                              |  |
                           ^  |  .d
                        |  |  ^  X
                     .  .  ^  .  Sd

Note that the map has a height of 8 and a width of 12.  If yours is reversed (meaning yours has a height of 12 and a width of 8), then something is wrong.  The exact formatting of your map can vary a bit -- as long as it prints out the correct dimensions and the correct data for each spot.  The characters in the map all have a specific meaning.  Each location has a single character to define it:

  • A period ('.') means grassland
  • A vertical bar ('|') means forest
  • A caret ('^') means mountain
  • 'S' is the starting location
  • 'F' is the finish (in the upper-left of the map)
  • 'X' is where the player is currently

Furthermore, a 'd' next to the location means that there is a depot at that Location.

There are a number of things going on in this output:

  • For this lab, it's printing out multiple views of the exact same map -- note that the first and third map are the exact same.  The code has been set up to always print the same map (and, thus, yours should look the same or very similar).  In the full version of the game, it will generate a different map each time it is printed.
  • There are two maps views printed: one for the player, which shows what parts of the map s/he has traveled to (the first and third maps), and the other that shows the entire map.
  • There are two depots shown in the first and third map -- above and below the player (the player is marked by an 'X').  There are 9 depots in the second map.
  • Location (0,0) is in the upper-left of the screen, (7,0) is the lower-right, (0,11) is the upper right, and (7,11) is the lower-left.  We realize that this is probably backwards, but that's how the rest of the code works...

There are three methods that you will need to develop for this lab, all of which should be in the MapPrinter.java class: two versions of printMap(), as well as one other method called getTerrainCharacter().  Both of the printMap() methods are public, the other method is privateAll these methods must be static!  These methods are explained in more detail below.

Map class

The Map class that we provide only contains four methods, as they are the only methods that are needed for this lab; the first one is called in Game.java, and thus you don't need to use it in your MapPrinter class.

  • void populate(): This method fills the Map with Location objects and Depots.  It's called in Game.java, and thus does not need to be called by your code.
  • int getNumCols(): This method returns the width of the Map.  You must use this method call, not Game.BOARD_WIDTH, to determine the map width in your code!
  • int getNumRows(): This method returns the height of the Map.  You must use this method call, not Game.BOARD_HEIGHT, to determine the map height in your code!
  • Location getLocationAt (int row, int col): This method will return the Location object at the passed coordinates.  Note that the row is passed in as the first parameter.  Thus, location (0,0) is in the upper-left of the screen, (7,0) is the lower-right, (0,11) is the upper right, and (7,11) is the lower-left.  If an invalid value is passed to this method, it will print an error message and exit.

Note that normally, to get an element out of a 2-D array, you have code similar to: map[3][4].  In this lab, you have to use Game.map.getLocationAt(3,4) instead.  The idea is the same, but you are using the accessor method to get the Location object rather than indexing the array directly.  The reason is that the 2-D array is a private part of the Map class, and the getLocationAt() method allows one to get a individual Location from that private array.  So you are still accessing a 2-D array, but indirectly.

MapPrinter class

There are three methods that you need to develop in the MapPrinter class: two versions of printMap(), as well as one other method called getTerrainCharacter().

The Map as printed has the concept of visibility.  The parts of the map that the player has traveled to are visible.  Furthermore, the player is assumed to be able to see a square or two beyond those squares that s/he has traveled to.  Thus, some of the map will be visible, and some of the map will not be visible.  The finish location is always visible.

static char getTerrainCharacter (int terrainType)

This method will return one of the three terrain characters for the map.  The parameter passed in is one of the Game constants (Game.TERRAIN_GRASSLAND, Game.TERRAIN_FOREST, or Game.TERRAIN_MOUNTAIN).  This method will return '.' (a period) as the character for grassland, '|' (a vertical bar) as the character for a forest, and '^' (a caret) as the character for a mountain.  If the parameter passed in is not one of these three, then ' ' (a space) should be returned.

static void printMap (boolean showAll)

This method will first print out the map title (via Descriptions.getMapTitle()), and then go through every column in every row, and print out a 3-character String for each Location at the given row, column coordinates.  Note that it MUST print a 3 character String -- otherwise, your map printout will not line up.  The third parameter to the method is whether to show all of the map (if showAll is true), or just the parts that are visible to the player (if showAll is false).  Recall that you can use the Game.map.getLocationAt() method to obtain the Location at a given coordinate.

The method will print out the following for each square:

  1. If the square is the finish location, then the method will just print "F", regardless of the terrain type.  The finish location is (Game.FINISH_ROW_COORD, Game.FINISH_COL_COORD).  This location is shown regardless of whether it is visible or not, as the player needs to know where to travel to.
  2. If showAll is false (meaning the non-visible part of the map is hidden), then this method will just print a space if that location is not visible.  To tell if a Location is visible, you can use the getIsVisited() method in the Location class.
  3. If the square is the same as the player's current location, then an 'X' is printed, regardless of the terrain type.  The player's location can be found by Game.player.getLocation().
  4. If the location is the start location (which is (Game.START_ROW_COORD, Game.START_COL_COORD)), then 'S' is printed, regardless of the terrain type.
  5. If none of the above are true, then the character representing the terrain type (obtained via the getTerrainCharacter() method, above) is printed.
  6. In the previous 3 cases (steps 3-5), if a depot is present, then a 'd' should be printed right next to the character representing the square.  A 'd' is not printed in the first two cases (when you reach the finish square, the game ends, so there is no need for a depot there; and if a location is not visible, then the player should not know if there is a depot present).

There will be times when there are multiple letters to print, in particular if the player is at the start location.  In this case, your code can print either 'X' or 'S'.  In al cases, enough spaces should be added to make the printed string be EXACTLY 3 characters long (so the map will line up properly). 

This method will be the hardest to develop.  Thus, we have a few hints as to how and where to start.  Consider the first and third map printed by the output:

The 'verse map
F


                                 .
                              |  |
                           ^  |  .d
                        |  |  ^  X
                     .  .  ^  .  Sd

The map above is color coded as follows:

  1. The red F indicates the finish spot, which is step 1 above
  2. The blank spaces are from step 2, above
  3. The orange X is the player's current position from step 3 above
  4. The green S is the starting location, from step 4 above
  5. The blue characters are the terrain type (as obtained from getTerrainCharacter()) from step 5 above
  6. The purple d characters are the depots from step 6 above

Where to start: This method will most likely be a long if-else-if clause inside nested for loops.  First, create the for loops, and print any character (such as a dash ('-')) for each square, regardless of what it is.  Assure that the map is 12 spots wide by 8 spots tall.  Then, implement each of the 6 steps above one at a time, making sure that the output above is correct for that step.  If you don't do this sort of incremental development, your lab will take much longer to develop.  You can also verify all of this from the second map printed as well.

static void printMap()

This method is just a convenience method -- it's easier to call this version without supplying a parameter for showAll.  It calls the previous version of the printMap() method, using the value of Game.cheatModeEnabled as the parameter.  Thus, if cheat mode is enabled (i.e. Game.cheatModeEnabled is true), then the showAll parameter will be true, and the entire map will be printed.  Likewise, if Game.cheatModeEnabled is false, then only the visible parts of the map will be printed.  This version of the method can be done in one line.

Submission

When you are finished, you just need to submit the MapPrinter.java file.  As the other java files were not modified, they do not need to be submitted.

You can use any remaining time to work on HW 9.

spacer.gif
spacer.gif footer-middle.gif spacer.gif