如何让前一个按钮作为每个井字棋移动的撤消按钮?

How do I get the previous button to work as a undo button for each Tic Tac Toe move?

为什么我recordBoardState()的时候,之前推送的boardboardState在Google更新到最新的boardChrome 实时服务器?这会阻止我的 previousMove() 将更改应用到 HTML 文档。我能做些什么来防止这种情况发生吗?

let board = [
  ["", "", ""],
  ["", "", ""],
  ["", "", ""]
]


const boardState = []

var square1 = document.getElementById("square1")
square1.addEventListener("click", function(el) {
  if (turnMove() % 2 === 0) {
    square1.innerHTML = "X"
    board[0].splice(0, 1, "X")
  } else {
    square1.innerHTML = "O"
    board[0].splice(0, 1, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})

var square2 = document.getElementById("square2")
square2.addEventListener("click", function(el) {
  if (turnMove() % 2 === 0) {
    square2.innerHTML = "X"
    board[0].splice(1, 1, "X")
  } else {
    square2.innerHTML = "O"
    board[0].splice(1, 1, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})

var square3 = document.getElementById("square3")
square3.addEventListener("click", function(el) {
  if (turnMove() % 2 === 0) {
    square3.innerHTML = "X"
    board[0].splice(2, 2, "X")
  } else {
    square3.innerHTML = "O"
    board[0].splice(2, 2, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})

var square4 = document.getElementById("square4")
square4.addEventListener("click", function(el) {
  if (turnMove() % 2 === 0) {
    square4.innerHTML = "X"
    board[1].splice(0, 1, "X")
  } else {
    square4.innerHTML = "O"
    board[1].splice(0, 1, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})

var square5 = document.getElementById("square5")
square5.addEventListener("click", function(el) {
  if ((turnMove() % 2 === 0)) {
    square5.innerHTML = "X"
    board[1].splice(1, 1, "X")
  } else {
    square5.innerHTML = "O"
    board[1].splice(1, 1, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})

var square6 = document.getElementById("square6")
square6.addEventListener("click", function(el) {
  if ((turnMove() % 2 === 0)) {
    square6.innerHTML = "X"
    board[1].splice(2, 2, "X")
  } else {
    square6.innerHTML = "O"
    board[1].splice(2, 2, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})

var square7 = document.getElementById("square7")
square7.addEventListener("click", function(el) {
  if ((turnMove() % 2 === 0)) {
    square7.innerHTML = "X"
    board[2].splice(0, 1, "X")
  } else {
    square7.innerHTML = "O"
    board[2].splice(0, 1, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})

var square8 = document.getElementById("square8")
square8.addEventListener("click", function(el) {
  if ((turnMove() % 2 === 0)) {
    square8.innerHTML = "X"
    board[2].splice(1, 1, "X")
  } else {
    square8.innerHTML = "O"
    board[2].splice(1, 1, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})

var square9 = document.getElementById("square9")
square9.addEventListener("click", function(el) {
  if ((turnMove() % 2 === 0)) {
    square9.innerHTML = "X"
    board[2].splice(2, 2, "X")
  } else {
    square9.innerHTML = "O"
    board[2].splice(2, 2, "O")
  }
  console.log(board)
  recordBoardState()
  checkRowWin()
  checkColWin()
  checkDiagWin()
})



// const turnMove = () => turns++;
let turns = 0;

function turnMove() {
  return turns++
}

function checkRowWin() {
  board.forEach((row, index) => {
    if (row.toString() === "X,X,X") {
      if (index === 0) {
        square1.style.backgroundColor = "yellow"
        square2.style.backgroundColor = "yellow"
        square3.style.backgroundColor = "yellow"
        document.getElementById("buttons").style.display = "flex"
      } else if (index === 1) {
        square4.style.backgroundColor = "yellow"
        square5.style.backgroundColor = "yellow"
        square6.style.backgroundColor = "yellow"
        document.getElementById("buttons").style.display = "flex"
      } else {
        square7.style.backgroundColor = "yellow"
        square8.style.backgroundColor = "yellow"
        square9.style.backgroundColor = "yellow"
        document.getElementById("buttons").style.display = "flex"
      }
    }
    if (row.toString() === "O,O,O") {
      if (index === 0) {
        square1.style.backgroundColor = "yellow"
        square2.style.backgroundColor = "yellow"
        square3.style.backgroundColor = "yellow"
        document.getElementById("buttons").style.display = "flex"
      } else if (index === 1) {
        square4.style.backgroundColor = "yellow"
        square5.style.backgroundColor = "yellow"
        square6.style.backgroundColor = "yellow"
        document.getElementById("buttons").style.display = "flex"
      } else {
        square7.style.backgroundColor = "yellow"
        square8.style.backgroundColor = "yellow"
        square9.style.backgroundColor = "yellow"
        document.getElementById("buttons").style.display = "flex"
      }
    }
  })
}


function checkColWin() {
  if (board[0][0] === "X" && board[1][0] === "X" && board[2][0] === "X") {
    square1.style.backgroundColor = "yellow"
    square4.style.backgroundColor = "yellow"
    square7.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
  if (board[0][1] === "X" && board[1][1] === "X" && board[2][1] === "X") {
    square2.style.backgroundColor = "yellow"
    square5.style.backgroundColor = "yellow"
    square8.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
  if (board[0][2] === "X" && board[1][2] === "X" && board[2][2] === "X") {
    square3.style.backgroundColor = "yellow"
    square6.style.backgroundColor = "yellow"
    square9.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
  if (board[0][0] === "O" && board[1][0] === "O" && board[2][0] === "O") {
    square1.style.backgroundColor = "yellow"
    square4.style.backgroundColor = "yellow"
    square7.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
  if (board[0][1] === "O" && board[1][1] === "O" && board[2][1] === "O") {
    square2.style.backgroundColor = "yellow"
    square5.style.backgroundColor = "yellow"
    square8.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
  if (board[0][2] === "O" && board[1][2] === "O" && board[2][2] === "O") {
    square3.style.backgroundColor = "yellow"
    square6.style.backgroundColor = "yellow"
    square9.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
}

function checkDiagWin() {
  if (board[0][0] === "X" && board[1][1] === "X" && board[2][2] === "X") {
    square1.style.backgroundColor = "yellow"
    square5.style.backgroundColor = "yellow"
    square9.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
  if (board[0][2] === "X" && board[1][1] === "X" && board[2][0] === "X") {
    square3.style.backgroundColor = "yellow"
    square5.style.backgroundColor = "yellow"
    square7.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
  if (board[0][0] === "O" && board[1][1] === "O" && board[2][2] === "O") {
    square1.style.backgroundColor = "yellow"
    square5.style.backgroundColor = "yellow"
    square9.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
  if (board[0][2] === "O" && board[1][1] === "O" && board[2][0] === "O") {
    square3.style.backgroundColor = "yellow"
    square5.style.backgroundColor = "yellow"
    square7.style.backgroundColor = "yellow"
    document.getElementById("buttons").style.display = "flex"
  }
}

function resetGame() {
  const squares = document.getElementsByClassName("square")
  for (let i = 0; i < squares.length; i++) {
    squares[i].textContent = ""
    squares[i].style.backgroundColor = "aliceblue"
  }
  for (let i = 0; i < board.length; i++) {
    board[i].splice(0, 3, ["", "", ""])
  }
  document.getElementById("buttons").style.display = "none"
  boardState = []
  console.log(board)
  console.log(boardState)
}

function recordBoardState() {
  boardState.push(board)
  console.log(boardState)
}

function previousMove() {
  boardState.pop()
  square1.textContent = boardState[boardState.length - 1][0][0]
  square2.textContent = boardState[boardState.length - 1][0][1]
  square3.textContent = boardState[boardState.length - 1][0][2]
  square4.textContent = boardState[boardState.length - 1][1][0]
  square5.textContent = boardState[boardState.length - 1][1][1]
  square6.textContent = boardState[boardState.length - 1][1][2]
  square7.textContent = boardState[boardState.length - 1][2][0]
  square8.textContent = boardState[boardState.length - 1][2][1]
  square9.textContent = boardState[boardState.length - 1][2][2]
  console.log(boardState)
  const squares = document.getElementsByClassName("square")
  for (let i = 0; i < squares.length; i++) {
    squares[i].style.backgroundColor = "aliceblue"
  }

}
#board {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  max-width: 40%;
  height: 40vw;
  margin: auto;
  border: 2px solid black;
  text-align: center;
  font-size: 5rem;
}

.square {
  background-color: aliceblue;
  border: 1px solid black;
}

#buttons {
  display: none;
  align-items: center;
  justify-content: center;
  margin-top: 1rem;
}

button {
  width: 10%;
  font-size: medium;
  margin: 1rem;
}
<html>

<head>
  <title>Tic Tac Toe Game</title>
  <link rel="stylesheet" href="style.css">
  <meta name="viewport" content="width-device-width initial-scale=1">
</head>

<body>
  <div id="board">
    <div id="square1" class="square"></div>
    <div id="square2" class="square"></div>
    <div id="square3" class="square"></div>

    <div id="square4" class="square"></div>
    <div id="square5" class="square"></div>
    <div id="square6" class="square"></div>

    <div id="square7" class="square"></div>
    <div id="square8" class="square"></div>
    <div id="square9" class="square"></div>
    <script type="text/javascript" src="script.js"></script>
  </div>

  <div id="buttons">
    <button id="previous" onclick="previousMove()">Previous</button>
    <button id="reset" onclick="resetGame()">Reset</button>
    <button id="next">Next</button>
  </div>
</body>

</html>

您每次都在推送相同的对象引用,它会在随后的回合中发生变异。而是尝试推送板数据的克隆:

function recordBoardState() {
  boardState.push(board.map(row => row.map(cell => cell)))
}

function previousMove() {
  board = boardState.pop()
  ...
}