Java Project – Minesweeper Game

Welcome, puzzle enthusiasts! Minesweeper is a classic puzzle game that challenges players to uncover cells on a grid while avoiding hidden mines.

In this Java Minesweeper Game, we will explore the code for a simplified version of the Minesweeper game implemented in Java. Get ready to dive deep into the logic of uncovering cells while skillfully avoiding hidden mines. We’ll equip you with the tools to understand the inner workings of this intriguing puzzle game.

We will walk through the code step by step and explain its functionality in simple terms. So, let’s get started and embark on this thrilling Minesweeper quest!`

About Java Minesweeper Game Project

We will implement the following functionalities in the Java Minesweeper Game:

1. We will define the game logic and board representation with the MinesweeperGame class.

2. We will initialize the game board, set the number of mines, and randomly place the mines on the board in the constructor.

3. The play method will process the player’s actions (reveal or flag) and update the game state accordingly.

4. We will use the revealCell method to reveal a cell and update the game state. If the selected cell has no adjacent mines, we will recursively reveal adjacent cells.

5. We will toggle the flag on a cell using the toggleFlag method to indicate that it may contain a mine.

6. The printBoard method will display the current state of the game board, showing revealed cells, flagged cells, and unvisited cells.

7. When the game is over, the revealAllMines method will reveal all remaining mines on the board.

8. As the entry point of the program, our main method will prompt the user to enter the dimensions of the game board and the number of mines. We will then initiate the game loop, where the player can make moves until the game is over or all cells are revealed.

Overall, we will set up the Minesweeper game, handle player input, update the game state, and display the board until the game is over or we win.

Prerequisites for Java Minesweeper Game

To write and run the Minesweeper game code, the following prerequisites are required:

1. Basic understanding of the Java programming language, including knowledge of loops, conditional statements, and object-oriented programming concepts.

2. Familiarity with array data structures and the Java.util package, which provides utility classes like Random and Arrays.

3. A working Java development environment, which includes installing the Java Development Kit (JDK) on your computer. You can download the JDK from the official Oracle website or use a package manager specific to your operating system.

4. An Integrated Development Environment (IDE) like IntelliJ IDEA, Eclipse, or NetBeans, which can greatly simplify Java development. Choose an IDE you are comfortable with and set it up.

Download Java Minesweeper Game

Please download the source code of the Java Minesweeper Game: Java Minesweeper Game Project Code. 

Setting Up the Java Minesweeper Game

Let’s begin by setting up the game! To get started, we will import the essential Java utilities and define the dimensions of our game board. The game board itself is represented by a special 2D character array called “board”. Additionally, we have two boolean arrays, “revealed” and “flagged”, which help us keep track of the cells we’ve uncovered and flagged, respectively. We also initialize variables to keep count of the remaining cells and to determine if the game is over. With these initial steps in place, we’re ready to dive into the exciting world of Minesweeper!

Code Breakdown

1. MineSweeperGame class:

  • rows, cols, mines: Private instance variables to store the dimensions and number of mines in the game.
  • board: A 2D character array to represent the game board.
  • visited: A 2D boolean array to track visited cells on the board.
  • flagged: A 2D boolean array to track flagged cells on the board.
  • gameOver: A boolean variable to indicate if the game is over.
  • remainingCells: An integer variable to store the number of remaining cells to be revealed.
public class MineSweeperGame {
    private int rows;
    private int cols;
    private int mines;
    private char[][] board;
    private boolean[][] visited;
    private boolean[][] flagged;
    private boolean gameOver;
    private int remainingCells;

2. MineSweeperGame constructor:

  • Initializes the instance variables with the provided values.
  • Created the game board and visited and flagged arrays.
  • Calls the initializeBoard and placeMines methods.
public MineSweeperGame(int rows, int cols, int mines) {
        this.rows = rows;
        this.cols = cols;
        this.mines = mines;
        this.board = new char[rows][cols];
        this.visited = new boolean[rows][cols];
        this.flagged = new boolean[rows][cols];
        this.gameOver = false;
        this.remainingCells = rows * cols - mines;
        initializeBoard();
        placeMines();
    }

3. initializeBoard method:

  • Initializes the game board with empty cells (“-“).
  • Sets all cells as unvisited and unflagged.
// Initialize the game board with empty cells
    private void initializeBoard() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                board[i][j] = '-';
                visited[i][j] = false;
                flagged[i][j] = false;
            }
        }
    }

4. placeMines method:

  • Randomly places mines on the game board until the desired number of mines is reached.
  • Uses a Random object to generate random row and column indices.
  • Check if the selected cell is not already a mine and place a mine (“*”) in that cell.
// Randomly place mines on the game board
   private void placeMines() {
       Random random = new Random();
       int count = 0;

       while (count < mines) {
           int row = random.nextInt(rows);
           int col = random.nextInt(cols);

           if (board[row][col] != '*') {
               board[row][col] = '*';
               count++;
           }
       }
   }

5. isValidCell method:

  • Check if the given row and column indices represent a valid cell on the game board.
  • Returns true if the cell is valid, false otherwise.
// Check if a cell is a valid cell on the game board
   private boolean isValidCell(int row, int col) {
       return row >= 0 && row < rows && col >= 0 && col < cols;
   }

6. countAdjacentMines method:

  • Counts the number of mines adjacent to the given cell (row, col).
  • Checks the cells in the surrounding 3×3 grid centred around the given cell.
  • Increments the count if a valid adjacent cell contains a mine (“*”).
// Count the number of adjacent mines to a given cell
   private int countAdjacentMines(int row, int col) {
       int count = 0;

       for (int i = row - 1; i <= row + 1; i++) {
           for (int j = col - 1; j <= col + 1; j++) {
               if (isValidCell(i, j) && board[i][j] == '*') {
                   count++;
               }
           }
       }

       return count;
   }

7. revealed method:

  • Reveals a cell and updates the game state.
  • If the cell is a valid, unvisited, and unflagged cell:
  • Marks the cell as visited and decrements the remaining cells count.
  • If the cell contains a mine, set the gameOver flag to true.
  • If the cell has no adjacent mines, recursively reveals the adjacent cells.
  • This method is called when the player chooses to reveal a cell.
// Reveal a cell and update the game state
 private void revealCell(int row, int col) {
     if (isValidCell(row, col) && !visited[row][col] && !flagged[row][col]) {
         visited[row][col] = true;
         remainingCells--;

         if (board[row][col] == '*') {
             gameOver = true;
             return;
         }

         if (countAdjacentMines(row, col) == 0) {
             for (int i = row - 1; i <= row + 1; i++) {
                 for (int j = col - 1; j <= col + 1; j++) {
                     if (isValidCell(i, j) && !visited[i][j] && !flagged[i][j]) {
                         revealCell(i, j);
                     }
                 }
             }
         }
     }
 }

8. toggle flag method:

  • Toggles the flag on a cell.
  • If the cell is valid, toggle the flagged state of the cell.
// Toggle the flag on a cell
 private void toggleFlag(int row, int col) {
     if (isValidCell(row, col)) {
         flagged[row][col] = !flagged[row][col];
     }
 }

9. play method:

  • Plays the game based on the player’s action (reveal or flag).
  • If the game is over or the cell is invalid or already visited, it returns.
  • If the action is “reveal”:
  • If the cell does not contain a mine, mark the cell as revealed (“1”).
  • If the cell contains a mine, set the gameOver flag to true.
  • Calls the revealCell method to update the game state.
  • If the action is “flag”, toggle the flag on the cell.
  • Check if the game is over or if all cells have been revealed to print the appropriate message or continue the game.
  • Calls the printBoard method to display the current state of the game board.
// Play the game based on the player's action (reveal or flag)
 public void play(int row, int col, String action) {
     if (gameOver || !isValidCell(row, col) || visited[row][col]) {
         return;
     }

     if (action.equalsIgnoreCase("reveal")) {
         if (board[row][col] != '*') {
             board[row][col] = '1'; // Mark the cell as revealed
         } else {
             gameOver = true;
         }
         revealCell(row, col);
     } else if (action.equalsIgnoreCase("flag")) {
         toggleFlag(row, col);
     }

     if (gameOver) {
         System.out.println("Sorry! Game Over!");
         revealAllMines();
     } else if (remainingCells == 0) {
         System.out.println("Congratulations! You Won!");
         revealAllMines();
     } else {
         printBoard();
     }
 }

10. revealAllMines method:

  • Reveals all the remaining mines on the game board.
  • Marks the unvisited mine cells as visited.
// Reveal all the remaining mines on the game board
  private void revealAllMines() {
      for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; j++) {
              if (board[i][j] == '*' && !visited[i][j]) {
                  visited[i][j] = true;
              }
          }
      }

      printBoard();
  }

11. print board method:

  • Prints the current state of the game board.
  • Displays the remaining cell count.
  • For each cell:
  • If the cell is visited, print the revealed value.
  • If the cell is flagged, print “F”.
  • If the cell is unvisited, print “-“.
  • Prints an empty line.
// Print the current state of the game board
  private void printBoard() {
      System.out.println("Remaining cells: " + remainingCells);
      System.out.println();

      for (int i = 0; i < rows; i++) {
          for (int j = 0; j < cols; j++) {
              if (visited[i][j]) {
                  System.out.print(board[i][j] + " ");
              } else if (flagged[i][j]) {
                  System.out.print("F ");
              } else {
                  System.out.print("- ");
              }
          }
          System.out.println();
      }
      System.out.println();
  }

12. main method:

  • The entry point of the program.
  • Creates a Scanner object for user input.
  • Prompts the user to enter the dimensions and number of mines for the game.
  • Creates an instance of MineSweeperGame.
  • Runs a loop until the game is over or all cells are revealed:
  • Prompts the user to enter the row, column, and action (reveal or flag).
  • Calls the play method to process the user’s input.
  • Closes the Scanner.
public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("Welcome to the MineSweeper Game by FirstCode!");

        System.out.print("Enter number of rows: ");
        int rows = scanner.nextInt();

        System.out.print("Enter number of columns: ");
        int cols = scanner.nextInt();

        System.out.print("Enter number of mines: ");
        int mines = scanner.nextInt();

        MineSweeperGame minesweeper = new MineSweeperGame(rows, cols, mines);

        while (!minesweeper.gameOver && minesweeper.remainingCells > 0) {
            System.out.print("Enter row (0-" + (rows - 1) + "): ");
            int row = scanner.nextInt();

            System.out.print("Enter column (0-" + (cols - 1) + "): ");
            int col = scanner.nextInt();

            scanner.nextLine(); // Consume newline character

            System.out.print("Enter action (reveal/flag): ");
            String action = scanner.nextLine();

            minesweeper.play(row, col, action);
        }

        scanner.close();
    }

Code to illustrate the Java MineSweeper Game

import java.util.*;
public class MineSweeperGame {
    private int rows;
    private int cols;
    private int mines;
    private char[][] board;
    private boolean[][] visited;
    private boolean[][] flagged;
    private boolean gameOver;
    private int remainingCells;

    public MineSweeperGame(int rows, int cols, int mines) {
        this.rows = rows;
        this.cols = cols;
        this.mines = mines;
        this.board = new char[rows][cols];
        this.visited = new boolean[rows][cols];
        this.flagged = new boolean[rows][cols];
        this.gameOver = false;
        this.remainingCells = rows * cols - mines;
        initializeBoard();
        placeMines();
    }

    // Initialize the game board with empty cells
    private void initializeBoard() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                board[i][j] = '-';
                visited[i][j] = false;
                flagged[i][j] = false;
            }
        }
    }

    // Randomly place mines on the game board
    private void placeMines() {
        Random random = new Random();
        int count = 0;

        while (count < mines) {
            int row = random.nextInt(rows);
            int col = random.nextInt(cols);

            if (board[row][col] != '*') {
                board[row][col] = '*';
                count++;
            }
        }
    }

    // Check if a cell is a valid cell on the game board
    private boolean isValidCell(int row, int col) {
        return row >= 0 && row < rows && col >= 0 && col < cols;
    }

    // Count the number of adjacent mines to a given cell
    private int countAdjacentMines(int row, int col) {
        int count = 0;

        for (int i = row - 1; i <= row + 1; i++) {
            for (int j = col - 1; j <= col + 1; j++) {
                if (isValidCell(i, j) && board[i][j] == '*') {
                    count++;
                }
            }
        }

        return count;
    }

    // Reveal a cell and update the game state
    private void revealCell(int row, int col) {
        if (isValidCell(row, col) && !visited[row][col] && !flagged[row][col]) {
            visited[row][col] = true;
            remainingCells--;

            if (board[row][col] == '*') {
                gameOver = true;
                return;
            }

            if (countAdjacentMines(row, col) == 0) {
                for (int i = row - 1; i <= row + 1; i++) {
                    for (int j = col - 1; j <= col + 1; j++) {
                        if (isValidCell(i, j) && !visited[i][j] && !flagged[i][j]) {
                            revealCell(i, j);
                        }
                    }
                }
            }
        }
    }

    // Toggle the flag on a cell
    private void toggleFlag(int row, int col) {
        if (isValidCell(row, col)) {
            flagged[row][col] = !flagged[row][col];
        }
    }

    // Play the game based on the player's action (reveal or flag)
    public void play(int row, int col, String action) {
        if (gameOver || !isValidCell(row, col) || visited[row][col]) {
            return;
        }

        if (action.equalsIgnoreCase("reveal")) {
            if (board[row][col] != '*') {
                board[row][col] = '1'; // Mark the cell as revealed
            } else {
                gameOver = true;
            }
            revealCell(row, col);
        } else if (action.equalsIgnoreCase("flag")) {
            toggleFlag(row, col);
        }

        if (gameOver) {
            System.out.println("Sorry! Game Over!");
            revealAllMines();
        } else if (remainingCells == 0) {
            System.out.println("Congratulations! You Won!");
            revealAllMines();
        } else {
            printBoard();
        }
    }

    // Reveal all the remaining mines on the game board
    private void revealAllMines() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (board[i][j] == '*' && !visited[i][j]) {
                    visited[i][j] = true;
                }
            }
        }

        printBoard();
    }

    // Print the current state of the game board
    private void printBoard() {
        System.out.println("Remaining cells: " + remainingCells);
        System.out.println();

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (visited[i][j]) {
                    System.out.print(board[i][j] + " ");
                } else if (flagged[i][j]) {
                    System.out.print("F ");
                } else {
                    System.out.print("- ");
                }
            }
            System.out.println();
        }

        System.out.println();
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("Welcome to the MineSweeper Game by FirstCode!");

        System.out.print("Enter number of rows: ");
        int rows = scanner.nextInt();

        System.out.print("Enter number of columns: ");
        int cols = scanner.nextInt();

        System.out.print("Enter number of mines: ");
        int mines = scanner.nextInt();

        MineSweeperGame minesweeper = new MineSweeperGame(rows, cols, mines);

        while (!minesweeper.gameOver && minesweeper.remainingCells > 0) {
            System.out.print("Enter row (0-" + (rows - 1) + "): ");
            int row = scanner.nextInt();

            System.out.print("Enter column (0-" + (cols - 1) + "): ");
            int col = scanner.nextInt();

            scanner.nextLine(); // Consume newline character

            System.out.print("Enter action (reveal/flag): ");
            String action = scanner.nextLine();

            minesweeper.play(row, col, action);
        }

        scanner.close();
    }
}

Java Minesweeper Game Ouput:

Mine Sweeper Game java

Java Mine Sweeper Game

Java Mine Sweeper Game output

Building different levels of the Java MineSweeper Game

To create different levels of the Minesweeper game in Java, we can modify the MineSweeperGame class by adding different levels with varying grid sizes, mine densities, and difficulty.

Here’s an example of how we can implement the beginner, intermediate, and hard levels:

import java.util.*;
public class MineSweeperGame {
    // ...

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("Welcome to the MineSweeper Game by FirstCode!");
        System.out.println("Select the difficulty level:");
        System.out.println("1. Beginner");
        System.out.println("2. Intermediate");
        System.out.println("3. Hard");

        System.out.print("Enter the level number: ");
        int level = scanner.nextInt();
        scanner.nextLine(); // Consume newline character

        int rows, cols, mines;

        switch (level) {
            case 1: // Beginner level
                rows = 8;
                cols = 8;
                mines = 10;
                break;
            case 2: // Intermediate level
                rows = 12;
                cols = 12;
                mines = 20;
                break;
            case 3: // Hard level
                rows = 16;
                cols = 16;
                mines = 40;
                break;
            default:
                System.out.println("Invalid level selection. Exiting the game.");
                return;
        }

        MineSweeperGame minesweeper = new MineSweeperGame(rows, cols, mines);

        while (!minesweeper.gameOver && minesweeper.remainingCells > 0) {
            // ...
            // Rest of the code remains the same
            // ...
        }

        scanner.close();
    }
}

In this example, the main method prompts the user to select the difficulty level. Depending on the level chosen, the corresponding grid size and mine density are set. The levels defined in this example are as follows:

Beginner level:
Grid size: 8×8
Number of mines: 10

Intermediate level:
Grid size: 12×12
Number of mines: 20

Hard level:
Grid size: 16×16
Number of mines: 40

We can adjust the grid size and number of mines according to our preferences for each level.

Summary

In this project, we examined a simplified version of the Minesweeper game implemented in Java. We explored the code step by step, understanding its various methods and their roles in the game. By following this code structure, you can build upon it and create a fully functional Minesweeper game with additional features and complexities. Enjoy coding and happy mine-clearing!

Leave a Reply

Your email address will not be published. Required fields are marked *