Java 使用array.clone()并更改值也会影响原始数组

Java 使用array.clone()并更改值也会影响原始数组,java,arrays,Java,Arrays,我已经为一个练习编写了一个程序,该程序生成带有0(用随机数填充其余单元格)的numofalidboardstocreate数独棋盘,然后求解它们。如果生成的电路板无效或不可解,它会尝试创建另一个电路板,直到获得它为止。现在让我们假设,为了简单起见,我们只需要一块带有75个空单元的电路板及其解决方案 solve()方法检查电路板是否可解,如果可解,则进行求解并返回true。现在,因为当我使用isSolvableBoard()检查for循环的if语句中每个电路板的有效性时,它反过来调用solve()

我已经为一个练习编写了一个程序,该程序生成带有0(用随机数填充其余单元格)的
numofalidboardstocreate
数独棋盘,然后求解它们。如果生成的电路板无效或不可解,它会尝试创建另一个电路板,直到获得它为止。现在让我们假设,为了简单起见,我们只需要一块带有75个空单元的电路板及其解决方案

solve()
方法检查电路板是否可解,如果可解,则进行求解并返回true。现在,因为当我使用
isSolvableBoard()
检查for循环的if语句中每个电路板的有效性时,它反过来调用
solve()
,我不想求解原始电路板,因为我需要显示原始的未解决电路板,然后显示解决方案。因此,我决定使用
sudokuBoard.clone()
复制原始版本,并将其用于检查,而忽略它,因为它将在评估条件后得到解决。我希望if()语句中的原始
sudokuBoard
在我第一次打印时不会被解析,但输出是已解析的版本。我错过了什么

public static void main(String[] args) {
        BacktrackingAlgorithm solver = new BacktrackingAlgorithm();

        // Get the required input from the user
        Scanner scanner = new Scanner(System.in);
        System.out.println("Enter the number of empty cells that the board should have:");
        int emptyCellsPerBoard = scanner.nextInt();
        System.out.println("Enter how many boards the app should create and solve:");
        int numOfValidBoardsToCreate = scanner.nextInt();

        // extra data to keep track of for printing purposes
        int numOfInvalidBoards = 0;
        int numOfUnsolvableBoards = 0;

        // finding the time before the operation is executed
        long start = System.currentTimeMillis();

        int[][] sudokuBoard;
        int[][] copyOfBoard;
        
        for (int i = 1; i <= numOfValidBoardsToCreate; i++) {
            sudokuBoard = solver.generateSudokuBoard(emptyCellsPerBoard);

            // Create a copy of the board to pass to isSolvableBoard to test the condition without altering the board
            copyOfBoard = sudokuBoard.clone();

            if (solver.isSolvableBoard(copyOfBoard)) {
                System.out.println("Board #"+i);
                solver.printBoard(sudokuBoard);
                System.out.println("Solution of board #"+i);
                solver.solve(sudokuBoard);
                solver.printBoard(sudokuBoard);
            } else {
                numOfUnsolvableBoards++;
                numOfInvalidBoards++;
                i--; // run the loop again if we haven't reached the end
            }
        }

        // finding the time after the operation is executed
        long end = System.currentTimeMillis();
        //finding the time difference and converting it into seconds
        float sec = (end - start) / 1000F;

        // Print final message
        System.out.println("Empty Cells per board: " + emptyCellsPerBoard + "\nValid boards created: " + numOfValidBoardsToCreate + "\nInvalid boards created: "
                + numOfInvalidBoards + "\nUnsolvable boards created: " + numOfUnsolvableBoards + "\nElapsed time: " + sec + " seconds");
    }
}

boolean solve(int[][] board) {
    for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) {
        for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) {
            if (board[row][column] == NO_VALUE) {
                for (int k = MIN_VALUE; k <= MAX_VALUE; k++) {
                    board[row][column] = k;
                    if (isValid(board, row, column) && solve(board)) {
                        return true;
                    }
                    board[row][column] = NO_VALUE;
                }
                return false;
            }
        }
    }
    return true;
}

/**
 * Checks if a Sudoku board is valid and solvable.
 *
 * @param board The given board
 * @return True if it is or false otherwise.
 */
boolean isSolvableBoard(int[][] board) {
    return isValidBoard(board) && solve(board);
}

/**
 * Checks if the given sudoku board is valid.
 *
 * @param brd The 9x9 board
 * @return True if it's valid or false otherwise.
 */
private boolean isValidBoard(int[][] brd) {
    for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) {
        for (int j = BOARD_START_INDEX; j < BOARD_SIZE; j++) {
            try {
                if (!isValid(brd, i, j)) return false;
            } catch (ArrayIndexOutOfBoundsException e) { // if a given cell has a value > 9, an exception is thrown, so handle it
                return false;
            }
        }
    }
    return true;
}
publicstaticvoidmain(字符串[]args){
BacktrackingAlgorithm解算器=新的BacktrackingAlgorithm();
//从用户处获取所需的输入
扫描仪=新的扫描仪(System.in);
System.out.println(“输入电路板应具有的空单元数:”);
int emptyCellsPerBoard=scanner.nextInt();
System.out.println(“输入应用程序应该创建和解决的板数:”);
int numovalidboardstocreate=scanner.nextInt();
//为打印目的跟踪的额外数据
int numovalidboards=0;
int numobleboards=0;
//查找执行操作之前的时间
长启动=System.currentTimeMillis();
int[][]数独板;
int[][]电路板副本;
对于(inti=1;i9),会引发异常,因此请处理它
返回false;
}
}
}
返回true;
}

一个好的解决方案是:

for(int j=0; j <9; j++) {
  copyOfBoard[j] = Arrays.copyOf(sudokuBoard[j], sudokuBoard.length); // deep copy of the subarray
}

for(int j=0;j@Sebastian)我对此进行了研究,但即使迭代并将每个单元格添加到copyOfBoard数组中似乎也不起作用是浅层副本。使用任何循环/流式处理和复制数组实例仍将只提供浅层副本。请阅读此内容以了解您的选项:。当然,总有第三方API存在,但java lang为深度副本提供的选项很少。@Digitshift不应提供数组。copyOf()perofrm一个卷影副本?或者在单元格上迭代并将值分配给一个新的不同数组
int[]]newArr
?我想我已经尝试过了,但只得到了浅拷贝。让我再试一次-20分钟。是的,在2D数组上调用
clone()
时,它看起来像java,不会对子数组进行深度复制:(