Implement a graphical version of the Minefield Game . The game will have a 5x5 g
ID: 3546533 • Letter: I
Question
Implement a graphical version of the Minefield Game. The game will have a 5x5 grid of squares, with two of the squares designated as the Start and Finish. Hidden underneath two of the squares will be landmines. The objective of the game is to move from the Start to the Finish without encountering any landmines. The player cannot move diagonally.
Write a class MineField that extends JFrame and implements ActionListener. It should have two panels: the top panel contains a 5x5 grid of buttons simulating a minefield and the bottom panel contains a Clear button and a Done button. Pushing the Clear button begins the game. It should cause two randomly chosen minefield buttons to be designated as Start and Finish, and two randomly chosen minefield buttons to have mines hidden below them. When a user clicks on a minefield button (from Start to Finish), it should change color to show the selected path. After a user completes the path, pushing the Done button should cause a check to see whether a mine was encountered and a message to appear indicating safe passage or failure.
I strongly suggest that you develop this program incrementally, a little at a time. First, simply draw a window big enough to hold the panels. Then add the two panels. Then add buttons to the panels. Then add anActionListener for each button that indicates when it was pushed. Then add the functionality for the Clear. Then add the functionality for the Done. Etc.
At a minimum
Explanation / Answer
*/
import java.io.*;
import java.util.Random;
import java.util.StringTokenizer;
class square{
//the square object, representing a square in the game board.
// it contains 2 fields, the actual value, and if the square has been revealed.
private boolean revealed;
private char value;
public square(char v){
//constructor that sets value to parameter, and revealed to false.
revealed=false;
value=v;
}
public String toString(){
//public method to convert object to string for easy output
// the beauty of this is the square object itself decides what
// to output because of the _revealed_ field.
if (revealed)
return (value+"");
else
return "-";
}
public char getValue(){
//public method to return value field.
return value;
}
public void setValue(char v){
//public method to set the value field.
value=v;
}
public void setRevealed(boolean r){
//public method to set the revealed flag.
revealed=r;
}
public boolean isRevealed(){
//public method to return the revealed field.
return revealed;
}
}
class MineBoard{
//the MineBoard object that represents the game board, a matrix of squares.
private square[][] board;
private int rows, cols, nummines;
private int uncovered; //to keep track number of squares uncovered (for win condition)
public MineBoard(int r, int c, int n){
//public constructor to initialize board size and mine count to parameters.
rows=r;
cols=c;
nummines=n;
board=new square[rows][cols];
uncovered=0;
fillSquares();
}
public MineBoard(){
//default constructor to create a 5x5 game with 6 mines.
this(5,5,6);
}
private void fillSquares(){
//private method to initialize the square objects in the board.
//instanciates all the squares, and then places the mines randomly.
int r,c;
int mines=nummines;
Random rng=new Random();
for (r=0;r<rows;r++)
for (c=0;c<cols;c++)
board[r][c]=new square('?'); //just to instanciate the squares
while (mines>0){ //loop to place the mines.
r=rng.nextInt(rows);
c=rng.nextInt(cols);
if ((board[r][c]).getValue()!='*'){
board[r][c]=new square('*');
mines--;
}
}
}
private int minecount(int r, int c){
// private method to return an integer for the number of mines
// surrounding the square at [r][c].
int count=0;
for (int y=-1; y<=1; y++){
for (int x=-1; x<=1; x++){
if (y==0 && x==0) continue;
if (r+y <0 || r+y>=rows) continue;
if (c+x <0 || c+x>=cols) continue;
if (board[r+y][c+x].getValue()=='*')
count++;
}
}
return count;
}
public boolean reveal(int r, int c){
//public method that reveals the square at [r][c].
// returns false if a mine is hit
// returns true otherwise.
//checks to see if i've already been here, or if r,c is out of bounds:
if (r<0 || r>=rows || c<0 || c>=cols || board[r][c].isRevealed()) return true;
board[r][c].setRevealed(true); //sets the square to revealed.
if (board[r][c].getValue()=='*') return false; //hit a mine.
else{
//otherwise, compute the mine count on the fly and set the value.
board[r][c].setValue((char)(minecount(r,c)+'0'));
uncovered++; //increments the count of uncovered.
if (board[r][c].getValue()=='0'){ //the recursive calls for flood revealing.
reveal(r-1,c-1); reveal(r-1,c); reveal(r-1,c+1);
reveal(r,c-1); reveal(r,c+1);
reveal(r+1,c-1); reveal(r+1,c); reveal(r+1,c+1);
}
return true;
}
}
public boolean hasWon(){
//public method that returns true if the game is won,
// ie., the player has uncovered all the squares that are not mines.
// returns false otherwise.
return (uncovered==(rows*cols-nummines));
}
public String toString(){
//public method to convert the game state into a string for output.
int r, c;
String out=" |";
for (c=0;c<cols;c++) //this section just creates
out+=Integer.toString(c)+" "; // the initial heading/top part
out+=" ==+"; // of the output
for (c=0;c<cols;c++) //because i wrote this to
out+="=="; // allow user defined game
out+=" "; //parameters (row, cols, # mines).
for (r=0;r<rows; r++){ //this loop outputs each square object
out+=(r+" |"); // of the board.
for (c=0;c<cols;c++){ //again, this is very concise because
out+=(board[r][c]+ " "); // of our OO method, it just calls
} // square's toString() method.
out+=" ";
}
return out;
}
}
public class MineSweeper{
//our public main class that is actually the game and contains the main()
// which creates a MineSweeper object to play.
MineBoard game;
public MineSweeper(int rows, int cols, int mines) throws IOException{
//the constructor that plays the game.
int r,c;
StringTokenizer strtok;
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
game = new MineBoard(rows,cols,mines);
boolean won=false;
//this do-while loop takes in user input and reveals the appropriate
// square, quitting when a mine is hit or win state is achieved
do{
System.out.println(game);
System.out.print("Enter row followed by column (both on this line)>");
//I tokenize the input line since i ask for row and column on one line.
//the if-else is just for if there is not enough tokens (bad user input).
// if so, it puts ineffective values into r,c, which reveal() will just
// disregard, thus continuing the loop for more input.
strtok=new StringTokenizer(in.readLine(), " ,");
if (!strtok.hasMoreTokens()) r=-1;
else r=Integer.parseInt(strtok.nextToken());
if (!strtok.hasMoreTokens()) c=-1;
else c=Integer.parseInt(strtok.nextToken());
} while (game.reveal(r,c) && !(won=game.hasWon()));
for (r=0;r<rows;r++) //just to reveal
for (c=0;c<cols;c++) // the rest of the
game.reveal(r,c); // board to show
System.out.println(game); // at the end.
if (won){
System.out.println(" **Congratulations!!** You've won!");
}
else{
System.out.println(" ** Oops! ** You LOST!");
}
}
public static void main(String args[])throws IOException{
//the "main" that is executed. The default values for number of
// rows, columns, and mines is assigned and overwritten is supplied
// via arguments.
int r=5,c=5,n=6;
if (args.length==3){
r=Integer.parseInt(args[0]);
c=Integer.parseInt(args[1]);
n=Integer.parseInt(args[2]);
}
new MineSweeper(r,c,n);
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.