0

I'm working on an assignment where I make a maze from a text file reader. I have made a method which lets me select a text file and convert it to a maze but I'm having trouble extracting the maze from the method. I'm getting a NullPointerException on line 28 which is this: X = Maze[0].length;

I'm stuck on why the method isn't returning my array and also how I can have the method return the StartX and StartY position.

package Innlevering09;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javafx.application.Application;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;

public class MazeGame extends Application {

    MazeRoute[][] Maze;
    int X;
    int Y;
    int StartX;
    int StartY;
    Player Player;

    public void start(Stage primaryStage) {
        try {
            GridPane root = new GridPane();
            Player Player = new Player(StartX, StartY);
            Maze = FileReader();

            X = Maze[0].length;
            Y = Maze.length;

            root.add(Player.getAppearance(), Player.getXpos(), Player.getYpos());

            for(int x = 0; x<X; x++){
                for(int y = 0; y<Y; y++){
                    root.add(Maze[x][y].getAppearance(), x, y);
                }
            }

            Scene scene = new Scene(root, X*10, Y*10);
            //scene.setOnKeyPressed(new FileListener(this));
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }


    public MazeRoute[][] FileReader() {
        String Text = "";
        File File;
        int Row;

        FileChooser FileChooser = new FileChooser();
        FileChooser.setTitle("Open a textfile");
        FileChooser.getExtensionFilters().add(new ExtensionFilter("Text Files", "*.txt"));
        File = FileChooser.showOpenDialog(null);

        try (Scanner FileReader = new Scanner(File)){
            X = FileReader.nextInt();
            Y = FileReader.nextInt();
            Text = FileReader.nextLine();

            MazeRoute[][] Maze = new MazeRoute[X][Y];
            while (FileReader.hasNext()){
                Text = FileReader.nextLine();

                for (int i = 0 ; i < X ; i++){
                    for (Row = 0 ; Row < Y ; Row++) {
                        char Character = Text.charAt(i);
                        switch (Character){
                        case '#':
                            Maze[i][Row] = new Wall(i, Row);
                            break;
                        case ' ':
                            Maze[i][Row] = new NormalTile(i, Row);
                            break;
                        case '-':
                            Maze[i][Row] = new EndTile(i, Row);
                            break;
                        case '*':
                            Maze[i][Row] = new NormalTile(i, Row);
                            StartX = i;
                            StartY = Row;
                            break;
                        }Row++;
                    }
                }
            }
        }catch (FileNotFoundException Error) {
            System.out.println("Cannot open file");
            Error.printStackTrace();
        }
        return Maze;
    }


    public static void main(String[] args) {
        launch(args);
    }
}

edit:

for the people of the future this is the code where I solved the problem:

public class MazeGame extends Application {
    MazeRoute[][] maze;
    int X;
    int Y;
    int startX;
    int startY;
    Player player = new Player();



