Extension 5.4: Memory Matching¶
Description¶
Your goal in this extension is to create a memory matching game using StdDraw
and your growing computer science knowledge. If you’ve never played a memory matching game before, you can try this version to get the general idea. Additionally, you can find a video demoing a solution here.
In this extension, you are going to create a matching game that uses colors rather than images. Generating a 4x4 board with randomly arranged tiles can be a bit daunting. We will guide you through writing a few helper methods first to perhaps inspire a solution.
Procedure¶
MemoryMatchBoard¶
Inspect
getPalette()
.We have provided you with an array of colors which should be more discernible to those who are color-blind. You are free to change the Colors if you would like to. If you choose to do so, why not make your application available to more people? There are plenty of resources on the web to help select a more inclusive palette.
Complete
swap(board, aRow, aCol, bRow, bCol)
Note: this method should be written to be generally useful. Therefore it should not assume a 4x4 board nor that it is filled with the colors from
getPalette()
. Honestly, it should not need to. You may assume that aRow, aCol, bRow, bCol are all on the board.Open
MemoryMatchTestSuite.java
and Run it as a JUnit Test.Examine the results of the test cases. * Update your
swap()
method until it passes all of theSwapTestSuite
cases ofMemoryMatchTestSuite
and you are happy with its clarity.Complete
shuffle(board)
Note: this method should be written to be generally useful. Therefore it should not assume a 4x4 board nor that it is filled with the colors from
getPalette()
. Honestly, it should not need to.Question: What amount of shuffling is necessary for a memory match game?
Run
MemoryMatchTestSuite.java
as a JUnit Test until you have passed all of theShuffleTestSuite
cases.Note: One should never completely rely on the results of test cases. It would be especially perilous here. The threshold for passing these tests are much lower than what a human would likely consider “good enough” for a memory match game. Be sure to strive for the human’s satisfaction and not just the TestSuite’s passing.
Complete
generateShuffled4x4Board(palette)
Question: How will you create and fill a 4x4 2D array with each of the contents of the 8 long 1D palette array twice?
Question: How will you shuffle it into a random order?
Run
MemoryMatchTestSuite.java
as a JUnit Test until you have passed all of theGenerateBoardTestSuite
cases.
MemoryMatchGame¶
Note the declaration of
X
andY
.
private static final int X = 0;
private static final int Y = 1;
Use these to index the X and Y coordinates of the points represented as double arrays of length 2 in this extension.
Investigate and possibly edit
defineWorldBoundaries()
How you define the world can often make problems easier or harder. By default StdDraw’s world is from (0.0, 0.0) in the bottom left hand corner to (1.0, 1.0) in the top right corner. You can either leave it this way, or elect to modify xMin, xMax, yMin, and yMax. Either way, you will need to:
convert the reported mouse position in the world space into the correct row and column of the board, and
convert the cells at particular rows and columns into the world space to draw them.
No matter what you choose, be sure to be consistent throughout the code.
Complete
waitForMouseClick()
The code to wait for the mouse to be presses and released has been provided. Complete this method by returning a created an array of length 2 with the array item at the X index assigned to StdDraw.mouseX() and the array item at the Y index assigned to StdDraw.mouseY().
private static double[] waitForMouseClick() {
// wait for the mouse to be pressed
while (!StdDraw.isMousePressed()) {
StdDraw.pause(10);
}
// wait for the mouse to be released
while (StdDraw.isMousePressed()) {
StdDraw.pause(10);
}
// TODO: return the current mouse position
// Delete the line below and implement this method
throw new NotYetImplementedException();
}
Complete
toRow(xy)
Based on how you have defined your world boundaries, map the
y
of xy into the appropriate row of the board.Complete
toColumn(xy)
Based on how you have defined your world boundaries, map the
x
of xy into the appropriate column of the board.Investigate
waitForClickOnRowColumn()
private static int[] waitForClickOnRowColumn() {
double[] xy = waitForMouseClick();
int r = toRow(xy);
int c = toColumn(xy);
return new int[] { r, c };
}
Complete
drawBoard(Color[][] board, ???)
You will find the beginnings of a drawBoard method. You will undoubtedly need additional parameters.
Consider implementing a method isGameStillAlive which takes whatever parameters are necessary and returns a true or false based on whether or not the game is still alive.
Note: often it is better to pull functionality like this out into its own method. It makes the looping in methods like the upcoming
playGame
method cleaner.Complete
playGame()
Tiles should start out hidden and should reveal their concealed color when clicked. When a single tile is clicked, it should remain visible until a second is selected. If that second selected tile does not conceal the same color as the first tile then, after a reasonable delay, both tiles should revert to hidden. If the second tile is the same color as the first tile, then both tiles can either remain flipped or simply disappear. The process then repeats.
The game must keep track of score. You can do this by either counting the number of clicks it takes before the full board is revealed or timing it. Once the game is over, the score should be displayed on the
StdDraw
canvas somewhere.