NullPointerException в программе мойки - PullRequest
4 голосов
/ 09 февраля 2012

Итак, я студент информатики и начинающий программист на Java. Кто-то попросил меня помочь им с заданием, в котором им нужно было создать довольно простую программу тральщика. Эта программа вообще не использует помечающие мины, но, кроме того, она функционально такая же, как любая другая игра по подметанию мин.

Я запускаю исключение NullPointerException при попытке запустить программу. Я исследовал, что это может означать, и теперь знаю, что это действительно должно быть NoObjectException или DereferenceException, но я все еще не приблизился к решению проблемы.

Это исключение возникает, когда вызывается метод makeField класса Tile. Кроме того, я действительно пытаюсь сосредоточиться на правильном наследовании, статическом и нестатическом, публичном и частном, и как все они взаимосвязаны, поэтому я извиняюсь, если это полный вопрос о нубах. 1005 *

Итак, у меня есть основной файл, суперкласс Tile и два подкласса класса плиток - Bomb и 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;
}

}

//

Ответы [ 6 ]

6 голосов
/ 09 февраля 2012

Ваша проблема во втором цикле метода makeField, я думаю.

Когда вы проверяете if(!Board[i][j].isBomb) Это конкретное значение будет нулевым, потому что вы еще не полностью заполнили свой массив.В первом цикле есть пара случайных бомб, но остальные значения равны нулю.

Я бы порекомендовал обратить ваши петли вспять.Сначала пройдитесь по всему и сделайте всю доску из Flat s, ничего не проверяя.

Затем во втором цикле вы просто перезапишете пару Flat s с помощью Bomb s

Другое решение - просто сделать эту крошечную модификацию и проверить на ноль:

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

Обратите внимание, что если вы принимаете это решение, нулевая проверка должна быть FIRST .Это происходит из-за того, что называется с коротким замыканием .

. Причина, по которой я рекомендую свое первое решение по переключению циклов, состоит в том, что он исключает 1 дополнительное сравнение, а не огромные сделки, но вы никогда не знаете...

5 голосов
/ 09 февраля 2012

Мне кажется, я вижу проблему.Когда вы делаете доску, вы устанавливаете бомбы на случайные элементы подряд.Затем вы проверяете их все, чтобы увидеть, есть ли там бомба.

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

Это полезно?

5 голосов
/ 09 февраля 2012

Там много вопросов, но для ответа на главный вопрос, почему вы получаете нулевой указатель:

Board[i][randomInRow] = new Bomb();

В приведенном выше коде вы размещаете бомбы случайным образом вокруг доски в каждомстрока.Обратите внимание, что это будет только установить значение для подмножества квадратов.

Затем вы перебираете КАЖДЫЙ квадрат и делаете следующее:

if(!Board[i][j].isBomb) Board[i][j] = new Flat();

Проблема в том, что если квадрат былне назначена бомба, ей ничего не назначено, поэтому она является нулевой.Когда вы вызываете isBomb для чего-то, что является нулевым, вы получаете нулевой указатель.Вместо этого этот тест должен проверять, если Board[i][j] == null.

При этом, возможно, вы захотите начать с меньшего, чем это.Будучи относительно базовыми в отношении игр, я думаю, что вам нужно больше базового понимания Java, прежде чем погрузиться в нечто подобное.

0 голосов
/ 09 февраля 2012

Проблема здесь в том, что доска не инициализируется плиткой по умолчанию.

У вас есть:

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

, а затем вы случайным образом назначаете бомбы:

Board[i][randomInRow] = new Bomb();

Плитки, которые не были бомбами, по-прежнему равны нулю.Таким образом, вызов этого приведет к NPE (NullPointerException):

if (!Board[i][j].isBomb)

Чтобы решить это изменение этой строки на:

if (!Board[i][j] == null)

Итак, если доска в этой текущей позиции равна нулю, то этоне был инициализирован как бомба.Есть и другие способы, которыми вы можете повернуть и повернуть код, чтобы решить эту проблему, но это самый простой способ, о котором я подумал.

0 голосов
/ 09 февраля 2012

Проблема в том, что вы не заполняете массив 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;               
}
0 голосов
/ 09 февраля 2012

Когда вы объявляете свой многомерный массив, вы не получаете никаких объектов, созданных в ваших массивах.Вам нужно что-то вроде

for(int i = 0; i < dimensions; i++) {
    for(int j = 0; j < dimensions; j++) {
        Board[i][j] = new Tile();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...