I am a java Beginner and I'm working on a MineSweeper project now. I encountered a strange problem where I cannot reset the level properly when clicking the "New" button.(Although it could work for the first few times). I think it might have something to do with Swing EDT but not too sure how to fix it exactly.
public class GUI extends JFrame {
private CenterPanel centerPanel;
public GUI() {
super("Minesweeper");
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
JMenuItem newGame = new JMenuItem("New");
centerPanel = new CenterPanel();
menuBar.add(menu);
menu.add(newGame);
newGame.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
centerPanel.removeAll();
centerPanel.setup();
centerPanel.revalidate();
centerPanel.repaint();
}
});
add(menuBar, BorderLayout.NORTH);
add(centerPanel, BorderLayout.CENTER);
pack();
}
}
public class Board {
private int width;
private int height;
private Square[][] board;
private int mines;
public Board(int x, int y, int z) {
width = x;
height = y;
mines = z;
board = new Square[x][y];
setup();
}
public void setup() {
for (int i = 0; i < mines; i++) {
int randRow = (int) (Math.random() * width);
int randColumn = (int) (Math.random() * height);
while (board[randRow][randColumn] == Square.MINE) {
randRow = (int) (Math.random() * width);
randColumn = (int) (Math.random() * height);
board[randRow][randColumn] = Square.MINE;
}
board[randRow][randColumn] = Square.MINE;
}
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int neighbourcount = 0;
if (board[i][j] != Square.MINE) {
if (i > 0 && j > 0 && board[i - 1][j - 1] == Square.MINE) {
neighbourcount++;
}
if (i > 0 && board[i - 1][j] == Square.MINE) {
neighbourcount++;
}
if (i > 0 && j < width - 1
&& board[i - 1][j + 1] == Square.MINE) {
neighbourcount++;
}
if (j > 0 && board[i][j - 1] == Square.MINE) {
neighbourcount++;
}
if (i < height - 1 && j > 0
&& board[i + 1][j - 1] == Square.MINE) {
neighbourcount++;
}
if (i < height - 1 && board[i + 1][j] == Square.MINE) {
neighbourcount++;
}
if (i < height - 1 && j < width - 1
&& board[i + 1][j + 1] == Square.MINE) {
neighbourcount++;
}
if (j < width - 1 && board[i][j + 1] == Square.MINE) {
neighbourcount++;
}
board[i][j] = Square.getByNumber(neighbourcount);
}
}
}
}
public Square getSquare(int i, int j) {
return board[i][j];
}
}
public enum Square {
ZERO(0), ONE(1), TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT(
8), MINE(9);
private int number;
private Square(int i) {
number = i;
}
public int getNumber() {
return number;
}
public static Square getByNumber(int i) {
for (Square sr : Square.values()) {
if (i == sr.getNumber()) {
return sr;
}
}
return null;
}
}
public class CenterPanel extends JPanel {
private JPanel[][] PanelArray;
private Board board;
public CenterPanel() {
setLayout(new GridLayout(9, 9));
setup();
}
public void setup(){
PanelArray= new JPanel[9][9];
board = new Board(9, 9, 10);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
final int row = i;
final int column = j;
final JButton button = new JButton();
PanelArray[i][j] = new JPanel();
PanelArray[i][j].setLayout(new GridLayout(1,1));
PanelArray[i][j].add(button);
button.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3) {
if (button.getText().equals("")) {
button.setText("F");
} else {
button.setText("");
}
}
if (e.getButton() == MouseEvent.BUTTON1) {
if (button.getText().equals("F")) {
} else {
int k = board.getSquare(row,
column).getNumber();
if (k == 0) {
PanelArray[row][column].remove(button);
revalidate();
repaint();
} else if (k == 9) {
removeAll();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int m = board.getSquare(i, j)
.getNumber();
if (m == 0) {
add(new JLabel(""));
} else if (m == 9) {
add(new JLabel(
" *"));
} else {
add(new JLabel(
" "
+ Integer
.toString(m)));
}
}
}
revalidate();
repaint();
} else {
PanelArray[row][column].remove(button);
PanelArray[row][column].add(new JLabel(" "
+ Integer.toString(k)));
revalidate();
repaint();
}
}
}
}
});
add(PanelArray[i][j]);
}
}
}
}
public class Main {
public static void main(String[] args) {
GUI game = new GUI();
game.setVisible(true);
}
}
Appreciate your help!
I would have preferred to put this as a comment, but there's really not enough place to put my explanation in there.
Your loop that fills your board with mines is flawed and can enter an infinite-loop--> your application will freeze (you can also probably see that one of your CPU is used at 100%).
Let's check that loop:
for (int i = 0; i < mines; i++) {
int randRow = (int) (Math.random() * width);
int randColumn = (int) (Math.random() * height);
while (board[randRow][randColumn] == Square.MINE) {
randRow = (int) (Math.random() * width);
randColumn = (int) (Math.random() * height);
board[randRow][randColumn] = Square.MINE;
}
board[randRow][randColumn] = Square.MINE;
}
At the end of the while, you call:
board[randRow][randColumn] = Square.MINE;
then the while loop will check the condition: board[randRow][randColumn] == Square.MINE
. Since you just assigned a MINE to that position, the condition is always true--> Here is your infinite loop.
You should have written something like:
Random r = new Random();
for (int i = 0; i < mines; i++) {
int randRow = r.nextInt(width);
int randColumn = r.nextInt(height);
while (board[randRow][randColumn] == Square.MINE) {
randRow = r.nextInt(width);
randColumn = r.nextInt(height);
// Don't do anything here !!!
}
// Now that you found an empty spot, put a mine
board[randRow][randColumn] = Square.MINE;
}