In this assignment, you will build a version of the game Bejewelled. Bejewelled is a 'match 3' game, where you must match 3 or more of the same gem by moving the gems on the board. The gems can only move 1 cell up or down, left or right, and swap with neighbouring gem when moving. Upon matching, the gems that match disappear, leaving a gap, and the gems above the gap fall, filling the gap. If you are unfamiliar with the game, you can plan an online version here.
Keep all of your methods short and simple. In a properly-written object-oriented program, the work is distributed among many small methods, which call each other. There are few methods in this entire assignment that should require more than 15 lines of code, not counting comments, blank lines, or {} lines.
Unless specified otherwise, all instance variables must be private, and all methods should be public.
Your assignment should be DRY - don't repeat yourself. If you notice you have code that does the same function in two places, consider making a private method that can be called to do the work. If you see 3 or more lines of code that do the same thing in two different methods, consider making a private method that does that task. This is often called a 'helper method.
We have provided sample test files for each phase to help you see if your code is working according to the assignment specifications. These files are starting points for testing your code. Part of developing your skills as a programmer is to think through additional important test cases and to write your own code to test these cases.
First, create the game board, named class Grid.
The Grid class should have:
To choose random gems, you can add this to your Grid class:
public static char[] gems = {'r', 'g', 'b','y'};
public static char getRandomGem() {
int choice = (int)(Math.random() * gems.length);
return gems[choice];
}
We want to be able to save our progress. To do this, we will save our progress to a file, and be able to read these files.
The save files have a special format. The top line is the dimensions of the saved board: number of rows, then number of columns. The rest of the file is the contents of the board. Example:
2 3
yrb
bry
Is a valid file.
To do this, implement these methods in the Grid class:
Sample output:
yr
by
bb
rr
java.io.IOException: No dimensions to read
java.io.IOException: The size values were not numeric!
java.io.IOException: There was not enough rows! Saw 5 need 10
java.io.IOException: There was not enough colums. Saw 2 need 12
yr
by
These should be the same:
rryryb
yybgbg
yrrbrb
yyryrr
brgbgr
rryryb
yybgbg
yrrbrb
yyryrr
brgbgr
Add the following methods to extract data from your Grid class. You will use these later in the program.
Write a method named static char[] replaceSets(char[] input) in Grid that is passed a 1D array of gems, and checks if there are set of 3 or more gems in a row. Return a new array that has the gems that are in a row replaced with 'x' characters.
We have methods to find if there are sets of gems. Now, write the method replaceAll() in Grid. This method uses the methods created in phase 4 to mark any sets of 3 with x's.
There are some subtleties to this method. Consider:
bbb
bgg
bgg
There is a set of 3 in both the first row, and first column. If you set the first row to all x's, then check the column, then column 0 would be xbb, and the program would not set column 0 to all xs. A solution to this is to create a new 2D array with the sets replaced by xs, while looking at the original to see if there are sets to be replaced.
Create method boolean drop() in class Grid. This method 'drops' the gems that are above cells that have an x in them. In Bejewelled, as gems disappear, the gems above them drop down. This method does the dropping step. The drop method returns true if any gems have moved.
In any spots that are now empty, place random gems. This will be the gems that are 'falling from the top'.
Create 4 public static final variables in class Grid: UP, DOWN, LEFT, and RIGHT. You can set these to any numbers you like but they all must be different numbers.
Create the method void swap(int row, int col, int direction). This will swap the gem specified by row and column (indexed at 0) in the direction specified. Throw appropriate exceptions for out-of-bounds gem selection, and movement. Throw IndexOutOfBoundsException for any strange things that may happen.
+10%: In Bejewelled, moves are only allowed if it causes a match. Update the game to enforce that rule.
+20%: The game is over when there are no more moves. Update the game, and TestPhase7b.java to enforce this. Visit every gem, and see if it can move up/down/left/right. Continue the game if there is at least 1 valid move left.