我正在通过回溯算法对数独求解器进行编码。
为什么我的代码中的slice()方法返回引用?我知道,如果数组不是Number,String或Boolean,则slice方法将返回引用。但是在我的代码中,数组填充为0,这怎么可能?
backtrack() {
if (this.state.IsEnd === true)
return true;
const board = this.state.squares.slice(); //board array is the reference of this.state.squares array;
let row, col;
if (!this.findvalid()) {
this.setState({
IsEnd: true
});
return true;
}
let ok = false;
for (let i = 0; i < 9; i++) {
if (ok)
break;
for (let j = 0; j < 9; j++) {
if (board[i][j] === 0 || isNaN(board[i][j])) {
row = i;
col = j;
ok = true;
break;
}
}
}
for (let num = 1; num <= 9; num++) {
if (this.isSafe(row, col, num)) {
board[row][col] = num; /*when board changes,the state squares also changes.*/
this.setState({
squares: board
}); /*when I delete this line,every thing is still the same.*/
if (this.backtrack()) {
return true;
}
board[row][col] = 0;
this.setState({
squares: board
});
}
}
return false;
}
这是我的完整代码
//this function create a board
function createBoard() {
let board = Array(9);
for (let i = 0; i < 9; i++) {
let subarray = Array(9).fill(0);
board[i] = subarray;
}
return board;
}
class App_sudoku_solver extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: createBoard(),
IsEnd: false
}
this.handleChange = this.handleChange.bind(this);
this.SafeBox = this.SafeBox.bind(this);
this.SafeCol = this.SafeCol.bind(this);
this.SafeRow = this.SafeRow.bind(this);
this.isSafe = this.isSafe.bind(this);
this.findvalid = this.findvalid.bind(this);
this.backtrack = this.backtrack.bind(this);
this.solve = this.solve.bind(this);
this.check = this.check.bind(this);
this.restart = this.restart.bind(this);
}
//check if any cell is empty
findvalid() {
const board = this.state.squares.slice();
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (board[i][j] === 0 || isNaN(board[i][j]))
return true;
}
}
return false;
}
// check valid 3x3 squares
SafeBox(startrow, startcol, num) {
const board = this.state.squares.slice();
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (board[startrow + i][startcol + j] === num)
return false;
}
}
return true;
}
//check valid row
SafeRow(row, num) {
const board = this.state.squares.slice();
for (let i = 0; i < 9; i++) {
if (board[row][i] === num)
return false;
}
return true;
}
//check valid column
SafeCol(col, num) {
const board = this.state.squares.slice();
for (let i = 0; i < 9; i++) {
if (board[i][col] === num)
return false;
}
return true;
}
//check if this number is valid in the cell
isSafe(row, col, num) {
return (this.SafeRow(row, num) === true && this.SafeCol(col, num) === true && this.SafeBox(row - row % 3, col - col % 3, num) === true);
}
//solve sudoku by backtrack
backtrack() {
if (this.state.IsEnd === true)
return true;
const board = this.state.squares.slice();
let row, col;
if (!this.findvalid()) {
this.setState({
IsEnd: true
});
return true;
}
let ok = false;
for (let i = 0; i < 9; i++) {
if (ok)
break;
for (let j = 0; j < 9; j++) {
if (board[i][j] === 0 || isNaN(board[i][j])) {
row = i;
col = j;
ok = true;
break;
}
}
}
for (let num = 1; num <= 9; num++) {
if (this.isSafe(row, col, num)) {
board[row][col] = num;
this.setState({
squares: board
});
if (this.backtrack()) {
return true;
}
board[row][col] = 0;
this.setState({
squares: board
});
}
}
return false;
}
答案 0 :(得分:0)
this.state.squares是一个数组数组,未填充0
如果要在其上运行切片的数组包含任何对象,则该方法将仅复制对其的引用。由于您的数组包含数组-因此也包含对象,因此其所有元素只能通过引用进行复制。
function createBoard() {
let board = new Array(9);
for (let i = 0; i < 9; i++) {
let subarray = Array(9).fill(0);
board[i] = subarray;
}
return board;
}
// 2d array containing 9 arrays
let board = createBoard();
console.log("Board: ", board);
const modifiedSlicedBoard = board.slice()[0][2] = 9999999; // I'm modifying the contents of one of the sub-arrays. Because the arrays are copied shallowly, this will also modify the original board
console.log(board, modifiedSlicedBoard);