COMP 110 Summer 2012

Program 4 Method Guide

Below are some in-depth explanations of the methods you need to implement and how you should go about it.

displayHit

Your displayHit method should probably call the other displayHit method that is already implemented. This other method takes 4 paremeters:

The method you're writing takes in one paremeter: Graphics g. The only thing your method needs to do is call the existing displayHit, passing it this g, along with the correct color and xSquare and ySquare locations. The correct square locations are given in the preconditions. To get the color, call the method getColor, passing it these square locations as well. (If you haven't yet implemented getColor yourself, my placeholder code will have it always return Color.WHITE).

Note: ySquare is the row of the square, and xSquare is the column of the square. Be careful what order you pass them to other methods, so you don't do it backwards. You can check the method you're calling to see in what order it wants the row/column given.

getIconDisplayXLocation and getIconDisplayYLocation

These methods don't need to call any other methods at all. Their job is to take a parameter that is either the row or the column of a square and to return the pixel coordinate at the top or left of a circle centered in the row or column given. The range for this input parameter is [0,SQUARES). That is, since SQUARES is 4 for this program, the values could be 0, 1, 2, or 3. Your output (i.e., the thing you return) will be some pixel coordinates. The range of pixel coordinates is [0,BOARD_SIZE_PIXELS]. So, in this example, between 0 and 400, inclusive, because that's how many pixels there are on the game board in one direction. It may help to know that the variable squareWidth already contains the height and width of a single game square and CIRCLE_WIDTH already contains the diameter of the circle.

Look at the diagram of the game board given on the assignment page, and try to do the math yourself an paper for various input values. Once you can do the math yourself, you can teach your method to do it.

buildBoard

There are two 2D arrays that are declared as instance variables: gameBoard and gameBoardCorrect. This method needs to create new arrays to store in these variables. Each of these arrays represents the game board, so each array element will correspond to a square in the game board. So, since the game board has SQUARES rows and SQUARES columns, each of the arrays must have that same size.

You'll have to loop through all the elements in the arrays, initializing them. For gameBoardCorrect, the values should all be set to false. For gameBoard, the values should be integers that will each represent a color. Since we are playing Memory, each number (and thus each color) should appear exactly twice in the array. Since there are SQUARES rows and SQUARES columns on the board (and in the array), there are a total of SQUARES*SQUARES squares on the board. Since numbers appear two times, there will be half that many unique integers (i.e., (SQUARES*SQUARES/2)). Or in our case, 4*4/2 = 8, so 8 unique colors. So, you should put the numbers from 0 to one less than the number of colors into the array, twice each.

This method won't need to call any other methods. It only needs to create and store the two arrays, then initialize them correctly.

getColor

This method doesn't need to call any other methods. You are free to map the row and column of a square to a color in any way you want, but the COLOR_MAP array already in the code provides an easy way.

3 If you set each integer i in gameBoard so that 0 <= i < the number of colors (as suggested above), then you can use i as the index of the color you want from the COLOR_MAP array. You would have to get the integer i from gameBoard using the row and col parameters.

swapSquares

This method doesn't need to call any other methods. It takes in the row and column of two game squares. You need to switch the values (in gameBoard) of the first square (which is in row row1 and column col1) and the second square (which is in row row2 and column col2).

There is an example of a method that swaps two array values in ArrayUtils.java, which was part of the posted solution to Lab 8. The swap method in that file differs in two key ways:

randomizeBoard

