2010-01-05 20 views
0

Après avoir obtenu une aide précieuse, j'ai terminé mon jeu Démineur. Cependant, il y a un problème que je ne peux pas comprendre. Le jeu lui-même fonctionne bien, cependant, j'ai une option pour l'utilisateur de changer le réglage de la difficulté (débutant, intermédiaire, avancé) qui me donne du chagrin. L'utilisateur sélectionne "Jeu" dans le JMenuBar puis sélectionne "Changer la Difficulté" dans le menu déroulant. Cela appelle la méthode selectDifficulty() qui ouvre un JOptionMessageBox qui utilise JRadioButtons pour que l'utilisateur sélectionne l'une des 4 options (la 4ème étant Personnalisée - mais je ne l'ai pas implémentée pour l'instant). La boîte de dialogue semble fonctionner correctement la première fois que l'utilisateur change de mode de difficulté. Cependant, lorsque l'utilisateur tente de changer de difficulté une deuxième fois ou plus, le jeu implémente le réglage, puis la boîte de dialogue réapparaît et invite l'utilisateur à sélectionner à nouveau la difficulté. Cela se répète parfois deux fois avant de partir, et d'autres fois jusqu'à 4 ou 5 fois. J'apprécierais n'importe quelle aide car je ne sais pas pourquoi ceci se produit.La boîte de dialogue Message réapparaît après avoir cliqué sur le bouton OK

En outre, j'apprécierais aussi quelques conseils sur la façon dont je pourrais améliorer la façon dont les paramètres de difficulté changent. En l'état, le code supprime le JPanel et le champ de mines (fait de boutons) et instancie à nouveau les boutons/Japanels avec le nouveau paramètre de difficulté. Y a-t-il un moyen de rendre cela plus efficace?

Il existe une classe logique et un verre GUI. Les deux problèmes ci-dessus sont présents dans la 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); 
     }    
}  

CODE COMPLET: GUI CLASSE

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

CLASSE LOGIC:. 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 ("<|"); 
      } 
     } 
    } 
} 
} 
+0

@ newBie01: Vous pouvez upvoter des réponses utiles et accepter le meilleur/le plus utile. –

Répondre

1

Vous appelez MineSweeper(width, height) (doit être en minuscule comme il est une méthode) à la fin de start, que vous appelez dans selectDifficulty.

MineSweeper crée tous vos composants nouveaux. optionsButton n'est pas créé nouveau, donc vous ajoutez un autreActionListener à lui. Chaque ActionListener est appelée lorsque vous appuyez sur le bouton, de sorte que selectDifficulty est appelée de plus en plus de fois. La solution de contournement la plus simple consiste à ajouter ce ActionListener au constructeur de MineSweeperGUI, mais vous devez refactoriser votre source pour créer tous les composants une seule fois si possible. Au moins tout le menu devrait aller au constructeur.

+0

Ouais, ça a marché. Je vous remercie!! – newBie01

0

Essayez de régler votre composant de menu (JMenuBar et enfants) une fois au lieu de chaque fois que MineSweeper est appelé. Je pensais que c'était un constructeur, btw, donc cela peut aussi dérouter les autres développeurs Java.

Cela est dû au fait que le actionPerformed peut être invoqué plusieurs fois.

0

Vous rendez la chose très compliquée, Java est un langage orienté objet, essayez de séparer votre travail en objets en fonction des propriétés/actions de ces objets.

Quoi qu'il en soit, deux suggestion pour votre boîte de dialogue de difficulté.

  • Soit vous mettez les 3 difficultés dans le menu lui-même. Ainsi, le menu déroulant, a des modes débutant, moyen ou difficile, avec un mode personnalisé qui ouvre une boîte de dialogue JPanel.
  • Ou Vous continuez votre méthode mais devrez faire quelques changements. Principalement divisé le dialogue de message de leur interface graphique principale et créer une nouvelle classe, disons OptionsDialog qui étend JDialog par lui-même. Dans le constructeur de OptionsDialog, envoyez une référence à l'image parent. Après avoir réglé la difficulté, appelez une méthode sur le parent pour régler la difficulté.
+0

merci pour la réponse. Je ne veux pas créer une autre classe car l'instruction était de créer deux classes seulement. Quant à l'ajout des 3 difficultés dans le menu lui-même - j'avais d'abord essayé de le faire mais le menu déroulant se cacherait derrière le champ de mines après le début du jeu. J'ai essayé de comprendre le problème un peu mais j'ai ensuite décidé d'ajouter la boîte de dialogue. Une idée de comment je pourrais contourner ce problème? – newBie01