2

I need some help, obviously, but I have no idea what is going in my code. Seems pretty straightforward, but just doesn't make sense.

My understanding is that java doesn't have pointers that work the way C++ does so that's where my problem starts.

I have a private static char[][], which is a class variable, called "maze". Simple. No where does it get modified except when giving it it's fill of data.

After that it gets sent into a recursive algorithm that solves the maze as "mz" while keeping "maze" as a reference/map, and the one that is sent in "mz" is used as a step map, modified with a marker every time you take a step on a certain tile/cell.

The problem now is that when i try to draw the maze out again, it's showing the step map "mz" which has modified values, and not "maze" which hasn't been touch since the recursion started.

Thanks in advance.

Here's the code:

import java.io.*;
import java.util.*;

public class Maze {

    public static int   sizeX = 10, // Width of the maze
                        sizeY = 10, // Height of the maze
                        startX = 5, // Starting point on the X-axis of the maze
                        startY = 5, // Starting point on the Y-axis of the maze
                        winStep = 98; // Number of steps needed for a feasible maze and must be even or the path will be open at the end 
    private static int[][] path = new int[winStep][2]; // Placeholder for list of co-ordinates on the path
        // Path[  N  ][  0  ] = X
        // Path[  N  ][  1  ] = Y
    private static char[][] maze; // Placeholder for the maze map, and the step map
        // Maze[ Row ][ Col ]
        // Maze[  Y  ][  X  ] , necessary to know for traversing the maze

    public static int totalSteps = 0; // Troubleshoot code, used to see how far algorithm goes in the maze in case it fails


    public static void drawMaze() {

        System.out.printf("  "); // Spacing before drawing X-axis
        for( int i = 0 ; i < sizeX ; i++)
            System.out.printf(i + "  "); // Draw X-axis
        System.out.println();

    // Draws the maze from left to right (i = 0 to sizeX-1), top to bottom (j = 0 to sizeY-1)
        for( int i = 0 ; i < sizeX ; i++ ) {
            System.out.printf(i + " "); // Draw Y-axis
            for( int j = 0 ; j < sizeY ; j++ ) {
                System.out.print(maze[i][j] + "  ");                
            }
            System.out.println(); // Output formatting
        }
        System.out.println(); // Output formatting

        return;
        // End of drawMaze()
    }

