扫雷程序中的NullPointerException

Gth*_*ma2 4 java inheritance class nullpointerexception

所以我是一名计算机科学专业的学生,​​也是一名刚刚掌握Java的程序员.有人让我帮他们完成一项任务,他们必须创建一个非常基本的扫雷程序.该程序根本不使用标记地雷,但除此之外,它在功能上与任何其他扫雷游戏相同.

当我尝试运行程序时,我遇到了NullPointerException.我已经研究了这可能意味着什么,现在知道这应该是NoObjectException或DereferenceException,但我仍然没有更接近解决问题.

调用Tile类的makeField方法时会出现此异常.此外,我真的试图围绕正确的继承,静态与非静态,公共与私人,以及所有这些相互关联的方式,所以如果这是一个完全的noob问题,我很抱歉.

所以,我有一个主文件,一个Tile超类,以及tile类的两个子类--Bomb和Flat.炸弹是一个带有炸弹的瓷砖,而Flat是任何不是炸弹的瓷砖.

public class MineSweeperMain{
public static void main(String[] args)
{
    Scanner kybd = new Scanner(System.in);
    int dimension;
    Tile[][] gameBoard;

    System.out.print("Enter the dimension of the board you would like to play on:\t");
    dimension = kybd.nextInt();

    gameBoard = Tile.makeField(dimension);
    Tile.printField(gameBoard, dimension);
}

}
Run Code Online (Sandbox Code Playgroud)

//

public class Tile {

static Random rand = new Random();

boolean isBomb;
boolean isRevealed;
int posX, posY;
int noOfAdjacentMines;

public Tile()
{
    isRevealed = false;
}

public static int detectMines(Tile[][] board, int dimensions)
{
    int detectedMines = 0;
    for(int i = 0; i < dimensions; i++)
    {
        for(int j = 0; j < dimensions; j++)
        {
            if(board[i][j].isBomb)
                detectedMines++;
        }
    }
    return detectedMines;
}

public static Tile[][] makeField(int dimensions)
{   
    int rowOfMines = dimensions / 3;
    int randomInRow;

    Tile[][] Board = new Tile[dimensions][dimensions];

    for(int i = 0; i < dimensions; i++)
        for(int j = 0; j <= rowOfMines; j++)
        {
        randomInRow = rand.nextInt(dimensions);
        Board[i][randomInRow] = new Bomb();
        }

    for(int i = 0; i < dimensions; i++)
        for(int j = 0; j < dimensions; j++)
        {
            if(!Board[i][j].isBomb)
                Board[i][j] = new Flat();
        }
    return Board;               
}

public static void printField(Tile[][] board, int dimensions)
{
    for(int i = 0; i <= dimensions; i++)
    {
        for (int j = 0; j <= dimensions; j++)
        {
            if(i ==0)
                System.out.print(i + " ");
            else if(j == 0)
                System.out.print(j + " ");
            else
            {
                if(board[i-1][j-1].isRevealed && !board[i-1][j-1].isBomb)
                    System.out.print(board[i-1][j-1].noOfAdjacentMines + " ");  
                else
                    System.out.print("# ");
            }
        }
    }
}

}
Run Code Online (Sandbox Code Playgroud)

//

public class Flat extends Tile{

public Flat()
{
    noOfAdjacentMines = 0;
    isBomb = false;
    isRevealed = false;
}
}
Run Code Online (Sandbox Code Playgroud)

//

public class Bomb extends Tile{
public Bomb()
{
    isBomb = true;
    isRevealed = false;
}

}
Run Code Online (Sandbox Code Playgroud)

//

gno*_*med 6

您的问题出在makeField我认为的方法的第二个循环中.

检查时,if(!Board[i][j].isBomb)由于尚未完全填充数组,因此特定值将为null.第一个循环放置了几个随机炸弹,但其余值都为空.

我建议你扭转你的循环.首先循环遍历所有内容,然后在Flat不检查任何内容的情况下将整个板放出.

然后在你的第二个循环中,你将FlatBombs 覆盖一对s

另一个解决方案是进行这个微小的修改并检查null:

if(null == Board[i][j] || !Board[i][j].isBomb)

请注意,如果你把这个解决方案,空校验必须是第一.这是因为称为短路的东西.

我推荐我的第一个解决方案虽然切换循环的原因是因为它消除了1个额外的比较,而不是大笔交易,但你永远不知道......


Jam*_*gne 5

那里有很多问题,但要回答为什么你得到一个空指针的主要问题:

Board[i][randomInRow] = new Bomb();
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,您将在每行的电路板周围随机放置炸弹.请注意,这只会将值设置为方块的子集.

然后你遍历每个方块并执行以下操作:

if(!Board[i][j].isBomb) Board[i][j] = new Flat();
Run Code Online (Sandbox Code Playgroud)

问题是,如果广场没有被分配为炸弹,它没有被分配任何东西,所以它是空的.当你调用isBombnull的东西时,你会得到一个空指针.这个测试应该是检查是否Board[i][j] == null.

话虽这么说,你可能想要从小开始.虽然就游戏而言是相对基础的,但我认为在深入了解之前你需要更多对java的基本理解.


Rus*_*ssS 5

我想我看到了问题.制作电路板时,您可以将炸弹设置为连续的随机元素.然后你检查所有这些,看看那里是否有炸弹.

if(!Board[i][j].isBomb) // What if board[i][j] is not set? Null Pointer Exception
                Board[i][j] = new Flat();
Run Code Online (Sandbox Code Playgroud)

这有用吗?