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

Course Project

This homework will continue to develop the course project, which is the game of Battleship.  We have developed a number of classes so far:

  • Ship (HW J6): Represents a ship, of course.  This can be any size ship, placed anywhere on the board.
  • Cell (HW J6): A cell is a single spot on a board.  Thus, a sample board could have a 15x15 grid of cells.
  • Descriptions (Lab 9): This class allows one to pick the names of their ships.
  • ShipList (HW J7): A list of ships.  For example, each player (human or computer) will have a list of 5 (or so) ships that were placed on the board.
  • Parser (Lab 10): This class reads in commands from the keyboard, and figures out (or 'parses') what the player means by them.
  • AI (HW J8): This class represents the computer player in the game (AI stands for Artificial Intelligence).  It is responsible for making the decisions as to which move to make next.
  • Human (HW J8): A class to represent the player in the game.  This class will be in charge of reading in input from the keyboard as to where to take the next shot, for example

In this homework, you will develop one class:

  • MapPrinter (Lab 11): This allows easy printing of the board to the text-based screen.

We will provide you with one class for this homework:

  • Game: The class with the main() method that will test the MapPrinter class.  It ties together all the other classes.

The remaining assignment will develop the remaining class:

  • Board (HW J9): This class represents the board that players place their ships on, and takes shots on as well.

Objective

In this lab, you will gain experience programming using two-dimensional arrays.  In particular, you will be developing a MapPrinter class, which will print out the Battleship board.  If you need a refresher on 2-D arrays, you may want to look over the lecture notes on arrays, starting at slide 72.

The name of this class should have been BoardPrinter, not MapPrinter.  However, we didn't change that prior to the last lab (Parser.java), and as Parser.java uses this class, we didn't want you to have to go back and have to modify your old code.  So we are stuck with the not-so-appropriate name.

Files

There are a number files that you need to download for this lab.

  • Board.class: This is a version of the Board class that is heavily modified for this lab.  In particular, it will generate the exact same board each time, which should help you with your debugging.  This version also only has five methods, whereas the full Board class (which you will develop in HW J9) will have more.
  • Cell.java: What you developed in HW J6.
  • Ship.class: Essentially the Ship class that you developed in HW J6.  It is modified slightly for this lab, and should not be used for other assignments.  You should use this version rather than your version, even if you are certain that your version works!
  • Game.java: Contains the main() method that you should run to test your MapPrinter class, as well as some constants that you will also need.
  • MapPrinter.java: The skeleton code for this lab.

Note that many of these classes are modified for this lab (in addition to the Board.java file mentioned above).  For example, no Descriptions class is needed, as the Ship class has been modified to not need it.  This was done to lower the number of files needed.

To run this lab, execute the Game.java file.  This file creates a board, and prints it out -- this lab is not interactive. 

Documentation

As with HW J8, 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 Battleship board.  A sample output of the functionality of the MapPrinter class is shown below.

Your board:
 _ _ _ _ _ _ _ _ _ _ _ 2 2 2 _
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ 3
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ X
 1 1 1 _ _ _ _ _ _ _ _ _ _ _ 3
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ X
 _ _ _ _ _ _ _ _ _ S _ _ _ _ _
 _ _ _ _ _ _ _ _ _ S _ _ _ _ _
 _ _ _ _ _ _ _ _ _ _ 4 X 4 4 4
Ship list:
0: the gray Dinghy from Higgin's Moon @ (9,7)
1: the slow Rowboat from Ariel @ (0,5)
2: the yellow Canoe from Osiris @ (11,0)
3: the broken Kayak from Ezra @ (14,3)
4: the green Raft from Miranda @ (10,9)



The computer's board:
 m _ _ _ _ _ _ _ _ _ _ _ _ _ _
 _ _ _ _ _ _ _ m _ _ _ _ _ _ _
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ m
 _ _ _ m _ _ _ _ _ _ _ _ _ _ _
 _ _ _ _ _ _ _ _ m _ _ _ _ _ X
 _ _ _ _ _ _ _ _ _ _ _ _ m _ _
 _ _ _ _ _ _ _ _ m _ _ _ _ _ X
 _ m _ _ _ _ _ _ _ S _ _ _ _ m
 _ _ _ _ m _ m _ _ S _ _ _ _ _
 _ _ _ _ _ _ _ _ _ m _ X _ _ _

Note that the board has a height of 10 and a width of 15.  If yours is reversed (meaning yours has a height of 15 and a width of 10), 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.

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

  • For this lab, it's actually printing out the exact same board, just two views of it.

  • There are two boards views printed: one for you, which shows your ships, and where those ships have been hit.  The other is showing your opponent's board, which shows what shots have hit ('X') and what shots have missed ('m')

  • If a ship is completely sunk, then it prints out 'S' instead of 'X' for each spot in the ship.

  • The ships each have a number, which corresponds to the number on the list of ships after the top board

