slice方法返回引用

时间:2018-09-12 11:36:26

标签: javascript reactjs

我正在通过回溯算法对数独求解器进行编码。

为什么我的代码中的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;
    }

1 个答案:

答案 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);