15-110 FALL 2009 (CORTINA)

PROGRAM 9 - due Monday, November 16, 2009 by 11:59PM

Electronic handin will be available after 5PM on Thursday.

In the game of Lights Out, the player gets a random square grid of lights with some on and some off. When the player clicks on a light, if it is on, it turns off, or if it is off, it turns on. In addition, its neighbors (to the left, to the right, above and below) do the same. Of course, some lights don't have all four of these neighbors.

In this assignment, you will implement the Lights Out game using two-dimensional arrays.

Assignment

DOWNLOAD THE FOLLOWING JAVA PROJECT: LightsOut.zip

This Java project contains the starting code for your Lights Out game.

Location

The Location class represents a two-dimensional coordinate location on a grid. This class has the following methods that you will need:

public Location(int row, int col)
A constructor that creates a new Location with the row and column given in the respective parameters.

public int getRow()
An accessor that returns the row coordinate of this location.

public int getCol()
An accessor that returns the column coordinate of this location.

Color

The Color class is used to represent a color using R,G,B coordinates. (R stands for Red, G stands for Green, and B stands for Blue). Colors are represented by some combination of red, green and blue. Each component can have a value between 0 and 255 (values that can be stored in one byte). Here are some common colors in RGB:

          R     G     B
black     0     0     0
white   255   255   255
red     255     0     0
green     0   255     0
blue      0     0   255
yellow  255   255     0
cyan      0   255   255
magenta 255     0   255
purple  128     0   128
gray    128   128   128
maroon  128     0     0
olive   128   128     0
teal      0   128   128
pink    255   192   203
tan     210   180   140

The Color class has the following method that you will need.

public Color(int r, int g, int b)
A constructor that creates a new Color with the r, g, and b values given in the respective parameters. It is assumed that the r, g, b values are all between 0 and 255, inclusive.

Grid

The Grid class is used to create the display that you will see. The Grid class has the following methods that you will need:

public Grid(int numRows, int numCols)
A constructor that creates a new Grid with the number of rows and columns given in the respective parameters.

public int getNumRows()
An accessor that returns the number of rows in this grid.

public int getNumCols()
An accessor that returns the number of columns in this grid.

public Color setColor(Location l, Color c)
A mutator that sets the color of this grid in location l to color c as given by the parameters.

public Color getColor(Location l)
An accessor that gets the color of this grid in location l.

public int setTitle(String title)
A mutator that displays the title given in the parameter in the title bar for this grid.

public static void pause(int milliseconds)
A method that pauses the display of the grid for the number of milliseconds given in the parameter.

public Location checkLastLocationClicked()
An accessor that returns the last location clicked on this grid by the user. This method returns null if no location has been clicked since the last time this method was called.

public int checkLastKeyPressed()
An accessor that returns the integer code for last key pressed on the keyboard by the user. This method returns 0 if no key has been pressed since the last time this method was called.

Program Requirements

Open the class named LightsOutGame in this project. This class contains your main method to run the game along with additional static methods that you will write to simplify your main method. There are a few static methods already written for you. Follow the instructions below to build your game, step by step.

  1. Write a main method that first asks the user for the size of the game (i.e. the number of rows/columns for the game). The minimum size is 5 (for a 5 × 5 game). If the user enters an integer lower than 5, ask again until the user finally inputs a valid value. Using this size, initialize two variables, one variable for a Grid object that you will use to display the current state of the lights, and one variable for a two-dimensional array of boolean values representing the current state of each light (true will represent "on" and false will represent "off"). The initial values stored in the boolean 2D array should all be false.

    Call the supplied method displayGrid with your grid and 2D boolean array to draw the game display on your screen. Note that this method sets the color of each grid cell (at location i,j) to the color based on the value in your boolean 2D array. If the boolean array value is true (meaning the light is on), the color is set to yellow (255,255,0). If the boolean array value is false (meaning the light is off), the color is set to black (0,0,0).

    Run the program to see if you can get a 5 × 5 grid of lights, all off.

  2. Write a method generateNewGame that takes a boolean 2D array as its parameter and initializes each cell of the 2D array randomly to true or false. The signature for this method is:

    public static void generateNewGame(boolean[][] lightArray)

    Call this method from your main method and then display the grid again. This time you should see a random set of lights turned on. Run the program several times to make sure you get a random set of lights and that your program works correctly for different game sizes besides 5 × 5.

  3. Write a method toggleLights that has the following signature:

    public static void toggleLights(boolean[][] lightArray, int row, int col)

    This method takes the two-dimensional boolean array representing the lights and a row and column and toggles the light in the 2D array at the given row and column. (Toggle means to flip its state from off to on, or on to off.) In addition, this method should toggle this light's neighbors (above, below, left and right). Note that you must check to make sure there is a neighbor in each direction before you toggle it so you don't cause an exception.

  4. In your main method, create a boolean variable gameOver to flag when the game is over. Set this variable initially to false. (When the game is over, you will set it to true.) Now implement the following algorithm:

    While the game is not over, do the following:
        Get the location where the user last clicked on the grid.
        If the user clicked since the last time you checked:
            Get the row and column of this location where the user clicked, and
            toggle the light at this row and column along with its neighbors.
    

    In the algorithm above, call the toggleLights method you wrote to do the work of toggling the light and its neighbors. Test your game now, and you should see a random set of lights first, then as you click, you should see the selected light and its neighbors toggle. Be sure to test the lights around the edge of the game to make sure your program tests for neighbors correctly and does not crash.


    A toggling sequence: clicking the middle cell first, then clicking the top right cell next.

  5. Write a method checkForGameWin that returns true if the user wins the game since all lights are off, or false otherwise. Use the following signature for your method:

    public static boolean checkGameForWin(boolean[][] lightArray)

    This method requires one parameter representing the boolean 2D array that has the current state of the lights.

    Once you have this method done, call this method from your main method after lights are toggled (i.e. inside your game loop) to see if the user wins. Depending on what this method returns, set your boolean variable gameOver to true or false accordingly.

    Now test your program to see if the game ends when you turn off all lights of the grid. A helpful suggestion is to output the statement "YOU WIN!" after your game loop ends so you know the game is over. NOTE: Try to come up with a strategy for winning the game. Are all randomly generated games winnable?

  6. To make the game ending more exciting, write another method toggleAllLights with the following signature:

    public static void toggleAllLights(boolean[][] lightArray)

    This method toggles all of the lights in the given light array.

    If the user wins the game, in your main method call this method twice, pausing 100 milliseconds in between calls to make the grid flash once. Put this code in a loop to make the grid flash the same number of times as the size of the grid. For example, if the grid is 5 × 5, then if the player wins, the grid should flash 5 times.

Developing and Testing your Program

Note how the program is developed. This assignment is meant to show you how to take a problem like this game and break it down into smaller parts, working on simpler parts to build the complex program. As you follow the instructions and test your program at each stage, think about what you've done so far and look at the overall structure of the program. Do NOT write all of the code first and then test it. Most likely, it will not work, and this is not what real programmers do. People who write programs for their job will write in stages as you see here and test as they go along.

Documentation & Programming Style

As usual, your code should be well documented and should demonstrate proper Java formatting style. Be sure to name your variables appropriately and indent properly.

Hand-in Instructions

See the course website for instructions on how to hand in your program. Please zip your project folder that is created in Eclipse. This makes it easier for us to grade your work.

Remember that the work you submit must be your own. Also, late hand-ins are not accepted. Please plan ahead and submit early to avoid server overload at the deadline. The deadline is based on the server's clock, not your clock. Please do not email your code to your instructor or course assistant as your official hand-in; these will not be graded.