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



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

solve()方法检查电路板是否可解,如果是,则求解并返回 true。现在,由于当我使用 for 循环的 if 语句检查每个板的有效性时isSolvableBoard()反过来调用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;
}

事实证明,一个好的解决方案如下:

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

它基本上执行 2D 阵列的每个子阵列的深度复制。

最新更新