This site requires JavaScript, please enable it in your browser!
Greenfoot back
TheGoldenProof
TheGoldenProof wrote ...

2018/4/19

nullPointerException when calling function that returns void

TheGoldenProof TheGoldenProof

2018/4/19

#
Once again, for the crude minesweeper game I'm making, I'm trying to make the thing that removes adjacent tiles of the same bomb value. I have a function that checks all adjacent tiles for their value, runs this function in that tile, then deletes itself. It compiles, but when I click on a tile, I get this error: java.lang.NullPointerException at Square.revealTiles(Square.java:33) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) at Square.revealTiles(Square.java:34) The code for the function is as follows:
public void revealTiles() {
        for (int xO = 0; xO <= 2; xO++) {
            for (int yO = 0; yO <=2; yO++) {
                Numbers nNumber = (Numbers)getOneObjectAtOffset(xO - 1, yO - 1, Numbers.class);
                Square nSquare = (Square)getOneObjectAtOffset(xO - 1, yO - 1, Square.class);
                Numbers tNumber = (Numbers)getOneIntersectingObject(Numbers.class);
                if (nNumber.numberOfBombs() == tNumber.numberOfBombs()) {
                    nSquare.revealTiles();
                }
            }
        }
        getWorld().removeObject(this);
    }
Normally, when you run function on another object and you do the object. all of the completions inherited from actor class are there but they arent just the ones Ive made.
danpost danpost

2018/4/19

#
Just to clarify, Minesweeper does not do what you are trying to do here -- that is, it does not expose all equal valued numbers chained with the one chosen. Normally, the only time multiple squares are exposed is when the number is exactly zero; and then, all chained number squares are exposed -- but so be it. The problem with your code above is that "this" tile will not be removed until all its neighbors have done their thing. This means that "this" will be one of its neighbors, and it will be again one of "this", ad infinitum. First, get a list of the neighbors and see which ones need to be exposed; next delete "this"; then run method on valid neighbors:
int num = ((Numbers)getOneObjectAtOffset(0, 0, Numbers.class)).numberOfBombs();
java.util.List<Square> nearOnes = (java.util.List<Square>)getNeighbours(1, true, Square.class); // lists neighboring squares
java.util.List<Square> validOnes = new java.util.ArrayList<Square>(); // to list exposeable squares
for (Square square : nearOnes) // for each neighbor in list
{ // if numbers match, add square to list of valid squares to expose
    if (num == ((Numbers)getWorld().getObjectsAt(square.getX(), square.getY(), Numbers.class).get(0)).numberOfBombs())
    {
        validOnes.add(square);
    }
}
getWorld().removeObject(this);
for (Square square : validOnes) square.revealTiles();
I think that is right.
TheGoldenProof TheGoldenProof

2018/4/19

#
unfortunately it does not. I have been trying other similar methods too such as this:
public void revealTiles() {
        int number = ((Numbers)getOneIntersectingObject(Numbers.class)).numberOfBombs();
        if (number == 0) {
            List<Square> nearbySquares = new ArrayList<>();
            if (getOneObjectAtOffset(1,0,Square.class) != null) {
                nearbySquares.add((Square)getOneObjectAtOffset(1,0,Square.class));
            }
            if (getOneObjectAtOffset(-1,0,Square.class) != null) {
                nearbySquares.add((Square)getOneObjectAtOffset(-1,0,Square.class));
            }
            if (getOneObjectAtOffset(0,1,Square.class) != null) {
                nearbySquares.add((Square)getOneObjectAtOffset(0,1,Square.class));
            }
            if (getOneObjectAtOffset(0,-1,Square.class) != null) {
                nearbySquares.add((Square)getOneObjectAtOffset(0,-1,Square.class));
            }
            getWorld().removeObject(this);
            for (Square nearbySquare : nearbySquares) {
                nearbySquare.revealTiles();
            }
            nearbySquares.clear();
        } else if (number > 0) {
            getWorld().removeObject(this);
        }
    }
And now its giving me errors saying the actor isn't in the world on the nearbySquare.revealTile(). Also after playing around with things, I've noticed that it never reveals the tiles above it and doesn't reveal all of them to the left side. It also doesn't reveal them to the left or right (depending on what side their on relative to the initial clicked square) of a actual number. Currently I have it set to only make 1 bomb. It seems like Greenfoot doesn't delete objects until all of the other code has finished running, making it add all of those squares to all of the list and then deleting them, causing to to try to delete things that have already been deleted.
danpost danpost

2018/4/19

#
Try changing line 19 to this:
if (nearbySquare.getWorld() != null)  nearbySquare.removeTiles();
TheGoldenProof TheGoldenProof

2018/4/20

#
It worked! Its funny how it really does just take a fresh pair of eyes sometimes. It's not like its a complicated solution, its just another simple way to attempt the same thing.
You need to login to post a reply.