修改发送到布尔函数的副本时,原始 char[][] 中的数据被覆盖

Data in my original char[][] is being overwritten when modifying a copy of it that is sent into a boolean function

显然,我需要一些帮助,但我不知道我的代码中发生了什么。看起来很简单,但就是没有意义。

我的理解是 java 没有像 C++ 那样工作的指针,所以这就是我的问题开始的地方。

我有一个 private static char[][],它是一个 class 变量,名为 "maze"。简单的。除了给它填充数据时,它没有在任何地方被修改。

之后,它被发送到一个递归算法中,该算法以 "mz" 的形式解决迷宫,同时将 "maze" 保持为 reference/map,并在 "mz" 中发送]作为步进图,每走一步就用marker修改tile/cell.

现在的问题是,当我尝试再次绘制迷宫时,它显示的是步进图 "mz",它已经修改了值,而不是 "maze",它自从递归开始。

提前致谢。

代码如下:

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()
    }
}

如评论中所述,Java 没有指针,只有引用,如果将对象传递给方法,则传递的是引用。引用本身被复制,即如果你有一个方法

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

调用方法的引用(以及它引用的数组)将保持不变,这与 C 中的 call-by-reference 不同(我学会了名称 call-by-reference-value 20 years以前但你现在不经常看到了)。

您的问题是您将对初始 char-array 的引用传递给方法,因此对该数组的每次修改都发生在初始数组中。如果要保持原始数组不变,则需要创建它的副本并将其传递给方法,例如通过使用 clone.

下面将maze中的二维数组对象传给参数mz.

您需要修改第二个对象:

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

应该变成这样:

       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')) {

然而,这同样适用于所有递归调用。

最好是您可以通过在每次调用后恢复 mz 的旧状态来重用 mz / 不要在 return.[=17 上更改 mz =]

坏消息。