Hi, After getting good help previously, I have completed my Minesweeper game. However, there is one problem that I can't figure out. The game itself works fine, however, I have an option for the user to change difficulty setting (beginner, intermediate, advanced) which is giving me grief. The user selects "Game" from the JMenuBar and then selects "Change Difficulty" from the drop down menu. This calls the method selectDifficulty() which opens a JOptionMessageBox which uses JRadioButtons to get the user to select one of the 4 options (the 4th being Custom - however I have not implemented that as of yet). The dialog box seems to work fine the first time the user changes difficulty mode. However, when the user attempts to change difficulty a 2nd time or more, the game implements the setting and then the dialogue box reappears and promts the user to select the difficulty again. This sometimes repeats twice before going away, and at other times up to 4 or 5 times. I would appreciate any help as I do not know why this is happening.
Also, I would also appreciate some advice on how I could improve how the difficulty settings are change. As it stands, the code removes the JPanel and the minefield(made of Buttons) and re instantiates the buttons/Japanels with the new difficulty setting. Is there a way to make this more efficient?
There is a logic class and a GUI glass. Both of the above issues are present in the GUI class.
private void selectDifficulty() {
group.add(b1);
group.add(b2);
group.add(b3);
group.add(b4);
b1.setSelected(true);
Object[] array = {new JLabel("Select Difficulty"),b1,b2,b3,b4};
JOptionPane.showMessageDialog(null, array);
if (b1.isSelected()) {
if (mode == 1){
rw = 9;
rh = 9;
mode = 1;
}else if(mode == 2){
rw = 15;
rh = 15;
mode = 1;
}else {
rw = 20;
rh = 20;
mode = 1;
}
start(9,9);
}else if (b2.isSelected()) {
if (mode == 1){
rw = 9;
rh = 9;
mode = 2;
}else if(mode == 2){
rw = 15;
rh = 15;
mode = 2;
}else {
rw = 20;
rh = 20;
mode = 2;
}
start(15,15);
}else if (b3.isSelected()) {
if (mode == 1){
rw = 9;
rh = 9;
mode = 3;
}else if(mode == 2){
rw = 15;
rh = 15;
mode = 3;
}else {
rw = 20;
rh = 20;
mode = 3;
}
start(20,20);
}
}
COMPLETE CODE: GUI CLASS
import java.awt.* ;
import java.awt.event.* ;
import javax.swing.* ;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
public class MineSweeperGUI extends JFrame implements MouseListener {
MinesweeperLogic logicClass = new MinesweeperLogic();
JButton newGameButton = new JButton ("New Game");
JMenuItem optionsButton = new JMenuItem ("Change Difficulty");
JRadioButton b1 = new JRadioButton ("Beginner: 9 X 9 Grid (10 Mines)");
JRadioButton b2 = new JRadioButton ("Intermediate: 15 X 15 Grid (36 Mines)");
JRadioButton b3 = new JRadioButton ("Advanced: 20 X 20 Grid (80 Mines)");
JRadioButton b4 = new JRadioButton ("Custom");
ButtonGroup group = new ButtonGroup();
JMenuItem aboutButton = new JMenuItem ("About Minesweeper");
JPanel p = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
int w, h, rw = 0, rh = 0, mode = 1;
public void MineSweeper(int width, int height) {
//setupI();
w = width;
h = height;
logicClass.startNewGame(w, h);
GridLayout layout = new GridLayout (w, h);
p2.setLayout(new BorderLayout());
p.setLayout(layout);
p2.add(p, BorderLayout.CENTER);
for(int x = 0 ; x < w ; x++) {
for(int y = 0 ; y < h ; y++) {
logicClass.label[x][y] = new Button();
logicClass.label[x][y].setPreferredSize(new Dimension(20,20));
logicClass.label[x][y].setBackground(new Color(33,58,156));
logicClass.label[x][y].addMouseListener (this);
p.add(logicClass.label[x][y]);
}
}
JMenuBar mb = new JMenuBar();
JMenu m = new JMenu("Game");
JMenu m2 = new JMenu("Help");
m.add(optionsButton);
m2.add(aboutButton);
mb.add(m);
mb.add(m2);
p2.add(p3, BorderLayout.PAGE_START);
newGameButton.setPreferredSize (new Dimension(87, 20));
newGameButton.setFont(new Font("sansserif",Font.BOLD,11));
newGameButton.setForeground(Color.black);
newGameButton.setBackground(new Color(235,52,52));
Border thickBorder = new LineBorder(Color.black, 2);
newGameButton.setBorder(thickBorder);
p3.add(newGameButton);
newGameButton.addMouseListener(this);
optionsButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
selectDifficulty();
}
});
this.setJMenuBar(mb);
this.add(p2);
this.pack();
this.setVisible(true);
}
private void start(int width, int height){
p2.remove(p);
for(int x = 0 ; x < rw ; x++) {
for(int y = 0 ; y < rh ; y++) {
p.remove(logicClass.label[x][y]);
}
}
p2.remove(p3);
p3.remove(newGameButton);
this.remove(p2);
MineSweeper(width, height);
}
private void lose() {
JOptionPane.showMessageDialog(this, "GAME OVER - YOU LOSE! Starting New Game", "Game Over", JOptionPane.INFORMATION_MESSAGE);
newGame();
}
private void win() {
JOptionPane.showMessageDialog(this, "YOU WIN! Starting New Game", "CONGRATULATIONS", JOptionPane.INFORMATION_MESSAGE);
newGame();
}
private void newGame() {
if(mode==1){
rw = 9;
rh = 9;
start(9,9);
}else if(mode==2){
rw = 15;
rh = 15;
start(15,15);
}else{
rw = 20;
rh = 20;
start(20,20);
}
}
public void mouseClicked(MouseEvent e) {
if(e.getSource() == newGameButton) {
if(e.getButton() == e.BUTTON1) {
newGame();
}
}
for (int x = 0 ; x < w; x++) {
for (int y = 0 ; y < h; y++) {
if(e.getSource() == logicClass.label[x][y]) {
if(e.getButton() == e.BUTTON1) {
if(logicClass.openCell(x, y) == false) {
lose();
} else {
for (int q = 0; q < w; q++) {
for (int j = 0; j < h; j++) {
if (logicClass.label[q][j].getBackground()==Color.green) {
win();
}
}
}
}
}else if(e.getButton() == e.BUTTON3) {
logicClass.markCell(x, y);
}
}
}
}
}
private void selectDifficulty() {
group.add(b1);
group.add(b2);
group.add(b3);
group.add(b4);
b1.setSelected(true);
Object[] array = {new JLabel("Select Difficulty"),b1,b2,b3,b4};
JOptionPane.showMessageDialog(null, array);
if (b1.isSelected()) {
if (mode == 1){
rw = 9;
rh = 9;
mode = 1;
}else if(mode == 2){
rw = 15;
rh = 15;
mode = 1;
}else {
rw = 20;
rh = 20;
mode = 1;
}
start(9,9);
}else if (b2.isSelected()) {
if (mode == 1){
rw = 9;
rh = 9;
mode = 2;
}else if(mode == 2){
rw = 15;
rh = 15;
mode = 2;
}else {
rw = 20;
rh = 20;
mode = 2;
}
start(15,15);
}else if (b3.isSelected()) {
if (mode == 1){
rw = 9;
rh = 9;
mode = 3;
}else if(mode == 2){
rw = 15;
rh = 15;
mode = 3;
}else {
rw = 20;
rh = 20;
mode = 3;
}
start(20,20);
}
}
public static void main(String[]args) {
MineSweeperGUI guiClass = new MineSweeperGUI();
guiClass.MineSweeper(9,9);
}
public void mouseEntered(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
LOGIC CLASS: import java.awt.* ;
public class MinesweeperLogic {
public int width, height;
private int w, h, maxBombs;
private boolean mine[][];
private boolean flag[][];
private boolean isClicked[][];
private boolean isZero[][];
private boolean marked;
MineSweeperGUI guiClass;
Button[][] label;
private int surBombs;
private String temp;
private double mineRatio;
public void startNewGame(int width, int height) {
w = width;
h = height;
label = new Button[w][h];
mine = new boolean[w][h];
flag = new boolean[w][h];
isClicked = new boolean[w][h];
isZero = new boolean[w][h];
if ( (w*h) <= 81) {
mineRatio = 0.13;
}else if ( (w*h) <= 255) {
mineRatio = 0.16;
}else {
mineRatio = 0.2;
}
maxBombs = (int) Math.floor (w * h * mineRatio);
for (int i = 0; i < maxBombs; i++) {
int x = (int) (Math.random() * w);
int y = (int) (Math.random() * h);
if (mine[x][y] == false) {
mine[x][y] = true;
isClicked[x][y] = false;
flag[x][y] = false;
isZero[x][y] = false;
} else {
i--;
}
}
}
int getWidth() {
return w;
}
int getHeight() {
return h;
}
boolean openCell(int x, int y) {
isClicked[x][y] = true;
if (mine[x][y] == true && flag[x][y] == false) {
lose();
return false;
} else if (getValue(x, y) > 0 && flag[x][y] == false) {
temp = Integer.toString (getValue(x, y));
label[x][y].setLabel (temp);
label[x][y].setBackground (new Color (111,184,252));
checkWin();
return true;
} else if (getValue(x, y) == 0 && flag[x][y] == false) {
for (int q = x-1; q <= x+1; q++) {
if(q < 0 || q >= w) {
continue;
}
for (int i = y-1; i <= y+1; i++) {
if(i < 0 || i >= h || flag[q][i] == true) { // makes sure that it wont have an error for buttons next to the wall
continue;
}
label[q][i].setBackground(new Color (111,184,252));
if (getValue(q, i) != 0) { // opens surrounding cells that have mines around them (max 8 cells)
temp = Integer.toString (getValue(q, i));
label[q][i].setLabel (temp);
isClicked[q][i] = true;
} else {
for (int k = x-1; k <= x+1; k++) {
if(k < 0 || k >= w) {
continue;
}
for (int m = y-1; m <= y+1; m++) {
if (m < 0 || m >= h || flag[k][m] == true) { // makes sure that it wont have an error for buttons next to the wall
continue;
}
if (isClicked[k][m] == false && getValue(k, m) == 0) { // recursively continues to open all surrounding cells with no mines around them
openCell(k, m);
}
}
}
}
}
}
checkWin();
return true;
} else {
return true;
}
}
boolean markCell(int x, int y) {
if (flag[x][y] == true) {
flag[x][y] = false;
label[x][y].setLabel ("");
label[x][y].setForeground (Color.black);
label[x][y].setFont (new Font (null, Font.PLAIN, 12));
return false;
}
if (isClicked[x][y] == false && flag[x][y] == false) {
flag[x][y] = true;
label[x][y].setFont (new Font ("sansserif", Font.BOLD, 14));
label[x][y].setLabel ("<|");
label[x][y].setForeground (Color.red);
}
if (mine[x][y] == true) {
return true;
} else {
return false;
}
}
boolean isOpen(int x, int y) {
if (isClicked[x][y] == false) {
return false;
} else {
return true;
}
}
boolean isMarked(int x, int y) {
if (flag[x][y] == true) {
return true;
} else {
return false;
}
}
int getValue(int x, int y) {
if (mine[x][y] == true) {
return -1;
} else {
return neighborBombs(x, y);
}
}
private int neighborBombs(int x, int y) { // checks surrounding 8 squares for number of bombs (it does include itself, but has already been checked for a bomb so it won't matter)
surBombs = 0;
for (int q = x-1; q <= x+1; q++) {
if (q < 0 || q >= w) {
continue;
}
for (int i = y-1; i <= y+1; i++) {
if (i < 0 || i >= h) { // makes sure that it wont have an error for buttons next to the wall
continue;
}
if (mine[q][i] == true) {
surBombs++;
}
}
}
return surBombs;
}
private void lose() {
for (int q = 0; q < w; q++) {
for (int j = 0; j < h; j++) {
if (mine[q][j] == true) {
if (label[q][j].getLabel().equals ("<|")) {
label[q][j].setBackground (Color.green);
} else {
label[q][j].setBackground (Color.red);
label[q][j].setLabel ("*");
label[q][j].setForeground (Color.black);
}
}
}
}
}
private void checkWin() {
int count = 0;
int count2 = 0;
for (int i = 0; i < w; i++){
for (int j = 0; j < h; j++) {
if (isClicked[i][j] == true){
count++;
}
if (mine[i][j] == true){
count2++;
}
}
}
if ( (count + count2) == (w * h) ){
win();
}
}
private void win() {
for (int q = 0; q < w; q++) {
for (int j = 0; j < h; j++) {
if (mine[q][j] == true) {
label[q][j].setBackground (Color.green);
label[q][j].setForeground (Color.red);
label[q][j].setFont (new Font ("sansserif", Font.BOLD, 14));
label[q][j].setLabel ("<|");
}
}
}
}
}