This method needs to randomize the game board by shuffling the integers in gameBoard around (without changing the numbers themselves. You will probably want to use your swapSquares method here.

One algorithm for randomizing the board is:

  1. Pick a random row number, and call it row1
  2. Pick a random column number, and call it col1
  3. Pick a random row number, and call it row2
  4. Pick a random column number, and call it col2
  5. Swap the integer in the squares at the row and column (row1,col1) with the one in row and column (row2,col2). (Use swapSquares for this swap.)
  6. Repeat, until we've done many swaps (e.g., 50 or so should be plenty).

updateSquareTracking

The given post-condition for this method is: "The value in xCurrentSquare is put into xLastSquare, and the value in xMouseSquare is put into xCurrentSquare. The same go for y." That's all this method is doing — storing the values of some variables into other variables. You won't need to call any methods in this class or do anything more complicated than simple assignment statements.

wipeIncorrectSquares

This method is responsible for clearing the circles that were drawn, if the player has guessed wrong (though this method doesn't need to check any of that game logic — it just needs to clear the squares when it's called).

There are several ways you could clear things that were drawn on the Graphics object g. The easiest might be to just draw over the thing you want to wipe. So, for example, since the game uses displayHit to draw the circles in the first place, you can call displayHit again (the one that was given, not the one you wrote) to erase them, as long as the color you give it that it should use to draw the circle is BACKGROUND_COLOR. Doing so will draw another circle the same color as the background, clearing the dot.

You will need to clear two squares in this way (because there are two squares guessed in a turn). The row and column of the first square guessed are yLastSquare and xLastSquare. The row and column of the second square guessed are yCurrentSquare and xCurrentSquare. (Note that the variables that start with y are the rows.)

isCorrectMatch

This method doesn't need to call any other methods. It only needs to compare the colors of the two squares clicked to see if they match. For the colors to match, the integers in gameBoard that correspond to the two squares have to be equal.

The row and column of the first square guessed are yLastSquare and xLastSquare. The row and column of the second square guessed are yCurrentSquare and xCurrentSquare.

So if the integer in gameBoard at row and column (yLastSquare,xLastSquare) is equal to the one in gameBoard at row and column (yCurrentSquare,xCurrentSquare), you should return true. Otherwise, you should return false.

markSquaresAsCorrect

Note that you should not use the paremeter Graphics g for anything. It was included erroneously.

The row and column of the first square guessed are yLastSquare and xLastSquare. The row and column of the second square guessed are yCurrentSquare and xCurrentSquare.

The only thing this method should to is set the boolean values in the gameBoardCorrect array at those locations to true. There is no need to call other methods — there is nothing else to do in this method.

legalSquare

This method won't need to call other methods. It needs to return true if the square clicked is legal according to the game rules and false otherwise. The rules are:

  1. If the square has already been correctly matched, it is illegal.

    You can tell if a square has been correctly matched by looking at the square's element in gameBoardCorrect (i.e., the element at the row and column that match the square). If the square has been correctly matched, the element there will be true, otherwise, it will be false. The row and column of the square you should be looking in are given by the variables yMouseSquare and xMouseSquare.

  2. If one square has already been chosen (i.e., we are in the second part of the turn) and the player has clicked on the same square he or she chose in the first part of the turn, it is illegal.

    You can read the variable firstPartOfTurn to see if we are in the first or second part of the turn. It will be true in the first part of the turn and false in the second part of the turn.

    The row and column of the square the user has just clicked (i.e., the one that we're checking the legality of) are yMouseSquare and xMouseSquare. The row and column of the square the player clicked in the first part of the turn will be yCurrentSquare and xCurrentSquare. Note that here we're not checking to see if the colors are the same — we're checking to see if they are actually the same exact square: the rows are the same, and the columns are the same.

  3. Otherwise, the square is a legal choice.

    So you can just return true.

totallySolved

This method won't need to call any other methods. It should return true if and only if every element in the array gameBoardCorrect is true.

The most straightforward way to do this check is to loop through all the elements in the array (and it's 2D, so you probably want nested loops). If you find an element that is false, then that means they're not all true, so you can immediately return false (indicating that the board is not totally solved).

If, however, you manage to get all the way through the loop(s), having checked all the elements and found none that are false, you know that the board is totally solved, and you can return true.

wipeBoard

This method needs to clear the entire board. We can reuse an idea from wipeIncorrectSquares, where we draw over the things we want to clear with something that is the same color as the background.

So, you could set the drawing color to BACKGROUND_COLOR, then draw a big rectangle that's the size of the whole board: I.e., starts at (0,0) and has height and width of BOARD_SIZE_PIXELS.

Then, to draw the white border around the game squares, you can call displayGame.