Thursday, August 4, 2011

Minesweeper in Java Fx 2.0

Minesweeper v1.0 in JavaFx 2.0

This week I tried my hands at developing Minesweeper game in JavaFx 2.0 and the snapshot of version 1.0 is shown above. If OS installed on your laptop or PC is Microsoft Windows , then chances are that you might have played this game before. For those who don't know about this game here is a quick introduction to the rules.

As shown in snapshot below, the game consist of grid of identical squares. Some of these squares contains mines which of course are unknown to the player.

Minesweeper game when it starts.
The total number of mines is shown to the user. In above snapshot total number of mines is shown as "MINES REMAINING". Player has to identify mines location by flagging a square. A square is flagged by right clicking it.
But how do player know that particular square has hidden mine ? For this user has to click a square (sometimes randomly). Clicking a square reveals number of bombs in the adjacent square. This is explained in snapshots below.
In above case top left square was clicked. It reveals number of mines  in  adjacent  squares.

In above case squares are flagged for mines.
Player wins when he flags all the squares containing mines.By checking the count of mines in the adjacent squares player has to guess the presence of mine and flag it.
In above screenshot player has correctly flagged all squares containing  mine and thus he won .
However if player clicks a square containing mine then all mines get activated and explodes. In this case of course he has lost the game.
In above case used has clicked square containing mine and all mines exploded . Player  has lost the game .
If you want to read in detail about this game then head to this wikipedia article.

So much so far. Now lets come to the coding part.

The applications main class is Main defined in file Main.java. Nothing special about this class except that it is application entry point(public static void main) , defines stage and scene for application and finally creates instance for class Grid wherein we have coded our game.


package minesweeper;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Application.launch(Main.class, args);
    }
    
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Minesweeper v1.0");
        
        
        primaryStage.setFullScreen(false);
        Group root = new Group();
        Scene scene = new Scene(root,Color.BLACK);

        root.getChildren().add(new Grid(9,9));
        primaryStage.setScene(scene);
        primaryStage.setVisible(true);
    }
}

In the whole project we have declared and used 4 classes. Main class we have just discussed above. Other 3 classes viz., Box ,Grid and Scoreboard are discussed below.

Box Class
Box class extends Parent class which is the base class for all nodes that have children in the scene graph. This class is used to draw a square in minesweeper.
Instance of  Box Class
As shown in figure above the Box class is nothing but a Rectangle drawn. However there is more in Box class. A square is minesweeper  has different states like flagged, uncover after user clicks it, showing count of number of mines(bombs) in adjacent squares and explode mine when user click a square having mine. All of these states are defined using attributes for Box class.

  • Uncovered Box : When user clicks a Box(square in minesweeper) the box gets uncovered. We are showing box is uncovered by changing color of box. Further there are two possibilities when a Box is clicked. 1) Clicked box don't have mines in adjacent 8 squares. In this case no count is shown. 2) Clicked box have mine(s) in adjacent 8 squares. In this case number of bombs in adjacent square is shown.
Uncovered Box with no bomb in adjacent squares.
Uncovered Box with 2 bombs in adjacent squares.
           Attribute : boolean isCovered; 
  • Flagged Box: When user right clicks a box the Box gets flagged. We are flagging a box by showing flag image on it. 
Flagged Box.
          Attribute: boolean isFlagged;
  • Exploded Box: When user clicks a Box having mine , the mine explodes. We are showing this by displaying image of explosion on Box.
Exploded Box.
          Attribute: boolean isBomb;

There are some methods declared that sets the state of Box. These are explained below.
  1. setBombBox() : This method is to add or remove bomb from Box. Attribute isBomb is set to true / false accordingly.
  2. showBombCount(): This method is to display number of mines in adjacent square. Attribute used is bomb_count.
  3. setCovered(): To uncover or cover a bomb.
  4. explodeBomb(): To show exploded Box if Box is having attribute isBomb = true.
  5. setFlagged(): Sets/Unsets the flag of the box. Attribute used is isFlagged.
  6. setBoxColor(): Sets color of the box.
  7. isBomb(),isCovered(),isFlagged() : As suggested in the method name itself it returns the boolean value of attribute.
  8. getBombCount: Returns number of bombs in adjacent squares of the box.
  9. resetBox(): This method resets all the attributes of Box and set the box to Covered state. This is used when to restart game.
  10. setBoxPosition() : Sets the value of attributes posRow and posCol using the parameters passed. This value is used to get Box position in the Grid.
  11. getBoxRow(),getBoxCol(): Returns posRow and posCol values respectively.
