修改发送到布尔函数的副本时,原始 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
=]
坏消息。
显然,我需要一些帮助,但我不知道我的代码中发生了什么。看起来很简单,但就是没有意义。
我的理解是 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
=]
坏消息。