views:

220

answers:

5

JAVA- Hi, I am writing a minesweeper program (first biggie) and am really stuck. The program itself is comprised of 2 classes (one for the logic, one for the GUI) as per the specifications that I am to follow. I have done a fair bit in both classes but am not finished either. However, I am attempting to test implementing call methods from one class to the other and that is where I get stuck. From the GUI class, I am attempting to call the method openCell(int x, int y) in the Logic Class every time the user clicks on a box. That Logic Class method will in turn check to see whether there is a mine, a 0 or a number on the square and call the appropriate method from the GUI class. The two methods involved in the error are as follows:

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

Following is the error report I recieve once the user clicks on a box in the game (it does to catch it when compiling the 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)

Finally, the entire (tho incomplete at this point) code for two classes so far if needed. (The methods in the logic class are required to perform specific actions as per the instructions of the project and must have no user interaction in the logic class). I cannot figure out what exactly is causing the error. Any guidance would be greatly appreciated. (hopefully it's not something really obvious cuz I have spent the last couple of hours trying to figure this out even though ive got the flu! 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;
        }
    }
A: 

It would be helpful to know what line number 117 in the logic class was. My guess would be either mine, mine[x], flagged or flagged[x] is null.

That said, your technique of "loop through the entire table to see which one was clicked" doesn't strike me as particularly inspired.

EDIT: Actually, the problem is that the isOpen array is null, because you've only just instantiated the class.

EDIT2: Alright, so it's one of the ones I listed initially. My guess would be all of them, because you've only just instantiated the class, and it's using the default do-nothing constructor.

Anon.
There's a colorful arrow pointing at what is probably line 117 in the first chunk of code.
Carl Smotricz
Except that it's NOT pointing at that line.
Michael Borgwardt
It's so completely not pointing at that line, it's in fact pointing at a line in *a completely different class*.
Anon.
No, that's line 126 in the GUI class..
tster
+6  A: 

How about that:

  1. look at the first line of your exception stacktrace, and see which class and which line the problem occurs
  2. go to that line, and see which objects could possibly be "null" at this location
  3. find out why the object that is null doesn't have a value assgined
  4. if there are more than one objects that could be null, you could System.out.println() them, to see whchi one is.
Bozho
While this will help fix the NullPointerException, the code in question is so wrong that it won't get him any closer to actually having a working minesweeper game.
tster
step by step :)
Bozho
Learning to use the debugger would be preferable to System.out.println
rob
for such simple things the debugger adds overhead
Bozho
If you're using Eclipse, you double-click on the line to create a breakpoint, then click a different button to run your program, instead of typing additional code (which you'll have to delete later). Unless you're scared of the debugger for some reason, debugging the code actually seems simpler to me. ;)
rob
Debugging the code helps you understand how the code *actually* works, not how you *think* it works. (This applies even if you wrote the code!)
Alan Krueger
+2  A: 

The arrays (flag, isZero, isClicked) are not initialized and are null when you try and use them. You need the GUI class to contain an instance of the logic class and always use that same instance. Otherwise, each GUI action will take place on a different game!

tster
I Agree. You are creating a new instance of MinesweeperLogic every time you click the mouse. You need to hold onto the instance that you create in the MineSweeper() method.
goatlinks
+4  A: 

Your stacktrace tells you this:

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

So you can go to line 117 and determine which references could possibly be null. (It seems like you added a line at 117 after the stacktrace was taken, and then commented out the new line, so I'm going to go out on a limb here and say the stacktrace was actually referring to what is now called line 118: isClicked[x][y] = true;) The only thing that could be null, in this case, is isClicked[][].

Digging a little deeper, we can see that you do initialize isClicked in startNewGame(), but obviously that instance is getting lost. This is happening for two reasons: first, the logicClass from your constructor is going out-of-scope because it's not a member of the class. Second (and this was probably a failed attempt to fix the first problem), in mouseClicked, you create a new MinesweeperLogic (along with a newly-created null isClicked) instead of using the one you previously created in your MineSweeper() constructor.

There are several other refactorings you should make to clean up your code, but making logicClass a member and removing the duplicate instantiation should fix the immediate problem.

It might be helpful for you to use the debugger, and step through the problem yourself to understand exactly what is happening.

rob
A: 

You say that the error occurs in the mouseClicked() method, however the stacktrace shows differently:

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

This is saying that the NPE occured on line 117 of MineSweeperLogic. Use either your debugger on that line, or insert print statements to work out what is null, from there, you can work out why.

Paul Wagland