    public static boolean pathfinder2(char[][] mz, int x, int y, int step, char oDir, char nDir) { 

    // Check if you've completed the maze yet
        if ( step == winStep - 15 ) { // Troubleshoot code
//      if ( x == startX && y == startY && step == winStep ) {
            path[step-1][0] = x;
            path[step-1][1] = y;
            return true;
        }

    // Preliminary check to make the path is still in the maze  
        if( x < 0 || x >= sizeX || y < 0 || y >= sizeY ) {
            return false;
        }

    // Check where you've ended up
        if( step > 0 ) { // Check these scenarios after the first step

        // Checking previous steps
            if(     ( nDir == 'u' && ( (oDir == 'u' && maze[y+1][x] == '/') || (oDir == 'u' && maze[y+1][x] == '\\') ) )    // If you just moved UP, but you're last step was also UP and the last tile was a '/' or '\'
                ||  ( nDir == 'r' && ( (oDir == 'r' && maze[y][x-1] == '/') || (oDir == 'r' && maze[y][x-1] == '\\') ) )    // If you just moved RIGHT, but you're last step was also RIGHT and the last tile was a '/' or '\'
                ||  ( nDir == 'd' && ( (oDir == 'd' && maze[y-1][x] == '/') || (oDir == 'd' && maze[y-1][x] == '\\') ) )    // If you just moved DOWN, but you're last step was also DOWN and the last tile was a '/' or '\'
                ||  ( nDir == 'l' && ( (oDir == 'l' && maze[y][x+1] == '/') || (oDir == 'l' && maze[y][x+1] == '\\') ) ) )  // If you just moved LEFT, but you're last step was also LEFT and the last tile was a '/' or '\'
                        { return false; }
        // Checking current steps
            else
                if( maze[y][x] == 'X' ) { // If you've walked into a Block-Tile 
                    return false;
                }else
                    if( x == startX && y == startY && step != winStep ) { // If you've ended up at the starting position but have not taken enough steps
                        return false;
                    }else
                        if( nDir == 'u' // If you've just moved UP from a lower tile
                        && ( maze[y][x] == 'U' || maze[y][x] == 'R' || maze[y+1][x] == 'D' || maze[y+1][x] == 'L' || mz[y][x] == 'S' ) ) { // If you've just walked through a ramp wall or a previously stepped on tile 
                                return false;
                        }else
                            if( nDir == 'r' // If you've just moved RIGHT from a lower to the left
                            && ( maze[y][x-1] == 'U' || maze[y][x] == 'R' || maze[y][x] == 'D' || maze[y][x-1] == 'L' || mz[y][x] == 'S' ) ) { // If you've just walked through a ramp wall or a previously stepped on tile 
                                    return false;
                            }else
                                if( nDir == 'd' // If you've just moved DOWN from an upper tile
                                && ( maze[y-1][x] == 'U' || maze[y-1][x] == 'R' || maze[y][x] == 'D' || maze[y][x] == 'L' || mz[y][x] == 'S' ) ) { // If you've just walked through a ramp wall or a previously stepped on tile 
                                        return false;
                                }else
                                    if( nDir == 'l' // If you've just moved LEFT from a tile to the right
                                    && ( maze[y][x] == 'U' || maze[y][x+1] == 'R' || maze[y][x+1] == 'D' || maze[y][x] == 'L' || mz[y][x] == 'S' ) ) { // If you've just walked through a ramp wall or a previously stepped on tile 
                                            return false;
                                    }else { // No obstacles were in the way. It is okay to continue

                                        if( step > totalSteps ) {
                                            totalSteps = step; } // Troubleshoot code
                                        System.out.println( "Step " + step + ": " + nDir + " " + x + " , " + y + " [" + maze[y][x] + "] x"); // Troubleshoot code

                                        if( mz[y][x] != 's' && ( maze[y][x] == '/' || maze[y][x] == '\\' ) ) { // If the '/' or '\' tile is not stepped on yet
                                            mz[y][x] = 's'; // Mark the tile as half stepped on and continue
                                        }else {
                                            mz[y][x] = 'S'; // Mark the tile as fully stepped on and continue
                                        }
                                    }
        }

    // MOVE
        if( pathfinder2( mz , x , y-1 , step+1 , nDir, 'u' ) ) { // Go North / Up
            path[step] = new int[] { x , y };
            return true;
        }else
            if( pathfinder2( mz , x+1 , y , step+1 , nDir, 'r' ) ) { // Go East / Right
                path[step] = new int[] { x , y };
                return true;
            }else
                if( pathfinder2( mz , x , y+1 , step+1 , nDir, 'd' ) ) { // Go South / Down
                    path[step] = new int[] { x , y };
                    return true;
                }else
                    if( pathfinder2( mz , x-1 , y , step+1 , nDir, 'l' ) ) { // Go West / Left
                        path[step] = new int[] { x , y };
                        return true;
                    }else { // Reaching this point means you've reached a dead-end

                        if( mz[y][x] == 'S' && ( maze[y][x] == '/' || maze[y][x] == '\\' ) ) { // If the '/' or '\' was fully stepped on previously
                            mz[y][x] = 's'; // Unmark the full stepped, and mark it as half stepped on
                        }else {
                            mz[y][x] = '-'; // Unmark the tile as stepped on and continue
                        }
                        return false;
                    }

        // End of pathfinder2()
    }

