JavaFX, как я могу исправить поток ()

Я создаю Сапер после этого видео: https://www.youtube.com/watch?v=JwcyxuKko_M

Но мне нужен шаблон MVC для этого, и я застрял с NullPointer здесь в соответствии с stream в View:

public class View{

Model model;
Field f; //here's where I'm trying to access the List created in Field class
Stage primarystage;
Text number = new Text();

public View(Model model, Stage primaryStage){

    this.model = model;
    this.primarystage = primaryStage;

    Pane root = new Pane();
    root.setPrefSize(model.WIDTH, model.HEIGHT);

    //iterate through rows and columns to fill board with random bombs
    for (int y = 0; y < model.Y_FIELDS; y++) {
        for (int x = 0; x < model.X_FIELDS; x++) {
            Field field = new Field(x, y, Math.random() < 0.2);
            model.array[x][y] = field;
            root.getChildren().add(field);

        }
    }

    for (int y = 0; y < model.Y_FIELDS; y++) {
        for (int x = 0; x < model.X_FIELDS; x++) {
            Field field = model.array[x][y];

    //trying to access the method getSurrounding from class Field with f
            long bombs = f.getSurrounding(field).stream().filter(b -> b.isBomb).count(); //number of bombs

            if (bombs > 0)
                field.bomb.setText(String.valueOf(bombs));
        }
    }
    Scene scene = new Scene(root, model.getWidth(), model.getHeight());
    getStage().setScene(scene);
}

Вот Field учебный класс:

import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;

import java.util.ArrayList;
import java.util.List;

public class Field extends StackPane{

//information for each field: x coordinate, y coordinate, is it a bomb or not
int x;
int y;
boolean isBomb;         //determines whether or not the field is a bomb
int bombsNum = 0;       //counts how many bombs are surrounding the field
Model model;

Rectangle board = new Rectangle(model.FIELD_SIZE - 2, model.FIELD_SIZE - 2);
Text bomb = new Text();

public Field(int x, int y, boolean isBomb){

    this.x = x;
    this.y = y;
    this.isBomb = isBomb;

    board.setFill(Color.LAVENDER);
    board.setStroke(Color.BLACK);
    bomb.setText(isBomb ? "X" : "");

    getChildren().addAll(board,bomb);

    setTranslateX(x * model.FIELD_SIZE);
    setTranslateY(y * model.FIELD_SIZE);
}

public List<Field> getSurrounding(Field field){

    //looks at all the fields surrounding the current field
    List<Field> surrounding = new ArrayList<>();

    int[] coordinates = new int[]{
            -1,-1,  //top left field
            -1, 0,  //left field
            -1, 1,  //bottom left field
             0,-1,  //top middle field
             0, 1,  //bottom middle field
             1,-1,  //top right field
             1, 0,  //right field
             1, 1   //bottom right field
    };

    for (int i = 0; i < coordinates.length; i++) {
        int columnX = coordinates[i];  //considers the x coordinate of a surrounding field
        int rowY = coordinates[++i];   //considers the y coordinate of a surrounding field

        int newX = field.x + columnX;  //sets the x coordinate of a surrounding field
        int newY = field.y + rowY;     //sets the y coordinate of a surrounding field

        if (newX >= 0 && newX < model.X_FIELDS                  //make sure it's not out of bounds
                && newY >= 0 && newY < model.Y_FIELDS) {
            surrounding.add(model.array[newX][newY]);
        }
    }

    return surrounding;
 }
}

И переменные в Model:

public static final int FIELD_SIZE = 40;
public static final int WIDTH = 800;
public static final int HEIGHT = 600;

//sets number of fields in x and y axis
public static final int X_FIELDS = WIDTH / FIELD_SIZE;
public static final int Y_FIELDS = HEIGHT / FIELD_SIZE;

public Field[][] array = new Field[X_FIELDS][Y_FIELDS];

Почему это не работает? Я пытаюсь передать список (содержащий всех соседей поля) в поток и отфильтровать те, которые содержат бомбы, а затем подсчитывает эти бомбы, чтобы я мог отобразить это число на текущем поле, чтобы игрок знал. Почему он не распознает список, который я пропустил? Или это фильтр, который запутался? Спасибо.

Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at View.<init>(View.java:46)
at Main.start(Main.java:10)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)

1 ответ

Решение

Я думаю, что у вас есть проблемы с дизайном в getSurrounding(), На данный момент вам необходимо пройти Field в качестве аргумента, но, насколько я понимаю, этот параметр не имеет смысла. Когда вы хотите захватить окрестности Field вам не нужно предоставлять другой Field! Просто используйте текущий (это)!

public List<Field> getSurrounding() {
    //looks at all the fields surrounding the current field
    List<Field> surrounding = new ArrayList<>();

    int[] coordinates = new int[]{
        -1,-1,  //top left field
        -1, 0,  //left field
        -1, 1,  //bottom left field
         0,-1,  //top middle field
         0, 1,  //bottom middle field
         1,-1,  //top right field
         1, 0,  //right field
         1, 1   //bottom right field
    };

    for (int i = 0; i < coordinates.length; i++) {
        int columnX = coordinates[i];  //considers the x coordinate of a surrounding field
        int rowY = coordinates[++i];   //considers the y coordinate of a surrounding field

        int newX = this.x + columnX;  //sets the x coordinate of a surrounding field
        int newY = this.y + rowY;     //sets the y coordinate of a surrounding field

        if (newX >= 0 && newX < model.X_FIELDS                  
            && newY >= 0 && newY < model.Y_FIELDS) {
            surrounding.add(model.array[newX][newY]);
        }
    }

    return surrounding;
}

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

long bombs = field.getSurrounding().stream().filter(b -> b.isBomb).count();

Это означает, что вы можете избавиться от атрибута вида Field f потому что сейчас не используется. Это было причиной, почему это было null потому что это не имело цели, поэтому никогда не было инициализировано.

Другие вопросы по тегам