2009-12-16 3 views
1

JAVA- Hi, Je suis en train d'écrire un programme dragueur de mines (premier biggie) et je suis vraiment coincé. Le programme lui-même est composé de 2 classes (une pour la logique, une pour l'interface graphique) selon les spécifications que je dois suivre. J'ai fait pas mal dans les deux classes mais je n'ai pas fini non plus. Cependant, j'essaie de tester la mise en œuvre des méthodes d'appel d'une classe à l'autre et c'est là que je suis bloqué. Dans la classe GUI, j'essaie d'appeler la méthode openCell (int x, int y) dans la classe Logic chaque fois que l'utilisateur clique sur une case. Cette méthode de classe logique vérifie à son tour s'il existe une mine, un 0 ou un nombre sur le carré et appelle la méthode appropriée de la classe GUI. Les deux méthodes impliquées dans l'erreur sont les suivantes:NullPointer Exception lors de l'appel de la méthode à partir d'une classe de différence

GUI CLASS 
public void mouseClicked(MouseEvent e) { 
    for (int x = 0 ; x < width ; x++) { 
     for (int y = 0 ; y < height ; y++) { 
      if (e.getSource() == table[x][y]) {  
       if(e.getButton() == e.BUTTON1) { 
        MinesweeperLogic logicClass = new MinesweeperLogic(); 
        logicClass.isOpen(x, y); // <--------------------------- ERROR 
       }}}}} 

LOGIC CLASS 
boolean openCell(int x, int y) { 
isClicked[x][y] = true; 
    if(mine[x][y] == true && flag[x][y]==false) { 
     return false; 
    } else if(neighborBombs(x, y) > 0 && flag[x][y]==false) { 
     return true; 
    }else { 
      marked = true; 
      return marked; 
    }} 

ci-après le rapport d'erreur que je reçois une fois que l'utilisateur clique sur une boîte dans le jeu (il ne l'attraper lors de la compilation du code):

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at MinesweeperLogic.isOpen(MinesweeperLogic.java:117) 
at MineSweeperGUI.mouseClicked(MineSweeperGUI.java:126) 
at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:253) 
at java.awt.Component.processMouseEvent(Component.java:6266) 
at javax.swing.JComponent.processMouseEvent(JComponent.java:3255) 
at java.awt.Component.processEvent(Component.java:6028) 
at java.awt.Container.processEvent(Container.java:2041) 
at java.awt.Component.dispatchEventImpl(Component.java:4630) 
at java.awt.Container.dispatchEventImpl(Container.java:2099) 
at java.awt.Component.dispatchEvent(Component.java:4460) 
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574) 
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4247) 
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168) 
at java.awt.Container.dispatchEventImpl(Container.java:2085) 
at java.awt.Window.dispatchEventImpl(Window.java:2475) 
at java.awt.Component.dispatchEvent(Component.java:4460) 
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) 
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) 
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) 

Enfin, l'ensemble (encore incomplet à ce stade) code pour deux classes si besoin est. (Les méthodes de la classe logique sont requises pour effectuer des actions spécifiques selon les instructions du projet et ne doivent pas avoir d'interaction utilisateur dans la classe logique). Je ne peux pas comprendre exactement ce qui cause l'erreur. Toute orientation serait grandement appréciée. (J'espère que ce n'est pas quelque chose de vraiment évident parce que j'ai passé les dernières heures à essayer de comprendre cela même si j'ai eu la grippe!

import java.awt.* ; 
import java.awt.event.* ; 
import java.awt.geom.* ; 
import javax.swing.* ; 
import javax.swing.event.* ; 

public class MineSweeperGUI extends JFrame implements ActionListener, MouseListener { 
int width = 10; 
int height = 10; 
JPanel p = new JPanel(); 
JButton[][] table = new JButton[width][height]; 

public void MineSweeper() { 
    MinesweeperLogic logicClass = new MinesweeperLogic(); 
    logicClass.startNewGame(width, height); 
    JButton[] button = new JButton[width*height]; 
    GridLayout layout = new GridLayout (width, height) ; 
    p.setLayout(layout); 
    for(int x = 0 ; x < width ; x++) { 
     for(int y = 0 ; y < height ; y++) { 
      table[x][y] = new JButton(); 
      table[x][y].setPreferredSize(new Dimension(25,25)); 
      table[x][y].addMouseListener (this); 
      p.add(table [x] [y]); 
     } 
    }  
    this.add(p); 
    this.pack(); 
    this.setVisible(true); 
} 


public void mouseClicked(MouseEvent e) { 
    for (int x = 0 ; x < width ; x++) { 
     for (int y = 0 ; y < height ; y++) { 
      if (e.getSource() == table[x][y]) {  
       if(e.getButton() == e.BUTTON1) { 
        MinesweeperLogic logicClass = new MinesweeperLogic(); 
        logicClass.isOpen(x, y); //<-------------------------------------- 
       } 
      } 
     } 
    } 
} 
public void gameover(int x, int y) { 
    table[x][y].setText("*"); 
} 

public static void main(String[]args) { 
    MineSweeperGUI guiClass = new MineSweeperGUI(); 
    guiClass.MineSweeper(); 
}}  


public void actionPerformed(ActionEvent e) { 
} 

public void mouseEntered(MouseEvent e) { 
} 

public void mousePressed(MouseEvent e) { 
} 

public void mouseExited(MouseEvent e) { 
} 

public void mouseReleased(MouseEvent e) { 
} 




public class MinesweeperLogic { 

private int w, h, maxBombs, bombsremaining; 
public int width, height; 
private boolean mine[][]; 
private boolean flag[][]; 
private boolean isClicked[][]; 
private boolean isZero[][]; 
private boolean marked; 



public void startNewGame(int width, int height) { 
    w = width; 
    h = height; 
    flag = new boolean[w][h]; 
    isZero = new boolean[w][h]; 
    isClicked = new boolean[w][h]; 
    mine = new boolean[w][h]; 
    maxBombs =(int) Math.floor (width*height*0.15); 
    bombsremaining = maxBombs; 
    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; 
     } 
    } 
} 


int getWidth() { 
    return w; 
} 


int getHeight() { 
    return h; 
} 


boolean openCell(int x, int y) { // <--------------------------------------------- 
    //MineSweeperGUI guiClass = new MineSweeperGUI(); 
    isClicked[x][y] = true; 
    if(mine[x][y] == true && flag[x][y]==false) { 
     //guiClass.gameover(x, y); 
     return false; 
    } else if(neighborBombs(x, y) > 0 && flag[x][y]==false) { 
     return true; 
    } else { 
      marked = true; 
      return marked; 
    }} 


boolean markCell(int x, int y) { 
    if(flag[x][y] == true) { 
      flag[x][y] = false; 
      isClicked[x][y] = false; 
      bombsremaining++; 
      marked = false; 
      return marked; 
     } else { 
      flag[x][y] = true; 
      isClicked[x][y] = true; 
      bombsremaining--; 
       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 
     int surBombs = 0; 
      for (int q = x - 1 ; q <= x + 1 ; q++) { 
       for (int w = y - 1 ; w <= y + 1 ; w++) { 
        while (true) { 
         if (q < 0 || w < 0 || q >= w || w >= h) { 
          break; 
         } 
         if (mine[q][w] == true) { 
          surBombs++; 
          break; 
         } 
        } 
       } 
      } 
     return surBombs; 
     } 
    } 

Répondre

11

Que diriez-vous que:

  1. regard sur la première ligne de votre stacktrace d'exception, et voir quelle classe et quelle ligne le problème se produit
  2. aller à cette ligne, et voir quels objets pourrait être " null » à cet endroit
  3. découvrir pourquoi l'objet est nul n'a pas une valeur assgined
  4. s'il y a plus d'un objet qui pourrait être nulle, vous pouvez les System.out.println(), pour voir whchi on est.
+1

Bien que cela aidera à corriger le NullPointerException, le code en question est si mauvais qu'il ne sera pas plus proche d'avoir un jeu de dragueur de mines en cours d'exécution. – tster

+1

étape par étape :) – Bozho

+2

Apprendre à utiliser le débogueur serait préférable à System.out.println – rob

0

Il serait utile de connaître le numéro de ligne 117 de la classe logique. Ma conjecture serait soit mine, mine[x], flagged ou flagged[x] est nulle. Cela dit, votre technique de "boucler toute la table pour voir lequel a été cliqué" ne me semble pas particulièrement inspirée.

EDIT: En fait, le problème est que le tableau isOpen est nul, car vous venez juste d'instancier la classe.

EDIT2: Très bien, donc c'est l'un de ceux que j'ai énumérés initialement. Ma conjecture serait tous, parce que vous venez d'instancier la classe, et il utilise le constructeur par défaut de rien.

+0

Il ya une flèche colorée pointant sur ce qui est probablement la ligne 117 dans le premier morceau de code. –

+1

Sauf qu'il ne pointe PAS sur cette ligne. –

+0

Il ne pointe pas du tout sur cette ligne, il indique en fait une ligne dans * une classe complètement différente *. –

2

Les tableaux (indicateur, isZero, isClicked) ne sont pas initialisés et sont null lorsque vous essayez de les utiliser. Vous avez besoin de la classe GUI pour contenir une instance de la classe logique et utilisez toujours cette même instance. Sinon, chaque action GUI aura lieu sur un jeu différent!

+0

J'accepte. Vous créez une nouvelle instance de MinesweeperLogic chaque fois que vous cliquez sur la souris. Vous devez conserver l'instance que vous créez dans la méthode MineSweeper(). – goatlinks

4

Votre stacktrace vous dit ceci:

Exception dans le thread "AWT-EventQueue-0" java.lang.NullPointerException à MinesweeperLogic.isOpen (MinesweeperLogic.java:117)

Alors vous pouvez aller à la ligne 117 et déterminer quelles références pourraient éventuellement être nulles. (Il semble que vous ayez ajouté une ligne à 117 après que la pile ait été prise, puis j'ai mis en commentaire la nouvelle ligne, donc je vais sortir d'ici et dire que la pile fait référence à ce qu'on appelle maintenant la ligne 118 : isClicked[x][y] = true;) La seule chose qui pourrait être nulle, dans ce cas, est isClicked[][].

En creusant un peu plus loin, nous pouvons voir que vous initialisez isClicked dans startNewGame(), mais évidemment cette instance est perdue. Cela se produit pour deux raisons: premièrement, la classe logique de votre constructeur sort du champ d'application parce que ce n'est pas un membre de la classe. Deuxième (et c'était probablement une tentative échouée pour résoudre le premier problème), dans mouseClicked, vous créez un nouveau MinesweeperLogic (avec un null isClicked nouvellement créé) au lieu d'utiliser celui que vous avez précédemment créé dans votre constructeur MineSweeper().

Il y a plusieurs autres refactorings que vous devriez faire pour nettoyer votre code, mais faire de logicClass un membre et supprimer l'instanciation en double devrait résoudre le problème immédiat.

Il peut être utile pour vous d'utiliser le débogueur et de résoudre vous-même le problème pour comprendre exactement ce qui se passe.

0

Vous dites que l'erreur se produit dans la méthode mouseClicked(), mais le stacktrace montre différemment:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at MinesweeperLogic.isOpen(MinesweeperLogic.java:117) 
at MineSweeperGUI.mouseClicked(MineSweeperGUI.java:126) 

Cela dit que la NPE est survenue sur la ligne 117 de MineSweeperLogic. Utilisez soit votre débogueur sur cette ligne, ou insérez des instructions d'impression pour déterminer ce qui est nul, à partir de là, vous pouvez déterminer pourquoi.

Questions connexes