    public static void main(String args[]) throws IOException {

        maze = new char[][] { 
                // 0    1    2     3     4     5     6     7     8     9
                { '-', '-', 'X' , '-' , '-' , '-' , '-' , '-' , '-' , '-' },    // 0
                { '-', '-', '-' , '-' , '-' , '-' , '-' , '-' , 'U' , '-' },    // 1
                { '-', '-', '-' , '-' , '-' , 'X' , '-' , '-' , '-' , '-' },    // 2
                { 'X', '-', '-' , 'R' , '-' , '-' , '-' , '-' , '-' , 'X' },    // 3
                { '-', '-', '-' , '-' , '-' , '\\' , '-' , '-' , '-' , '-' },   // 4
                { '-', '-', '-' , '-' , '-' , '-' , '-' , '-' , '/' , '-' },    // 5
                { '-', '-', '-' , '-' , '-' , '-' , '-' , '-' , '-' , '-' },    // 6
                { 'D', '-', 'R' , '-' , '-' , '-' , '-' , '-' , '-' , '-' },    // 7
                { '-', '-', '-' , '-' , '-' , '-' , '-' , '-' , '\\' , '-' },   // 8
                { '-', '-', '-' , '-' , 'X' , '-' , '-' , '-' , '-' , '-' }     // 9
            };
        drawMaze();

        if ( winStep % 2 == 0 ) { // The maze will end with dead-ends if the total possible steps are odd numbered.

            if( pathfinder2 ( maze , startX , startY , 0 , 'x', 'x' ) ) {

                System.out.printf("\n\nThe complete route started on x=" + startX + ", y=" + startY + ".\n");
                System.out.printf("The following steps make up the path: \n");

                for( int i = 0 ; i < winStep ; i++ ) {

                    System.out.println("Step " + (i+1) + ": " + path[i][0] + " , " + path[i][1] + " [" + maze[path[i][1]][path[i][0]] + "]" );
                }
                System.out.println();
                drawMaze();

            }else {

                System.out.println("This program is silly. Total steps taken this time: " + totalSteps);
            }
        }else {
            System.out.printf("\n\nIt is not possible to complete this maze.");
        }

        return;
        // End of main()
    }
}
Gam Boyo
  • 23
  • 3
  • 4
    Java doesn't have pointers/pointer arithmetic, but references still act a lot like pointers. Your `maze` and `mz` are referring to the same array. Just because you're using a different parameter name doesn't mean the array is copied. You'll have to make a copy of the array before you pass it in. – Kayaman Apr 04 '18 at 08:56
  • See also: https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value – lexicore Apr 04 '18 at 09:09
  • @Kayaman Hoooooooolyyyyyy f************k, I've been wracking my brain for the longest time on this. I've just tried it and you're right. Thanks! – Gam Boyo Apr 04 '18 at 09:13
  • @lexicore Hi! I've never touched java to this extent, and I'm just helping a friend out so this is all truly helpful information. Thanks so much! – Gam Boyo Apr 04 '18 at 09:17

2 Answers2

0

As mentioned in the comments, Java doesn't have pointers but references which is what you pass if you pass an object to a method. The reference itself is copied, i.e. if you have a method

void somemethod(char[][] array) {
    array = new char[][] {
        {'a', 'b', 'c'},
        {'d', 'e', 'f'},
    };
}

the reference (and therefor the array it references to) of the calling method will stay the same which is a difference to call-by-reference in C (I learned the name call-by-reference-value 20 years ago but you don't see that often now).

Your problem is that you pass the reference to the initial char-array to the method, so every modification to that array takes place in the initial one. If you want to keep the original array as it is, you need to create a copy of it and pass that to the method, e.g. by using clone.

Lothar
  • 5,323
  • 1
  • 11
  • 27
0

The following passes the 2D array object in maze to the parameter mz.

You need a second object to modify:

       if (pathfinder2(maze , startX , startY , 0 , 'x', 'x')) {

should become something like:

       char[][] mazevar = new char[10][];
       for (int i = 0; i < 10; ++i) {
           mazevar[i] = Arrays.copyOf(maze[i], 10);
       }
       if (pathfinder2(maze , startX , startY , 0 , 'x', 'x')) {

However the same holds for all recursive calls.

Best would be that you could reuse mz by restoring the old state of mz after each call / do not alter mz on return.

Bad news.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138