消息对话框重新出现单击确定按钮后

时间:2010-01-05 11:42:51

标签: java dialog joptionpane minesweeper

之前得到了很好的帮助后,我完成了我的扫雷游戏。但是,有一个问题我无法弄清楚。游戏本身运行良好,但是,我有一个选项让用户改变难度设置(初学者,中级,高级)这让我感到悲伤。用户从JMenuBar中选择“Game”,然后从下拉菜单中选择“Change Difficulty”。这将调用方法selectDifficulty(),它打开一个JOptionMessageBox,它使用JRadioButtons让用户选择4个选项中的一个(第4个是Custom - 但是我还没有实现它)。用户第一次更改难度模式时,该对话框似乎正常工作。然而,当用户试图第二次或更多次改变难度时,游戏实施设置然后再次出现对话框并且促使用户再次选择难度。这有时在离开之前重复两次,而在其他时间最多重复4或5次。 我很感激任何帮助,因为我不知道为什么会这样。

另外,我也很感激如何改善难度设置的变化。目前,代码删除了JPanel和minefield(由Buttons组成)并使用新的难度设置重新实例化按钮/ Japanels。有没有办法让这个更有效率?

有一个逻辑类和一个GUI玻璃。上述两个问题都存在于GUI类中。

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

完整代码: 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) {}
}    

逻辑课程:     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 ("<|");
            }
        }
    }
}
}

3 个答案:

答案 0 :(得分:1)

您在MineSweeper(width, height)的{​​{1}}结束时拨打start(因为它是一种方法应该是小写)。

selectDifficulty创建所有新组件。 MineSweeper未创建新版,因此您向其添加另一个 optionsButton。当您按下按钮时,每个ActionListener都会被调用,因此ActionListener被调用的次数越来越多。

最简单的解决方法是将此selectDifficulty添加到ActionListener的构造函数中,但您应该重构源代码,以便尽可能只创建一次所有组件。至少整个菜单应该转到构造函数。

答案 1 :(得分:0)

尝试设置菜单组件(JMenuBar和子项)一次,而不是每次调用MineSweeper。我认为这是一个构造函数,顺便说一句,所以它也可能会混淆其他Java开发人员。

这是因为actionPerformed可能会被多次调用。

答案 2 :(得分:0)

你使它变得非常复杂,Java是一种面向对象的语言,试图根据这些对象的属性/动作将你的工作分成对象。

无论如何,两个建议你的难度对话。

  • 要么将3个难点放在菜单本身。因此,下拉菜单包含初级,中级或硬模式,以及打开JPanel对话框的自定义模式。
  • 或者您继续使用您的方法,但需要进行一些更改。主要是将消息对话框从它们的主GUI分离并创建一个新类,让我们说自己扩展JDialog的OptionsDialog。在OptionsDialog的构造函数中,发送对父框架的引用。设置难度后,在父母上调用一个方法来设置难度。