I created the famous Minesweeper-game in Java, for which I used java-swing to create the GUI.
Here's the code:
Control.java
: This class contains the main-method, which just opens the GUI.
import javax.swing.SwingUtilities;
public class Control {
//Just to start GUI
public static void main(String args[]) {
SwingUtilities.invokeLater(Gui::new);
}
}
Minesweeper.java
: This class is responsible for creating the field, placing the mines and calculating the "neighbor-mines".
import java.util.Random;
public class Minesweeper {
//Saves the places of the mines and the number of neighbor-mines
private int[][] neighbors = new int[Gui.size][Gui.size];
private boolean[][] memory = new boolean[Gui.size][Gui.size];
//Places the bombs/mines randomly in the field
public void placeBombs() {
Random random = new Random();
int i = 0;
while(i < Gui.size * 3) {
int x = random.nextInt(Gui.size);
int y = random.nextInt(Gui.size);
if(neighbors[x][y] == 0) {
neighbors[x][y] = -1;
i++;
}
}
}
//Counts the "neighbor-mines"
public void countNeighbors() {
for(int x = 0; x < Gui.size; x++) {
for(int y = 0; y < Gui.size; y++) {
memory[x][y] = true;
if(neighbors[x][y] != -1) {
neighbors[x][y] = 0;
for(int i = x - 1; i <= x + 1; i++) {
for(int j = y - 1; j <= y + 1; j++) {
if(i >= 0 && j >= 0 && i < Gui.size && j < Gui.size ) {
if(neighbors[i][j] == -1) {
neighbors[x][y]++;
}
}
}
}
}
}
}
}
public int getterNeighbors(int x, int y) {
return neighbors[x][y];
}
public boolean getterMemory(int x, int y) {
return memory[x][y];
}
public void setterMemory(int x, int y, boolean value) {
memory[x][y] = value;
}
}
Gui.java
: The name is pretty self-explanatory: This class is responsible for the GUI.
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Timer;
public class Gui {
Minesweeper minesweeper = new Minesweeper();
public static final int size = 15;
private JFrame frame = new JFrame("Minesweeper");
private JButton[][] buttons = new JButton[size][size];
JTextField counter = new JTextField();
final private int delay = 1000;
private int seconds = 0;
private int minutes = 0;
Timer timer;
//Timer
final private ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(seconds < 59) {
seconds++;
}
else {
minutes++;
seconds = 0;
}
counter.setText(minutes + " : " + seconds);
}
};
public Gui() {
minesweeper.placeBombs();
minesweeper.countNeighbors();
timer = new Timer(delay, taskPerformer);
timer.start();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JPanel panel1 = new JPanel();
//Creates the buttons
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
buttons[i][j] = new JButton();
buttons[i][j].setText("");
buttons[i][j].setBackground(Color.GRAY);
buttons[i][j].setName(i + "" + j);
buttons[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
final int x = i;
final int y = j;
//Right-click
buttons[i][j].addMouseListener(new MouseAdapter() {
boolean test = true;
public void mouseClicked(MouseEvent e ) {
if(SwingUtilities.isRightMouseButton(e) && buttons[x][y].isEnabled()) {
if(test) {
buttons[x][y].setBackground(Color.ORANGE);
test = !test;
}
else {
buttons[x][y].setBackground(Color.GRAY);
test = !test;
}
}
}
});
//Left-click
buttons[i][j].addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonClicked(x, y);
}
});
panel1.add(buttons[i][j]);
}
}
//Layout
frame.setSize(600,450);
panel.setLayout(new java.awt.FlowLayout());
panel.setSize(600, 400);
panel1.setLayout(new java.awt.GridLayout(size, size));
panel1.setPreferredSize(new Dimension(400, 400));
JPanel panel2 = new JPanel();
panel2.setLayout(new java.awt.GridLayout(2,1, 100, 100));
panel2.setSize(200,400);
//Restart button
JButton restart = new JButton();
restart.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.setVisible(false);
frame.dispose();
SwingUtilities.invokeLater(Gui::new);
}
});
restart.setText("Restart");
//More Layout
counter.setHorizontalAlignment(JTextField.CENTER);
counter.setEditable(false);
counter.setText("Counter");
Font font1 = new Font("SansSerif", Font.BOLD, 30);
counter.setFont(font1);
restart.setFont(font1);
panel2.add(counter);
panel2.add(restart);
panel.add(panel1, FlowLayout.LEFT);
panel.add(panel2);
frame.add(panel);
frame.setVisible(true);
}
private void buttonClicked(int i, int j) {
buttons[i][j].setEnabled(false);
buttons[i][j].setBackground(Color.WHITE);
if(minesweeper.getterNeighbors(i, j) == -1) {
youLost(i, j);
}
else if(minesweeper.getterNeighbors(i, j) == 0) {
zeroNeighbors(i, j);
checkWin();
}
else {
buttons[i][j].setText(Integer.toString(minesweeper.getterNeighbors(i, j)));
checkWin();
}
}
//Recursive function to reveal more fields
private void zeroNeighbors(int x, int y) {
minesweeper.setterMemory(x, y, false);
for(int i = x - 1; i <= x + 1; i++) {
for(int j = y - 1; j <= y + 1; j++) {
if(i >= 0 && j >= 0 && i < Gui.size && j < Gui.size) {
buttons[i][j].setEnabled(false);
buttons[i][j].setBackground(Color.WHITE);
buttons[i][j].setText(Integer.toString(minesweeper.getterNeighbors(i, j)));
if(minesweeper.getterNeighbors(i, j) == 0 && minesweeper.getterMemory(i, j)) {
zeroNeighbors(i, j);
}
}
}
}
}
private void youLost(int x, int y) {
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
buttons[i][j].setEnabled(false);
buttons[i][j].setBackground(Color.WHITE);
}
}
timer.stop();
buttons[x][y].setBackground(Color.RED);
JOptionPane.showMessageDialog(frame, "You Lost!");
}
private void checkWin() {
boolean test = true;
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
if(buttons[i][j].isEnabled() && minesweeper.getterNeighbors(i, j) != -1) {
test = false;
}
}
}
if(test) {
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
buttons[i][j].setEnabled(false);
buttons[i][j].setBackground(Color.WHITE);
}
}
timer.stop();
JOptionPane.showMessageDialog(frame, "You Won!");
}
}
}
I would appreciate any suggestions on improving the code and especially the general code-structure.