
run() methodMineSweeper OnlineThe rules of the game are fairly simple. It is a one-player game in which the player is shown initially a blank board of square cells:
MineSweeperApp/res/raw/. Separately, save in the same folder all smiley images (right-click, Save As):
| mine images | smiley images |
|---|---|
mines.zip |
|
The game board will be represented as 2D array (table) of integers. Here are the possible values that can be stored in a the 2D array (table) and their corresponding meaningmX.pngwhereXis a number in0..29
| Example Image | Explanation |
|---|---|
![]() m7.png |
0..8 (hidden cells)
these numbers indicate that the cell has 0 to 8 adjacent mines; the cell has not been revealed to the player
these fuzzy images are used for testing; in the final version we draw hidden.png
|
![]() m17.png |
10..18 (revealed cells)
these numbers indicate that the cell has been revealed; the corresponding image is shown to the player
|
![]() m27.png |
20..28 (flagged cells)
these numbers indicate that the cell has been flagged; the image of a flag is shown to the player
|
m9.png |
9, 19, 29 (mine cells)
these numbers indicate a hidden mine (9) a revealed mine (19) and a flagged mine (29)
|
![]() hidden.png |
this image is displayed in the final version of the game for cells with numbers 0..9 instead of the fuzzy images |
0..9. The cells will be drawn as fuzzy images to make it possible to test the game.0..9 will change it to 20..29, respectively. The first digit (2) tells us that this is a flagged cell and the second digit tells us how many mines there were originally.20..29 will change it back to 0..9, respectively. The player changed their mind and the cell is again blank/hidden.0..9 will change it to 10..19, respectively. The first digit (1) tells us that this cell has been opened and the second digit tells us how many adjacent mines it has. Once it has been opened a cell does not respond to taps.m0.png, m1.png, ..., m29.png and correspond to the cell numbers above.m10.png, ..., m29.png and draw hidden.png for cells with values 0..9plantMines( field )
This method updates/modifies the given mine field by planting mines. You may assume that the given field will always be blank, i.e. will contain only 0 in each cell.
The method works by going through all cells of the given field and placing a 9 in a cell with probability of 20% (otherwise, it keeps the cell as is).
To get a probability of 20%, pick a random number from 1 to 10 and only place a mine if the number is at most 2. For example:
int[][] field = new int[6][7]; plantMines( field ); printTable( field ); // displays a table that has approximately 8 cells that are set to 9 // the 8 comes from the fact that of the 6*7=42 total cells 20% is 0.2*42 ~ 8 // // each time it is run the result will be different
setFlag( field, row, col )
This method places or removes a flag at the cell with the given row and column. Specifically:
int[][] field = {
{ 9, 9, 2, 1, 0 },
{ 3, 4, 9, 2, 1 },
{ 9, 12, 1, 3, 9 },
{ 1, 1, 0, 2, 9 } };
setFlag( field, 0, 1 ); // put a flag: 9 became 29
setFlag( field, 3, 2 ); // put a flag: 0 became 20
setFlag( field, 1, 1 ); // put a flag: 4 become 24
setFlag( field, 2, 1 ); // no change -- hit on 12
printTable( field ); // displays
// 9 29 2 1 0
// 3 24 9 2 1
// 9 12 1 3 9
// 1 1 20 2 9
setFlag( field, 0, 1 ); // removed a flag: 29 became 9
setFlag( field, 1, 1 ); // removed a flag: 24 became 4
printTable( field ); // displays
// 9 9 2 1 0
// 3 4 9 2 1
// 9 12 1 3 9
// 1 1 20 2 9
isCleared( field )
This method determines if the field is cleared (all cells revealed and all mines flagged).
// field not cleared -- has mines (9s), has hidden cells (1s, 2s, ...), has incorrect flags (23, 24) int[][] field = { { 9, 29, 2, 1, 20 }, {23, 24, 9, 12, 1 }, { 9, 12, 11, 13, 9 }, { 1, 11, 10, 12, 9 } }; System.out.println( "is field cleared: " + isCleared( field ) ); // displays false // field not cleared -- has incorrect flags (23, 24) int[][] field = { {29, 29, 12, 11, 10 }, {23, 24, 29, 12, 11 }, {29, 12, 11, 13, 29 }, {21, 11, 10, 12, 29 } }; System.out.println( "is field cleared: " + isCleared( field ) ); // displays false // cleared field -- only mine flags and no hidden cells int[][] field = { {29, 29, 12, 11, 10 }, {13, 14, 29, 12, 11 }, {29, 12, 11, 13, 29 }, {11, 11, 10, 12, 29 } }; System.out.println( "is field cleared: " + isCleared( field ) ); // displays true
openMines( field )
This method updates the given mine field by revealing all cells that contain mines, i.e. it replaces all 9's to 19's.
This is used when the player lost the game by opening a cell with a mine.
int[][] field = {
{ 9, 9, 2, 1, 0 },
{ 3, 4, 9, 2, 1 },
{ 9, 2, 1, 3, 9 },
{ 1, 1, 0, 2, 9 } };
openMines( field );
printTable( field ); // displays
// 19 19 2 1 0
// 3 4 19 2 1
// 19 2 1 3 19
// 1 1 0 2 19
isValid( field, row, col )
This method determines whether the given location (row,col) is valid within the field.
int[][] field = new int[6][7];
System.out.println("Is (3, 4) valid: " + isValid( field, 3, 4 )); // displays true
System.out.println("Is (7, 0) valid: " + isValid( field, 7, 0 )); // displays false
System.out.println("Is (?, ?) valid: " + isValid( field, ?, ? )); // displays false
System.out.println("Is (?, ?) valid: " + isValid( field, ?, ? )); // displays false
Try several invalid locations. There are many possibilities (some non-obvious). The good news is that if the program crashes, it will indicate the bad index, which will give you a hint about what you missed.
countMines( field, row, col )
This method counts how many mines are around (immediately adjacent to) the cell with the given row and column.
The cell is assumed to not contain a mine which is ensured by method updateField.
Use method isValid to check if the neighbor actually exists. Remember that && stops as soon as it encounters false.
Initially, you could write this as 8 if-statements that probe around the given location.
Eventually write it with a pair nested loop that examines the 3x3 region around the cell. It will be fine to go through the given cell, since it is assumed to not be a mine.
int[][] field = {
{ 9, 9, 0, 0, 0 },
{ 0, 0, 9, 0, 0 },
{ 9, 0, 0, 0, 9 },
{ 0, 0, 0, 0, 9 } };
int mines = countMines( field, 1, 1 );
System.out.println( "mines around cell (1,1): " + mines); // displays 4
int mines = countMines( field, 0, 4 );
System.out.println( "mines around cell (0,4): " + mines); // displays 0
updateField( field )
This method updates/modifies the given mine field by recording, for each non-mine cell, the number of mines that are adjacent to that cell (i.e. counts the number of immediate neighbors that contain 9).
This method should ignore (do nothing for) the mine cells. (Hint: Use method countMines for each cell).
int[][] field = {
{ 9, 9, 0, 0, 0 },
{ 0, 0, 9, 0, 0 },
{ 9, 0, 0, 0, 9 },
{ 0, 0, 0, 0, 9 } };
updateField( field );
printTable( field ); // displays
// 9 9 2 1 0
// 3 4 9 2 1
// 9 2 1 3 9
// 1 1 0 2 9
generateField( rows, cols )
This method builds a mine field with the given dimensions, plants mines and calculates the values for the cells adjacent to the mines. This is a simple method that uses other methods that have already been written (no loops).
int[][] field = generateField( 4, 5 );
printTable( field ); // displays different 4x5 fields each time
// but they should look correct; for example:
// 9 9 2 1 0
// 3 4 9 2 1
// 9 2 1 3 9
// 1 1 0 2 9
openCell( field, row, col )
This method reveals the cell with the given row and column (assumed to not be a mine), i.e. the method changes a cell from 0..8 to 10..18.
In addition, if the cell is empty (0), its non-revealed 8 neighbors (i.e. 0..8) are also revealed (ideally, more of the field will be revealed, but this will be done in future assignment).
If a cell/neighbor has already been revealed, it is ignored.
int[][] field = {
{ 9, 9, 2, 1, 0 },
{ 3, 4, 9, 2, 1 },
{ 9, 2, 1, 3, 9 },
{ 1, 1, 0, 2, 9 } };
openCell( field, 1, 3 );
printTable( field ); // displays [the ~ are put for emphasis, not shown]
// 9 9 2 1 0
// 3 4 9 ~12~ 1 2 became 12
// 9 2 1 3 9
// 1 1 0 2 9
openCell( field, 0, 4 );
printTable( field ); // displays [the ~ are put for emphasis, not shown]
// 9 9 2 ~11 10~ 1 became 11
// 3 4 9 ~12 11~ 12 is unchanged
// 9 2 1 3 9
// 1 1 0 2 9
openCell( field, 0, 3 );
printTable( field ); // displays: no change, cell 11
// in top row already revealed
drawCell(x, y, value)
This method draws an image centered at the given (x,y) that corresponds to the value of the given cell 0..29. No loop and no if.
drawField( field, startX, startY )
This method draws the given mine field such that the upper-left square is at the given coordinates. You may use 36 as a fixed number for the dimensions of the images.
At his point draw the images for all cell numbers. In the final version cells with numbers 0..9 will be drawn as "hidden.png".
|
|
playGame( )
This is the method that runs the game:
void playGame( )
{
// setup dimensions of the board
int rows = 8; // later pick a random number in [7..10]
int cols = 7; // later pick a random number in [6..8]
// calculate the center (x,y) coordinates of the upper-left square, so that the
// board is centered on the screen; you may use 36 as fixed number for image size
double startX = initially could use 50, but eventually should be computed
double startY = initially could use 50, but eventually should be computed
// any initial setup (for example, a boolean to keep track if mine tapped)
// as long as game is not over:
// show board, wait for touch, ...
// given formulas that use touch Y, X to compute cell R, C:
int cellRow = (int) ((touch.getY() - (startY - imageSize/2)) / imageSize);
int cellCol = (int) ((touch.getX() - (startX - imageSize/2)) / imageSize);
// update board on single/double tap
// any final actions
}
cs111 (where you run DrJava) hw/MineSweeperApp/src/cs1/MineSweeperApp (this is where your code is saved) MineSweeperApp.java and MineSweeperApp.log (ignore the other files)