    public void start(Stage primaryStage){
        try{
            maze = fileReader();

            player.setXpos(startX);
            player.setYpos(startY);

            GridPane root = new GridPane();
            Scene scene = new Scene(root, Color.BLACK);
            Player player = new Player();

            for(int x = 0; x<X; x++){
                for(int y = 0; y<Y; y++){
                    root.add(maze[x][y].getAppearance(), maze[x][y].getTileXpos(), maze[x][y].getTileYpos());
                }
            }

            root.add(player.getAppearance(), player.getXpos(), player.getYpos());

            primaryStage.setTitle("MazeGame");
            primaryStage.setScene(scene);
            primaryStage.show();

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public MazeRoute[][] fileReader() throws FileNotFoundException {
        String text = "";
        File file;
        FileChooser fileChooser = new FileChooser();

        fileChooser.setTitle("Open a text file with a maze");
        fileChooser.getExtensionFilters().add(new ExtensionFilter("Text Files", "*.txt"));
        file = fileChooser.showOpenDialog(null);

        Scanner fileScanner = new Scanner(file);
        X = fileScanner.nextInt();
        Y = fileScanner.nextInt();
        text = fileScanner.nextLine();

        MazeRoute[][] methodMaze = new MazeRoute [X][Y];

        while (fileScanner.hasNext()) {
            for (int row = 0 ; row < Y ; row++){
                text = fileScanner.nextLine();
                for (int i = 0 ; i < X ; i++) {
                    char character = text.charAt(i);
                    switch (character) {
                    case '#':
                        methodMaze[i][row] = new Wall(i, row);
                        break;
                    case ' ':
                        methodMaze[i][row] = new NormalTile(i, row);
                        break;
                    case '-':
                        methodMaze[i][row] = new EndTile(i, row);
                        break;
                    case '*':
                        methodMaze[i][row] = new NormalTile(i, row);
                        startX = i;
                        startY = row;
                        break;
                    }
                }
            }
        }
        return methodMaze;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

the changes I made are the following:

  • I made a new array with the maze blocks inside of the method to avoid the possibility of any scoping issues.
  • I swapped the row and i in the for loop meaning that the loop now goes through a full line before incrementing down to the next one.
  • I moved text = fileScanner.nextLine(); to the inside of the for loop so that it would actually scan the next line.
  • I changed the for loops to start counting from 0 instead of 1 (stupid mistake I know).
  • 2
    Avoid calling your variables with a starting upper-case letter, especially when they would have the same name as existing classes like `FileReader` or `Character` . – Arnaud Apr 05 '18 at 12:57
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – SedJ601 Apr 05 '18 at 13:10
  • Why wouldn't you put the `stacktrace` or at least identify the line that is causing the error? – SedJ601 Apr 05 '18 at 13:12
  • 1
    https://www.geeksforgeeks.org/java-naming-conventions/ – SedJ601 Apr 05 '18 at 13:16
  • @Sedrick The OP did mention the expression causing the NPE. – fabian Apr 05 '18 at 13:18
  • Oh, I somehow missed it. Early morning I guess. – SedJ601 Apr 05 '18 at 13:19
  • Attempting to use a `Method` as if it is a `Class`. `MazeRoute[][] Maze;` You are also doing this inside your `Method`. `MazeRoute[][] Maze = new MazeRoute[X][Y];` – SedJ601 Apr 05 '18 at 13:24
  • 1
    https://www.geeksforgeeks.org/variable-scope-in-java/ – SedJ601 Apr 05 '18 at 13:25

3 Answers3

1

The method FileReader (whose name should start with a lower case letter), returns Maze.
However, this is the property on class level since the local variable with the same name, declared within the try-catch, is out of scope.
This class-level property has not been assigned yet and is therefore equal to null.

Robert Kock
  • 5,795
  • 1
  • 12
  • 20
0

It's a scope problem. You are not returning the variable declared in the function "FileReader" because it's declared only in the scope of the while loop. The only variable available for the return is the one declared in the scope of the class.

jpmottin
  • 2,717
  • 28
  • 25
0

First, as others have pointed out, Java naming conventions are that all variables, methods, and non-static fields must start with a lower case letter. This is especially important when your variables have the same names as existing Java SE classes. Your code will be much easier to read, and you will not only help yourself, you will get help from people on Stack Overflow more quickly.

In your FileReader method, you have this line:

MazeRoute[][] Maze = new MazeRoute[X][Y];

That line declares a new variable named Maze, which has no relationship to the Maze field of your MazeGame class. All subsequent lines of code are populating that new variable, not the Maze field declared in the MazeGame class.

A variable only exists within the brace-enclosed block where it is declared. In this case, that block is your try block, since new Maze variable is declared inside that try block. Once the the end of that try block is reached, the Maze variable does not exist and its value is eligible for garbage collection.

When your FileReader method reaches its return statement, that Maze variable doesn’t exist, so return Maze; actually refers to the Maze field of the MazeGame class. But that field was never set by your method, since your code was setting a locally defined variable which happened to have the same name. In Java, all object fields are null until set otherwise. So the method returns null.

The easiest way to fix your problem is to avoid defining a new Maze variable. Change this:

MazeRoute[][] Maze = new MazeRoute[X][Y];

to this:

Maze = new MazeRoute[X][Y];
VGR
  • 40,506
  • 4
  • 48
  • 63