Thats all about Box class ! One thing should be remembered that Box class itself don't have game logic in it. It simply changes the state of the Box. It is the Grid class which dictates these changes and has game logic coded in it.

Grid Class
As the name suggests , Grid class is a Grid formed by Box objects. Like Box class, Grid class also extends Parent class.

Attributes of class are discussed in code snippet below. Please go through comments for the purpose of attributes.

int countColumn;//number of columns in the Grid.
    int countRow;//number of rows in the Grid.
    int countBomb;//number of Bombs(Mines) in the game.
    int countFlaggedBoxes=0;//number of boxes flagged by user.
    Box[][] boxGrid; //array to store objects of Box class.
    VBox vboxLayout; //layout to show children in vertical column
    ScoreBoard scoreBoard; //instance of inner class ScoreBoard.
    boolean isGameFinished = false; //whether game is finished 
Next is the constructor of Grid class.
public Grid(int cols,int rows)
The Grid constructor has arguments number of columns and rows. Accordingly it initializes boxGrid array with specified number of objects.This is of course done within for loops. While doing this we are also setting position of Box object within Grid. Also we are adding mouse events setOnMouseClicked,setOnMouseEntered,setOnMouseExited for each Box object within this loop.

Box objects on the same row are added in HBox layout and this HBox is then added in vboxLayout in the end. Thus we have a Grid of Boxes. You can imagine this.

Finally , we call setGamePuzzle() method to set game puzzle.
private void setGamePuzzle()
In this method we are first calculating total number of mines as 15% of total number of Boxes.
tempCountBomb = (int)((countColumn * countRow * 15.0)/100);
Then we place these many mines randomly in a Grid.
for (int i = 0; i < tempCountBomb; i++) {
            random_row=(int) (Math.random()*countRow);
            random_col=(int) (Math.random()*countColumn);
            boxGrid[random_row][random_col].setBombBox(true);
        }
There is a possibility that same pair of random row and column may generate twice and bomb will set twice for the same Box object. In such cases we are reducing count of bombs by 1.

After setting bombs for some Boxes we are initializing remaining Boxes which don't have bomb by number of bomb counts in the adjacent 8 squares. This is how game puzzle is set.

In the attributes list of Grid class you might have noticed ScoreBoard class. This is a inner class defined in class Grid. Purpose of scoreboard is to show total number of mines in the puzzle and guide user when he wins or losses games. It also have "RESTART GAME" button which resets the game.
ScoreBoard when game starts.

ScoreBoard when player wins game.

ScoreBoard when palyer losses game.
Instance of ScoreBoard is created in the Grid constructor and added in vboxLayout.

At this point game is ready and presented to the player. Now players interaction with application starts.

  • When user clicks a Box which happens to be a Bomb Box then he loses the game and other hidden bombs also explodes. We also update scoreboard with message "Game Over".
  • When user clicks a Box which is not a Bomb Box then we have to uncover that box and show user number of bombs present in the adjacent squares. If the clicked box don't have any bomb in adjacent square then we have to uncover all 8 adjacent squares and show number of bombs in the adjacent square of these squares. The process is recursive. This is handled in method showBombCounts() which is recursive. To get idea of this refer the image below. 
In above example player has clicked on a box which is marked in red color.
  • When player right clicks a box we have flag tha box. If box is already flagged then we have to remove that flag.
  • When user just hovers over the Covered Box with mouse cursor, we are changing color of box when cursor is on the Box. As soon as cursor exits box we are showing earlier color.

Here ends the description of the coding part. Hope you like the post ! 
Your suggestions are most welcome.

If you want to download jar file of the game it can be downloaded here
Javafx2.0 must be installed on your system to run this game. Get it from here.

Complete source code as a Netbeans Project is available here.
Get latest Netbeans IDE from here.









3 comments: