Pregunta

Java- hola, estoy escribiendo un programa de videas de minas (primer biggie) y estoy realmente atrapado. El programa en sí se compone de 2 clases (una para la lógica, una para la GUI) según las especificaciones que debo seguir. He hecho un poco en ambas clases, pero tampoco he terminado. Sin embargo, estoy intentando probar la implementación de métodos de llamadas de una clase a otra y ahí es donde me quedo atascado. Desde la clase GUI, intento llamar al método OpenCell (int x, int y) en la clase lógica cada vez que el usuario hace clic en un cuadro. Ese método de clase lógica verificará a su vez para ver si hay una mina, un 0 o un número en el cuadrado y llamar al método apropiado de la clase GUI. Los dos métodos involucrados en el error son los siguientes:

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

El siguiente es el informe de error que recibo una vez que el usuario hace clic en un cuadro en el juego (lo hace para atraparlo al compilar el código):

 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)

Finalmente, todo el código (aunque incompleto en este punto) para dos clases hasta ahora si es necesario. (Los métodos en la clase lógica son necesarios para realizar acciones específicas según las instrucciones del proyecto y no deben tener interacción de usuario en la clase lógica). No puedo entender qué está causando exactamente el error. Cualquier orientación sería muy apreciada. (¡Ojalá no sea algo realmente obvio porque he pasado las últimas horas tratando de resolver esto a pesar de que tengo la gripe! LOL).

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;
        }
    }
¿Fue útil?

Solución

Qué hay sobre eso:

  1. Mire la primera línea de su excepción StackTrace y vea qué clase y qué línea ocurre el problema
  2. Vaya a esa línea y vea qué objetos podrían ser "nulos" en esta ubicación
  3. Descubra por qué el objeto que es nulo no tiene un valor asumido
  4. Si hay más de un objetos que podrían ser nulos, podría System.out.println() ellos, para ver que uno lo es.

Otros consejos

Tu StackTrace te dice esto:

Excepción en el hilo "awt-eventqueue-0" java.lang.nullpointerexception en MinesweeperLogic.ISopen (MinesweeperLogic.Java:117)

Entonces puede ir a la línea 117 y determinar qué referencias podrían ser nulas. (Parece que agregaste una línea en 117 después de que se tomó StackTrace, y luego comentó la nueva línea, así que voy a salir a la extremidad aquí y decir que el StackTrace en realidad se refería a lo que ahora se llama línea 118 : isClicked[x][y] = true;) Lo único que podría ser nulo, en este caso, es isClicked[][].

Cavando un poco más profundo, podemos ver que se inicializa en StartNewGame (), pero obviamente esa instancia se está perdiendo. Esto está sucediendo por dos razones: primero, el LogicClass de su constructor se va fuera de alcance porque no es un miembro de la clase. Segundo (y este fue probablemente un intento fallido de solucionar el primer problema), en mouseClicked, creas un nuevo MinesweeperLogic (junto con un nulo recién creado) en lugar de usar el que creó anteriormente en su MineSweeper() constructor.

Hay varias otras refactorizaciones que debe hacer para limpiar su código, pero hacer de LogicClass un miembro y eliminar la instanciación duplicada debería solucionar el problema inmediato.

Puede ser útil para usted usar el depurador y atravesar el problema usted mismo para comprender exactamente lo que está sucediendo.

Las matrices (Flag, Iszero, ISclicked) no se inicializan y son nulas cuando intentas usarlas. Necesita la clase GUI para contener una instancia de la clase lógica y siempre use esa misma instancia. De lo contrario, ¡cada acción de GUI tendrá lugar en un juego diferente!

Sería útil saber qué línea era el número 117 en la clase lógica. Mi suposición sería mine, mine[x], flagged o flagged[x] es nulo.

Dicho esto, su técnica de "recorrer toda la tabla para ver en qué se hizo clic" no me parece particularmente inspirado.

Editar: en realidad, el problema es que el isOpen La matriz es nula, porque solo has instanciado la clase.

Edit2: Muy bien, entonces es uno de los que enumeré inicialmente. Mi suposición sería todos ellos, porque solo has instanciado la clase, y está usando el constructor predeterminado de no hacer nada.

Usted dice que el error ocurre en el método MouseClicked (), sin embargo, la StackTrace se muestra de manera diferente:

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

Esto dice que el NPE ocurrió en la línea 117 de Mines WeeperLogic. Use su depurador en esa línea o inserte declaraciones de impresión para resolver lo que es nulo, a partir de ahí, puede averiguar por qué.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top