Minesweeper Clone (Java Edition)

Java Edition

“New Game” button creates a new game. The “Continue” button loads the progress from a selected “progress” file. The “Save Progress” saves progress to a selected “progress” file. “Save Board” saves the mine placement to a selected board file and resets. It does not save progress. “Load Board” load the mine placement from a selected board file resets. The “Reset” button resets by restoring question marks, “Spaces Checked” count, “Mines Left” count, and removing flags.

In “Sweep Mode”, clicking a question mark spot reveals a mine, blank spot or number. “Flag Mode” allows marking areas the user believes are mines. Clicking a mine in “Sweep Mode” loses the game (although, the “Reset” button can undo this)

The images from my original article are missing. I plan to replace them soon.

Clicking a blank space clears all blank spaces and adjacent spaces.
Users can place flags on likely mine spaces.
Loss Screen
Win Screen
JW.java 
package main;

import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import java.awt.Font;

public class JW {

	JButton[][] buttonGrid = new JButton[10][10];
	public JFrame frmTippinMineSearch;
	private JLabel lblNewLabel;
	private int spacesChecked = 0;
	private static boolean playing = true;
	static Window window;

	private JButton btnNewButton;
	private JPanel panel;
	private JRadioButton rdbtnNewRadioButton;
	private JRadioButton rdbtnNewRadioButton_1;
	private JLabel lblNewLabel1;
	private JButton btnNewButton_4;
	private int minesFound = 0;

	private final String flag = "⚑";
	JFileChooser fileChooser = new JFileChooser();
	/**
	 * Create the application.
	 * @param dimensionX 
	 * @param dimensionY 
	 */
	public JW(int dimensionX, int dimensionY) {
		initialize(dimensionX, dimensionY);
	}

	private void flagAction(int i, int j) {
		if (playing) {
			if (buttonGrid[i][j].getText().equals("?")) {
				buttonGrid[i][j].setText(flag);
				minesFound++;
			} else if (buttonGrid[i][j].getText().equals(flag)) {
				buttonGrid[i][j].setText("?");
				minesFound--;
			}
			lblNewLabel1.setText("Mines Left: " + (Main.mineCount - minesFound));
		}
	}

	private void sweepAction(int i, int j) {
		if (buttonGrid[i][j].getText().equals("?") & playing) {
			spacesChecked++;
			lblNewLabel.setText("Spaces Checked: " + spacesChecked);
			switch (Main.board[j][i]) {
			case 9:
				lose();
				break;
			case 0:
				buttonGrid[i][j].setText(" ");
				int xStart = Math.max(0, i - 1), xEnd = Math.min(i + 1, Main.dimensionX - 1);
				int yStart = Math.max(0, j - 1), yEnd = Math.min(j + 1, Main.dimensionY - 1);

				for (int k = xStart; k <= xEnd; k++) {
					for (int l = yStart; l <= yEnd; l++) {
						sweepAction(k, l);
					}
				}
				break;
			default:
				buttonGrid[i][j].setText(Integer.toString(Main.board[j][i]));
			}
			if (playing && spacesChecked >= 90) {
				playing = false;
				lblNewLabel.setText("You won!");
				lblNewLabel1.setText("Mines Left: 0");
				for (int i1 = 0; i1 < 10; i1++) {
					for (int j1 = 0; j1 < 10; j1++) {
						if (buttonGrid[i1][j1].getText().equals("?")) {
							buttonGrid[i1][j1].setText(flag);
						}

					}
				}

			}

		}

	}

	private void lose() {
		for (int i1 = 0; i1 < 10; i1++) {
			for (int j1 = 0; j1 < 10; j1++) {
				if (Main.board[j1][i1] == 9) {
					buttonGrid[i1][j1].setText("✹");
				}

			}

			lblNewLabel.setText("You Lose!");
			playing = false;
		}
	}



