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.




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;
}
}