Search code examples
javaoptimizationclosuresclone

Java maze breaking closure


I have next maze class. There is only one optimisation that I need to add. If there is no maze = readFromFile(); in for loop, method check runs only once, because maze array is modified in check method. I want to avoid reading from file for each iteration. I am trying to do copy of my maze array in order to avoid mutating of it, but with no success.

public class Maze {
    private static char[][] maze;
    private static int size;
    private static Cell startCell = null;
    private static ArrayList<String> resultPaths = new ArrayList<>();
    private static final String INPUT_FILE_NAME = "Problem.in";
    private static final String OUTPUT_FILE_NAME = "Problem.out";
    private static char[][] readFromFile() throws FileNotFoundException {
        Scanner scanner = new Scanner(new File(Maze.INPUT_FILE_NAME));
        try {
            // Read maze size
            size = scanner.nextInt();
            scanner.nextLine();
            // Create the maze
            maze = new char[size][size];
            // Read the maze cells from the file
            for (int row = 0; row < size; row++) {
                String line = scanner.nextLine();
                for (int col = 0; col < line.length(); col++) {
                    char ch = line.charAt(col);
                    maze[row][col] = ch;
                    if (ch == '*') {
                        startCell = new Cell(row, col);
                    }
                }
            }
            return maze;
        } finally {
            scanner.close();
        }
    }

    public static void saveResult(String fileName, ArrayList<String> resultPaths) throws IOException {
        FileWriter writer = new FileWriter(fileName);
        try {
            for (String resultPath : resultPaths) {
                writer.write("" + resultPath + "\n");
            }
        } finally {
            writer.close();
        }
    }

    private static void check(int x, int y, int dest_x, int dest_y, char[][] maze, String path) {
        if (x < 0 || y < 0 || x >= size || y >= size || maze[y][x] == '#') {
            return;
        }
        if (maze[y][x] != '*') {
            path += String.valueOf(maze[y][x]);
        }

        if (x == dest_x && y == dest_y) {
            System.out.println(path);
            resultPaths.add(path);
            return;
        } else {
            maze[y][x] = '#';
            check (x + 0, y - 1, dest_x, dest_y, maze, path);
            check (x + 0, y + 1, dest_x, dest_y, maze, path);
            check (x - 1, y + 0, dest_x, dest_y, maze, path);
            check (x + 1, y + 0, dest_x, dest_y, maze, path);
            maze[y][x] = '#';
        }
    }

    public static ArrayList<Cell> getExits(char[][] maze) {
        ArrayList<Cell> result = new ArrayList<>();
        for (int row = 0; row < size; row++) {
            for (int col = 0; col < size; col++) {
                char ch = maze[row][col];
                maze[row][col] = ch;
                if (ch == '*') {
                    startCell = new Cell(row, col);
                }
                if ((ch != '#') && (row == 0 || col == 0 || row == (size - 1) || col == (size - 1))) {
                    result.add(new Cell(row, col));
                }
            }
        }
        return result;
    }

    public static void main(String[] args) throws IOException {
        maze = readFromFile();
        ArrayList<Cell> possibleExits = getExits(maze);
        String path = "";
        for (Cell currentCell : possibleExits) {
            maze = readFromFile(); // HERE I NEED TO REPLACE THIS WITH COPY OF CURRENT MAZE CHAR ARRAY
            check(startCell.getCol(), startCell.getRow(), currentCell.getCol(), currentCell.getRow(), maze, path);
        }
        saveResult(OUTPUT_FILE_NAME, resultPaths);
    }
}

Input file:

6
a##km#
z#ada#
a*m###
#d####
rifid#
#d#d#t

Output:

aza
madk
madamk
madkm
madam
az
a
dir
did
difid

Solution

  • You can operate on copyMaze and cleanMaze is not gonna change, you can do that copy every time you need a new maze. Just never modify cleanMaze after reading it from file.

    final char[][] cleanMaze = readFromFile(); // never modify this again
    
    char[][] copyMaze = new char[size][size];
    for (int i = 0; i < size; i++) {
      System.arraycopy(cleanMaze[i], 0, copyMaze[i], 0, size);
    }
    

    System.arracopy javadoc

    Don't be tempted to take copy out of the loop, it's not gonna work. It would only copy the first dimension, the modification of second dimension would modify it in both arrays, that's why we need to copy everything.