	private void resetBoard() {
		spacesChecked = 0;
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				buttonGrid[i][j].setText("?");
			}
		}
		playing = true;
		lblNewLabel.setText("Spaces Checked: 0");
		minesFound = 0;
		lblNewLabel1.setText("Mines Left: " + (Main.mineCount - minesFound));
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize(int dimensionX, int dimensionY) {
		frmTippinMineSearch = new JFrame();
		frmTippinMineSearch.setTitle("Tippin Mine Search");
		int buttonXDim = 43;
		int buttonYDim = 43;
		frmTippinMineSearch.setBounds(100, 100, 652, 500);
		frmTippinMineSearch.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmTippinMineSearch.getContentPane().setLayout(null);

		JButton btnNewButton_1 = new JButton("Reset");
		btnNewButton_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				resetBoard();

			}
		});
		btnNewButton_1.setBounds(472, 283, 110, 23);
		frmTippinMineSearch.getContentPane().add(btnNewButton_1);

		lblNewLabel = new JLabel("Spaces checked: 0");
		lblNewLabel.setBounds(472, 63, 130, 14);
		frmTippinMineSearch.getContentPane().add(lblNewLabel);

		btnNewButton = new JButton("New Game");
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Main.board = Main.minesweeper_numbers(Main.boardmaker(dimensionX, dimensionY, Main.mineCount));
				resetBoard();

			}

		});
		btnNewButton.setBounds(472, 113, 110, 23);
		frmTippinMineSearch.getContentPane().add(btnNewButton);

		buttonGrid = new JButton[dimensionX][dimensionY];
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				buttonGrid[i][j] = new JButton("?");
				buttonGrid[i][j].setMargin(new Insets(0, 0, 0, 0));
				buttonGrid[i][j].setFont(new Font("SansSerif.plain", Font.PLAIN, 15));
				final int q1 = i;
				final int q2 = j;
				buttonGrid[i][j].addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						if (rdbtnNewRadioButton.isSelected()) {
							sweepAction(q1, q2);
						} else {
							flagAction(q1, q2);
						}
					}

				});
				buttonGrid[i][j].setBounds(10 + (i * buttonXDim - 1), 11 + (j * buttonYDim - 1), buttonXDim,
						buttonYDim);
				frmTippinMineSearch.getContentPane().add(buttonGrid[i][j]);

			}
		}

		panel = new JPanel();
		panel.setBounds(472, 317, 103, 63);
		frmTippinMineSearch.getContentPane().add(panel);
		panel.setLayout(null);

		rdbtnNewRadioButton = new JRadioButton("Sweep Mode");
		rdbtnNewRadioButton.setSelected(true);
		rdbtnNewRadioButton.setBounds(6, 7, 109, 23);
		panel.add(rdbtnNewRadioButton);

		rdbtnNewRadioButton_1 = new JRadioButton("Flag Mode");
		rdbtnNewRadioButton_1.setBounds(6, 33, 109, 23);
		panel.add(rdbtnNewRadioButton_1);
		ButtonGroup group = new ButtonGroup();
		group.add(rdbtnNewRadioButton);
		group.add(rdbtnNewRadioButton_1);

		lblNewLabel1 = new JLabel("Mines Left: 10");
		lblNewLabel1.setBounds(472, 88, 130, 14);
		frmTippinMineSearch.getContentPane().add(lblNewLabel1);
		JButton btnNewButton_2 = new JButton("Save Board");
		btnNewButton_2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				save();
			}

		});
		btnNewButton_2.setBounds(472, 215, 110, 23);
		frmTippinMineSearch.getContentPane().add(btnNewButton_2);

		JButton btnNewButton_3 = new JButton("Load Board");
		btnNewButton_3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				load();
			}
		});
		btnNewButton_3.setBounds(472, 249, 110, 23);
		frmTippinMineSearch.getContentPane().add(btnNewButton_3);
		btnNewButton_4 = new JButton("Continue");
		btnNewButton_4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					continueCom();
				} catch (FileNotFoundException e1) {
					e1.printStackTrace();
				} catch (ClassNotFoundException e1) {
					e1.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
		btnNewButton_4.setBounds(472, 147, 110, 23);
		frmTippinMineSearch.getContentPane().add(btnNewButton_4);
		JButton btnNewButton_5 = new JButton("Save Progress");
		btnNewButton_5.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				saveProgress();
			}
		});
		btnNewButton_5.setBounds(472, 181, 110, 23);
		frmTippinMineSearch.getContentPane().add(btnNewButton_5);

	}

	protected void continueCom() throws FileNotFoundException, IOException, ClassNotFoundException {
		int a = fileChooser.showOpenDialog(null);
		if (a == JFileChooser.APPROVE_OPTION) {
			ObjectInputStream loadFile;
			loadFile = new ObjectInputStream(new FileInputStream(fileChooser.getSelectedFile().getAbsolutePath()));
			System.out.println("1");
			Main.board = (int[][])loadFile.readObject();
			char[][] cG= (char[][])loadFile.readObject();
			spacesChecked = (int) loadFile.readObject();
			minesFound =(int) loadFile.readObject();
			for (int i = 0; i < 10; i++) {
				for (int j = 0; j < 10; j++) {
					buttonGrid[i][j].setText(String.valueOf(cG[i][j]));
				}
			}
			lblNewLabel.setText("Spaces Checked: " + spacesChecked);
			lblNewLabel1.setText("Mines Left: " + (Main.mineCount - minesFound));

					
		}


	}

	protected void load() {
		int a = fileChooser.showOpenDialog(null);
		if (a == JFileChooser.APPROVE_OPTION) {

			ObjectInputStream loadFile;
			try {
				loadFile = new ObjectInputStream(new FileInputStream(fileChooser.getSelectedFile().getAbsolutePath()));
				Main.board = (int[][]) loadFile.readObject();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			resetBoard();
		}

	}

	protected void save() {
		int a = fileChooser.showSaveDialog(null);
		if (a == JFileChooser.APPROVE_OPTION) {
			try {
				ObjectOutputStream saveFile = new ObjectOutputStream(
						new FileOutputStream(fileChooser.getSelectedFile().getAbsolutePath()));
				saveFile.writeObject(Main.board);
				saveFile.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	protected void saveProgress() {
		int[][] b = Main.board;
		char[][] bG = new char[b.length][b[0].length];
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				bG[i][j] = buttonGrid[i][j].getText().charAt(0);
			}
		}
		int a = fileChooser.showSaveDialog(null);
		if (a == JFileChooser.APPROVE_OPTION) {
			try {
				ObjectOutputStream saveFile = new ObjectOutputStream(
						new FileOutputStream(fileChooser.getSelectedFile().getAbsolutePath()));
				saveFile.writeObject(b);
				saveFile.writeObject(bG);
				saveFile.writeObject(spacesChecked);
				saveFile.writeObject(minesFound);
				saveFile.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

}
Main.java
package main;

import java.util.Arrays;
import java.util.Random;
import java.util.stream.IntStream;

import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

public class Main {
	static int dimensionX = 10;
	static int dimensionY = 10;
	static int mineCount = 10;
	static int[][] board = { { 1 } };

	public static void main(String[] args) {
		dimensionX = 10;
		dimensionY = 10;
		mineCount = 10;
		board = Main.minesweeper_numbers(Main.boardmaker(dimensionX, dimensionY, mineCount));

		try {
			for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
				if ("Nimbus".equals(info.getName())) {
					UIManager.setLookAndFeel(info.getClassName());
					break;
				}
			}
		} catch (Exception e) {
		}
		JW.main(args);
	}

	public static int[][] boardmaker(int dimensionX, int dimensionY, int mineCount) {
		int[][] mines = new int[dimensionX][dimensionY];
		for (int i = 0; i < dimensionX; i++) {
			for (int j = 0; j < dimensionY; j++) {
				mines[i][j] = 0;
			}
		}
		int sum = 0;
		Random rng = new Random();
		while (sum < mineCount) {
			mines[rng.nextInt(dimensionX)][rng.nextInt(dimensionY)] = 1;
			IntStream stream = Arrays.stream(mines).flatMapToInt(x -> Arrays.stream(x));
			sum = stream.sum();
		}
		for (int i = 0; i < dimensionX; i++) {
			for (int j = 0; j < dimensionY; j++) {
				System.out.print("" + mines[i][j] + " ");
			}
			System.out.println("");
		}
		System.out.println("------");

		return mines;

	}

	public static int[][] minesweeper_numbers(int[][] board) {
		int dimensionX = board.length;
		int dimensionY = board[0].length;
		int[][] countBoard = new int[dimensionX][dimensionY];
		for (int i = 0; i < dimensionX; i++) {
			for (int j = 0; j < dimensionY; j++) {
				if (board[i][j] == 1) {
					countBoard[i][j] = 9;
				} else {
					int spaceSum = 0;
					int xStart = Math.max(0, i - 1), xEnd = Math.min(i + 1, dimensionX - 1);
					int yStart = Math.max(0, j - 1), yEnd = Math.min(j + 1, dimensionY - 1);

					for (int k = xStart; k <= xEnd; k++) {
						for (int l = yStart; l <= yEnd; l++) {
							spaceSum += board[k][l];
						}
					}
					countBoard[i][j] = spaceSum;
				}
			}
		}
		for (int i = 0; i < dimensionX; i++) {
			for (int j = 0; j < dimensionY; j++) {
				System.out.print("" + countBoard[i][j] + " ");
			}
			System.out.println("");
		}

		return countBoard;

	}
}
This entry was posted in Uncategorized. Bookmark the permalink.