所以,我是一名计算机科学专业的学生,也是一名刚刚掌握Java的程序员。有人让我帮他们完成一项任务,他们必须创建一个非常基本的扫雷程序。该计划根本不使用标记地雷,但除此之外,它在功能上与任何其他扫雷游戏相同。
当我尝试运行程序时,我遇到了NullPointerException。我已经研究了这可能意味着什么,现在知道这应该是NoObjectException或DereferenceException,但我仍然没有更接近解决问题。
调用Tile类的makeField方法时会出现此异常。另外,我真的试图围绕正确的继承,静态与非静态,公共与私有,以及所有这些相互关联,所以如果这是一个完全的noob问题,我很抱歉。 / p>
所以,我有一个主文件,一个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);
}
}
//
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("# ");
}
}
}
}
}
//
public class Flat extends Tile{
public Flat()
{
noOfAdjacentMines = 0;
isBomb = false;
isRevealed = false;
}
}
//
public class Bomb extends Tile{
public Bomb()
{
isBomb = true;
isRevealed = false;
}
}
//
答案 0 :(得分:6)
您的问题出现在我认为的makeField
方法的第二个循环中。
检查if(!Board[i][j].isBomb)
时,由于尚未完全填充数组,因此该特定值将为null。第一个循环放置了几个随机炸弹,但其余值都为空。
我建议你扭转你的循环。首先循环遍历所有内容,然后在不检查任何内容的情况下将整个板放在Flat
之外。
然后在第二个循环中,您只需用Flat
s覆盖一对Bomb
另一个解决方案是进行这个微小的修改并检查null:
if(null == Board[i][j] || !Board[i][j].isBomb)
请注意,如果采用此解决方案,则空检查必须为 FIRST 。这是因为名为short-circuting的东西。
我推荐我的第一个解决方案虽然切换循环是因为它消除了1个额外的比较,而不是大笔交易,但你永远不知道...
答案 1 :(得分:5)
那里有很多问题,但要回答为什么你得到一个空指针的主要问题:
Board[i][randomInRow] = new Bomb();
在上面的代码中,您将在每行的电路板周围随机放置炸弹。请注意,这只会将值设置为方块的子集。
然后你遍历每个方格并执行以下操作:
if(!Board[i][j].isBomb) Board[i][j] = new Flat();
问题是,如果广场没有被分配为炸弹,它没有被分配任何东西,所以它是空的。当你在null的东西上调用isBomb
时,你会得到一个空指针。此测试应该是检查Board[i][j] == null
。
话虽如此,你可能想要从小开始。虽然就游戏而言是相对基础的,但我认为在深入了解之前你需要更多对java的基本理解。
答案 2 :(得分:5)
我想我看到了问题。制作电路板时,您可以将炸弹设置为连续的随机元素。然后你检查所有这些,看看那里是否有炸弹。
if(!Board[i][j].isBomb) // What if board[i][j] is not set? Null Pointer Exception
Board[i][j] = new Flat();
这有用吗?
答案 3 :(得分:0)
问题是您没有填写Bomb
数组。
你需要这样的东西:
for(int i = 0; i < dimensions; i++)
for(int j = 0; j < dimensions; j++){
Board[i][j] = new Tile(); // or something
if(!Board[i][j].isBomb()) // use an accessor
Board[i][j] = new Flat();
}
return Board;
}
答案 4 :(得分:0)
这里的问题是未使用默认磁贴初始化电路板。
你有:
Tile[][] Board = new Tile[dimensions][dimensions];
然后你随机分配炸弹:
Board[i][randomInRow] = new Bomb();
不是炸弹的瓷砖仍然是空的。所以调用它会导致NPE(NullPointerException):
if (!Board[i][j].isBomb)
要解决此更改,请执行以下操作:
if (!Board[i][j] == null)
所以,如果那个当前位置的棋盘是空的,那么肯定它没有被初始化为炸弹 还有其他方法可以转动和扭曲代码来解决这个问题,但这是我想到的最简单的方法。
答案 5 :(得分:-1)
声明多维数组时,不会在数组中创建任何对象。你需要像
这样的东西for(int i = 0; i < dimensions; i++) {
for(int j = 0; j < dimensions; j++) {
Board[i][j] = new Tile();
}
}