There are two methods that you will need to develop for this lab, which are contained in the MapPrinter.java skeleton code: printBoardForPlayer() and printBoardForOpponent().  These are described in more detail below.  The first method prints out the top board; the second method prints out the bottom board.  The skeleton code also provides the printShipList() method, which prints out the list of ships.

Board class

The Board class that we provide only contains five methods, as they are the only methods that are needed for this lab; the first two are called in Game.java, and thus you don't need to use them in your MapPrinter class.  The last one is used in the printShipList() method that we provide for you in the MapPrinter skeleton code.  So, really, you only need to use the last two methods.

  • Board (int x, int y): creates a board of the passed size.  This is called in Game.java, and you don't need to use it in your MapPrinter class.

  • void generateRandomBoard (int numberOfShips): this method would normally generate the random board.  For this lab, however, the same board is generated each time, to aid you with debugging.  This is called in Game.java, and you don't need to use it in your MapPrinter class.

  • void printShipList(): this method prints out the ShipList.  Normally, this is done via a call to the print() method in ShipList, but that's been modified for this lab, as we are not using the ShipList class for this lab.

The methods you need to use in your MapPrinter class are:

  • Cell getCellAt (int x, int y): This method will return the Cell at the given (x,y) location.  If the coordinates are outside the board size (i.e. less than zero), then null is returned.

  • int getShipNumber (Ship ship): This method will return the number for the passed ship.  This is used in printBoardForPlayer(), where you need to print out the number of the particular ship so you can tell which ship is where.  These numbers start at 0, and correspond to the numbers printed out via the printShipList() method.

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

MapPrinter class

There are two methods that you need to develop in the MapPrinter class: printBoardForPlayer() and printBoardForOpponent().  The majority of the two methods are the same -- once you have one method written, the other should be very easy.  The only differences between the two methods are:

  • The name of the method, of course.

  • The printBoardForPlayer() method prints the ship list after the board (via the printShipList() method we provide in the skeleton code).

  • The ships are printed (as numbers) in the printBoardForPlayer().

  • Missed shots are printed (as 'm's) in the printBoardForOpponent().

Everything else about the methods is the same -- a 'X' is printed if the spot is a hit, and a 'S' is printed if the spot is a hit and the corresponding ship is sunk.  Note that the title, which is printed at the top of the board, is a parameter, so both methods print out the first parameter before the board is printed.

For the rest of this lab, we will just talk about the printBoardForPlayer() method, and just indicate where a difference occurs with the printBoardForOpponent() method.

The method must have the prototype: public static void printBoardForPlayer (String title, Board board).  The two parameters to the method are the title (which is the first line printed by the method), and the board to be printed.  The method will have three parts: printing out the title, printing out the board, and then printing out the ship list (the last step is not done in printBoardForOpponent()).

For each cell in the board, you need to examine the Cell object that is in that spot in the board (via the getCellAt() method in the Board class).  There are a number of possibilities, which were discussed in HW J6:

  • The spot has not been shot at, and there is no ship there: you print out a '_' for both methods.

  • The spot has not been shot at, and there is a ship there: you either print out a '_' (for printBoardForOpponent()) or a number (for printBoardForPlayer()).  To find the number to print out, you should call the getShipNumber() method in the Board class, passing in the ship as the parameter.

  • The spot has been shot at, and there is nothing there: you print an 'm' for printBoardForOpponent(); printBoardForPlayer() just prints out a '_'.

  • The spot has been hit, and there is a ship there: You should either print out a 'X' if the ship is not sunk (recall the isSunk() method in the Ship class) or a 'S' if the ship is sunk.

You may run into the situation where your program crashes with a NullPointerException.  If you try calling board.getCellAt(x,y).getShipOnCell().isSunk(), and there is no ship on the cell, the first part of that line (board.getCellAt(x,y).getShipOnCell()) will return null; and thus, you are trying to call the isSunk() method on a null reference.  Thus, if there is no ship on the cell, you should not be calling methods from that (non-existant) ship!

Note that it will make for a better looking map if you print a space between each character printed -- this will space out the map a bit left-to-right.  This is totally optional, though.

Where to start

The best way is to build up the methods incrementally.  First get one of the methods working for printing out a '_' for each spot in the board.  Then focus on getting the formatting and shape of the board correct (it should be wide, not tall).  Then start printing out each of the various characters on the board ('m', 'X', 'S', digits) -- add one at a time until it works properly.  Once one method works, copy the body of that method to the other one, and make a few modifications so that the second one works properly.

Submission

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

Have a great Thanksgiving break!

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