CS 61B – Summer 2005 – Project 1
“Minesweeper”
Due: July 5, 2005 11:00am
Overview
This project will give you practice writing and designing classes, methods, and arrays. Additionally, you will have to think through a strategy for testing that your program works correctly. You are to work on this project individually. Your will turn in your project electronically using the “submit” program on the lab machines. Make sure that your code compiles and works correctly on the lab computers. This is especially important if you tend to work from home. Remember: during the summer things move very quickly! Get started on this project as soon as possible. Good luck.
Minesweeper
Minesweeper is a popular (and addictive) game of strategy. You are presented with an NxM grid of squares, each of which starts out covered, or “closed”. You can “open” a square, which will reveal one of two things: a clue, or a bomb. If you uncover a bomb, then alas, you lose the game. If you uncover a square that does not have a bomb under it, then you will see a clue. A clue is an integer between 0 and 8 that represents the number of neighboring squares that contain bombs. Using the information from the clues, you can pick a strategy to uncover as many squares as possible without finding a bomb. You win the game by uncovering all of the non-bomb squares.
As you progress through the game, you will use the clues to predict which squares have the bombs under them. To remember these predictions, you can plant a “flag”. When you plant a flag on a square, you mark that square as a possible bomb square. You cannot open a flagged square. If, later, you decide that a flagged square doesn’t contain a bomb after all, then you can unflag the square. Only when the flag is removed can you then open it (and hopefully avoid a bomb!)
Here is a version of Minesweeper:
Now, we are not covering graphics or graphical user interfaces (GUIs) in this course, so our version of minesweeper will be much more humble. In fact, ours will be entirely text based.
Here is an example of our interface:
> java PlayMines
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
Enter Move
>o3,4
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXX1XXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
Enter Move
>o2,2
XXXXXXXXX
XXXXXXXXX
XX0XXXXXX
XXXX1XXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
Enter Move
We have provided you a “playmine.java” driver file. This file will handle the user input, and will terminate the program when a player loses (or wins). You will be responsible for writing the “Minesweeper” class (located in MineSweeper.java) The Minesweeper class is the brains of the game. It internally stores the board, the locations of the mines, the locations of open squares, and where all the flags are.
PlayMines Class
We have provided you with a class called “PlayMines.java”. Do not edit this file. There is another file called “Move.java” that is also included. Do not edit this file either. The PlayMines class handles the input from the user and terminates the game when it is over. It can be called in a variety of ways:
> java PlayMines
This starts the game with a default sized board (9x9).
> java PlayMines –d
This starts the game in “debug” mode. In debug mode, each time you make a move the driver will also print out the results of your toStringMines() and toStringTiles() methods. These methods are explained in the following section.
> java PlayMines 3 4
This starts the game with a 3x4 board.
> java PlayMines –d 3 4
This starts the game with a 3x4 board in debug mode.
Once you are playing the game, you enter moves by typing a command letter followed by the row number, then a comma, then the column number. For example:
> o3,4
Opens square (3,4).
The commands are:
· o: open a square
· f: puts a flag on a square
· u: removes a flag from a square
· q: quits the game.
Minesweeper class and game logic
We have provided you with a skeleton of the “MineSweeper” class. You are going to fill in each of the methods with your own code to implement the logic of the game. Do not change the names of the methods we provide you, do not remove those methods, and do not change the parameters to those methods either. You may add your own private methods, though, if you find that you would like some additional methods to make your program easier to write. You can add additional fields as well.
Our minesweeper game is represented by a pair of two-dimensional arrays called tiles and mines. Each array contains elements of type int.
Mine array
The mine array holds the positions of mines in your game. Mines are represented by the constant MINE (which happens to be integer 9). So if square (3,4) has a mine in it, then mines[3][4] == MineSweeper.MINE
If a square does not have a mine in it, then it will have a value between 0 and 8, inclusive. This value is called a “Clue”. A clue indicates how many adjacent squares contain bombs. Let’s say that square (2,4) has the value 1 in it. Then that means that there is no bomb in square (2,4), but there is 1 bomb in a square that is adjacent to (2,4).
(i-1,j-1) / (i-1,j) / (i-1,j+1)(i,j-1) / (i,j) / (i,j+1)
(i+1,j-1) / (i+1,j) / (i+1,j+1)
The value of the (i,j) entry of the mine array is:
· MineSweeper.MINE, if mine[i][j] contains a bomb
· c, otherwise
where c ranges between 0 and 8, and is the sum of the number of bombs in mine[i-1][j-1], mine[i-1][j], mine[i-1][j+1], mine[i][j-1], mine[i,j+1], mine[i+1][j-1], mine[i+1][j], mine[i+1][j+1]
Bomb placement
The placeMines() method will randomly put (1 + number of columns * number rows) / DIVISION_FACTOR bombs on your gameboard. It does this by setting the correct number of elements of the mines[][] array to MineSweeper.MINE. We have provided this method for you.
Tile array
The tile[][] array records which squares the player has opened, which are still closed, and which squares contain flags. The tile array is the same size as the mines array and contains integers. The value of a square in the tile array can take one of the following values:
· TILE_OPEN: The square is open.
· TILE_CLOSED: The square is closed.
· TILE_FLAG: The square is flagged.
Displaying the gameboard
When displaying the state of the game to the player, we will make use of the following key for each square on the board:
· X: This square is closed (the tile array value for that square is TILE_CLOSED)
· 0-8: This square is open (the tile array value for that square is TILE_OPEN, and the mines array value for that square is not MineSweeper.MINE)
· F: This square has a flag on it (the tile array value for that square is TILE_FLAG)
· *: This square contains a bomb (the tile array value for that square is TILE_OPEN, and the mines array value for that square is MineSweeper.MINE)
Setting up the gameboard
You will start by setting each element of the tile array to TILE_CLOSED. You will then call the “placeMines()” method we provide for you to place bombs on the mines array. You will then calculate the clue values. The method “initGame()” is where this happens, and we have provided it for you. You will have to fill in the methods that it calls, though.
Gameplay
During the game, the interface we provide you (PlayMines.java) will get moves from the user, and send those moves to you via the markTile() method. The first two parameters to markTile are the row and column the user selected. The third parameter is the type of move: if CMD_OPEN, the user wants to open that square. If CMD_FLAG, the user wants to put a flag on that square, and if CMD_UNFLAG, the user wants to remove the flag.
Note: In the “real” version of MineSweeper, if you open a square with a clue value of TILE_OPEN, then all squares next to that square which also have the value TILE_OPEN are opened as well. For this project you DO NOT have to implement that functionality.
Call graph
The following is a way of visualizing how the different methods interact:
The PlayMines class will make calls to:
· the two constructors
· toStringMines() and toStringTiles() (when debug is turned on, and at the very end of the game if the player loses)
· toStringBoard() each time a move is made
· markTile() when the player makes a move. markTile() is passed the row and column of the move, as well as what type of move it is (open a square, flag a square, or unflag a square).
Project Setup
First, copy the project files into your directory:
> mkdir proj1
> cd proj1
> cp $master/proj/proj1/* .
Compile the two “helper” classes we provide for you;
> javac –g PlayMines.java
> javac –g Move.java
Now you can begin to edit MineSweeper.java and fill in the methods with code as needed.
Part 1: Printing out tile and mine arrays (without clue values) (30% of the points)
For the first part, your MineSweeper class must be able to support the following methods:
toStringMines()
toStringTiles()
toStringBoard()
getBoard()
resetTiles()
If you implement these methods, you will be able to compile your code by saying:
> javac –g MineSweeper.java
and you can run you program by saying:
> java PlayMines –d
This will show you the tiles array, the mines array, and a new gameboard. Here is an example:
> java PlayMines -d
Tiles array:
111111111
111111111
111111111
111111111
111111111
111111111
111111111
111111111
111111111
Mines array:
000000000
000000000
900000000
000000000
000900000
009090009
900000000
009090000
000000000
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
Enter Move
Note that our game doesn’t do much yet, but this is the first step to getting it up and running.
Part 2: Calculating the clues (35% of the points)
For this part, you must implement the “calculateClues()” method. When you do that, you can compile your program (as in part 1), and run it in debug mode. The output should look something like the following (note that the actual bomb positions are random):
> java PlayMines -d
Tiles array:
111111111
111111111
111111111
111111111
111111111
111111111
111111111
111111111
111111111
Mines array:
000000129
001110293
112910292
192110111
111000000
000011100
111019100
192111100
129100000
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
Enter Move
Part 3: Marking tiles (35% of the points)
For this last part, you have to handle moves from the user. This involves implementing the remaining methods:
getMines()
getTiles()
markTile()
Important: For markTile(), if they open a square containing a bomb then you should set the game_state boolean variable to false and simply return from the method. When they open a non-bomb square, make sure to increment the numTilesOpen variable by using the line:
numTilesOpen++;
Once these methods are implemented, then you can interact with the game as described at the beginning of this document.
Submitting your solution
Make sure that your program compiles and runs on the lab machines. Change into your project 1 directory:
> cd
> cd proj1
Make sure that Move.java, PlayMines.java, and MineSweeper.java are in this directory. Then submit the homework electronically via:
> submit pj1
After submitting, if you find a bug in your program, you can submit again. We will look at the last solution you submit (unless you tell us otherwise).
Good luck, and please make use of the class newsgroup for discussion on Java concepts, compiler issues, and other issues that come up during your project. Remember the no-code rule though. Get in touch with us via or come to your TAs office hours if you run into trouble. We are here to help! Thanks.