Domanda

Dopo aver ottenuto un buon aiuto in precedenza, ho completato il mio gioco del campo minato. Tuttavia, v'è un problema che non riesco a capire. Il gioco in sé funziona bene, però, ho la possibilità per l'utente di modificare l'impostazione di difficoltà (principiante, intermedio, avanzato), che mi sta dando il dolore. L'utente seleziona "Game" dal JMenuBar e poi seleziona "Modifica di difficoltà" dal menu a discesa. Questo chiama il metodo selectDifficulty () che apre una JOptionMessageBox che utilizza JRadioButtons per arrivare all'utente di selezionare una delle 4 opzioni (il 4 ° essendo personalizzato - tuttavia non ho implementato che come ancora). La finestra di dialogo sembra funzionare bene la prima volta che l'utente cambia modalità di difficoltà. Tuttavia, quando l'utente tenta di cambiare la difficoltà di una seconda volta o più, il gioco implementa l'impostazione e quindi la finestra di dialogo riappare e promts all'utente di selezionare di nuovo la difficoltà. Questo a volte si ripete due volte prima di andare via, e altre volte fino a 4 o 5 volte. Gradirei qualsiasi aiuto come non so perché questo sta accadendo.

Inoltre, vorrei anche apprezzare qualche consiglio su come potrei migliorare come i livelli di difficoltà sono il cambiamento. Così com'è, il codice rimuove il JPanel e il campo minato (fatta di pulsanti) e ri un'istanza i pulsanti / Japanels con il nuovo livello di difficoltà. C'è un modo per rendere questo più efficiente?

C'è una classe di logica e un bicchiere GUI. Entrambe le questioni di cui sopra sono presenti nella classe 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);
        }             
}    

codice completo: 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 ("<|");
            }
        }
    }
}
}
È stato utile?

Soluzione

Si chiama MineSweeper(width, height) (dovrebbe essere minuscolo in quanto è un metodo) al termine del start, che voi chiamate in selectDifficulty.

MineSweeper crea tutti i componenti nuovi. optionsButton non si crea nuovo, quindi si aggiunge altro ActionListener ad esso. Ogni ActionListener viene chiamata quando si preme il pulsante, in modo selectDifficulty si chiama più e più volte.

La soluzione più semplice è quello di mettere l'aggiunta di questa ActionListener al costruttore di MineSweeperGUI, ma si dovrebbe refactoring la vostra fonte per creare tutti i componenti una sola volta, se possibile. Almeno l'intero menu dovrebbe andare al costruttore.

Altri suggerimenti

Prova a impostare il componente menu (JMenuBar e bambini) una volta al posto di ogni MineSweeper volta che viene chiamato. Ho pensato che era un costruttore, btw, quindi potrebbe confondere altri sviluppatori Java troppo.

Questo perché il actionPerformed può essere sempre invocato più di una volta.

Si stanno facendo molto più complicato, Java è un linguaggio orientato agli oggetti, cercare di separare il vostro lavoro in oggetti basati su proprietà / azioni di questi oggetti.

In ogni caso, due suggerimenti per il vostro dialogo difficoltà.

  • O si mettono i 3 difficoltà nel menu stesso. Così il menu a discesa, ha principiante, medio o difficile modalità, con una modalità personalizzata che apre una finestra di JPanel.
  • Oppure continua a tuo metodo, ma sarà necessario fare alcune modifiche. Principalmente dividere la finestra di fuori di essi GUI principale messaggio e creare una nuova classe, diciamo che si estende OptionsDialog JDialog da solo. Nel costruttore del OptionsDialog inviare un riferimento al telaio principale. Dopo aver impostato la difficoltà chiamare un metodo sul genitore per impostare la difficoltà lì.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top