井字游戏:重置游戏后无限获胜

Tic Tac Toe: Infinite winning after resetting game

我正在使用 HTML、CSS 和 JS 重新创建经典的井字游戏。

我已经让游戏 运行 成功进行了一场比赛,但在创建新游戏选项后功能似乎有一些错误。点击新游戏后,每次玩家标记一个方块时都会弹出获胜者消息。

游戏检查算法在 gameBoard 变量中,名为 checkWin。它在更新视图后在 displayController 内部调用。

图片显示问题:

除了在显示最终 X 位置(左下角)之前弹出获胜消息外正常工作

问题:点击新游戏后,我点击一个方块,弹出获胜消息。

let counter = 0;
let gameBoard = (function() {
  // 'use strict';

  let Board = ["", "", "", "", "", "", "", "", ""];

  let winningCombinations = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
  ]

  // has array 
  return {
    Board: Board,
    clickSquare: function(player) {
      document.querySelectorAll('td').forEach(item => {
        item.addEventListener('click', event => {
          // console.log(item.id.replace('_',''));
          player.markSquare(item.id.replace('_', ''));
        })
      });
    },
    checkWin: function() {
      return winningCombinations.some(combination => {
        return combination.every(index => {
          return Board[index] === "X"
        }) || combination.every(index => {
          return Board[index] === "O"
        })
      })
    }
  }
})();



let displayController = (function() {
  'use strict';

  function updateView(square) {
    console.log(square);
    document.querySelector("#_" + square).textContent = gameBoard.Board[square];
    if (gameBoard.checkWin() && counter % 2 === 0) {
      alert("Player One Wins!");
    } else if (gameBoard.checkWin() && counter % 2 !== 0) {
      alert("Player Two Wins!");
    } else if (counter == 8) {
      alert("TIE!");
    }
    counter++;
  }
  return {
    updateView: updateView
  }
})();

function createPlayer(name) {
  return {
    name: name,
    markSquare(square) {
      if (gameBoard.Board[square] === "") {
        if (counter % 2 === 0) {
          gameBoard.Board[square] = "X";
        } else {
          gameBoard.Board[square] = "O";
        }

        displayController.updateView(square);
      }
    }
  }
}

function gameFlow() {
  let player1 = createPlayer("Phil");
  gameBoard.clickSquare(player1);

  let resetGame = document.querySelector("button");
  resetGame.addEventListener('click', function() {
    for (let i = 0; i <= 8; i++) {
      document.querySelector("#_" + i).textContent = "";
    }
    gameBoard.Board = ["", "", "", "", "", "", "", "", ""];
    counter = 0;
  });

}
gameFlow();
body {
  margin: 0;
  font-family: 'Nunito', sans-serif;
}

h1 {
  text-align: center;
}

#playerNames {
  margin: auto;
  align-items: center;
  justify-content: center;
  display: flex;
}

input {
  width: 170px;
  height: 40px;
  font-size: 30px;
  margin: 0 30px 0 30px;
}

button {
  width: 100px;
  height: 100px;
  font-size: 30px;
  border-radius: 50%;
  background-color: yellow;
}

table {
  margin: auto;
}

td {
  width: 190px;
  height: 190px;
  text-align: center;
  font-size: 100px;
}

tr td:nth-of-type(2) {
  border-left: 2px solid black;
  border-right: 2px solid black;
}

tr:nth-of-type(2) td {
  border-top: 2px solid black;
  border-bottom: 2px solid black;
}
<!DOCTYPE html>
<html>

<head>
  <title></title>
  <link rel="stylesheet" type="text/css" href="TicTac.css">
  <link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
</head>

<body>
  <h1><b>Tic Tac Toe</b></h1>
  <div id="playerNames">
    <input id="pOne" placeholder="Player One" type="text">
    <button>New Game</button>
    <input id="pTwo" placeholder="Player Two" type="text">
  </div>

  <div>
    <table>
      <tr>
        <td id="_0"></td>
        <td id="_1"></td>
        <td id="_2"></td>
      </tr>
      <tr>
        <td id="_3"></td>
        <td id="_4"></td>
        <td id="_5"></td>
      </tr>
      <tr>
        <td id="_6"></td>
        <td id="_7"></td>
        <td id="_8"></td>
      </tr>

    </table>
  </div>

  <script src="TicTac.js"></script>
</body>

</html>

你很接近,但是你有两个问题。

一个是您没有将 click 事件正确添加到“新游戏”按钮。我进行了快速编辑以使其工作,但还有其他方法可以做到。

第二个是您将一个新数组分配给 gameBoard.Board.Board。我不确定为什么这不起作用,但在您已有的循环中重置当前值确实有效。

进行这两项小改动似乎可以让一切正常进行。我使用 console.logs 来确保不仅 运行 是正确的,而且还可以查看变量中的值。它帮助我快速确定单击按钮时未调用“重置”方法,并确认数据未按预期更新。我留在了这些日志中,因此您可以将它们视为如何使用它们的示例。我还留下了我注释掉的代码以显示一些差异,所以不要忘记清理所有这些。

顺便说一句,有些事情可以做得更好,但到目前为止做得很好。这在工作时确实相当干净简洁。

let counter = 0;
let gameBoard = (function() {
    // 'use strict';

    let Board = ["", "", "", "", "","","","",""];

    let winningCombinations = [
        [0,1,2],
        [3,4,5],
        [6,7,8],
        [0,3,6],
        [1,4,7],
        [2,5,8],
        [0,4,8],
        [2,4,6]
    ]

    // has array 
    return {
        Board: Board,
        clickSquare: function(player) {
            document.querySelectorAll('td').forEach(item => {
                item.addEventListener('click', event => {
                    // console.log(item.id.replace('_',''));
                    player.markSquare(item.id.replace('_',''));
                })
            });       
        },
        checkWin: function() {
        console.log(Board);
            return winningCombinations.some(combination => {
                return combination.every(index => {
                    return Board[index] === "X"
                }) || combination.every(index => {
                    return Board[index] === "O"
            })
        })
        }
    }
})();



let displayController = (function() {
    'use strict';

    function updateView(square) {
            console.log(square);
            document.querySelector("#_"+square).textContent = gameBoard.Board[square];
            if (gameBoard.checkWin() && counter %2 === 0) {
                alert("Player One Wins!");
            }
            else if (gameBoard.checkWin() && counter %2 !== 0) {
                alert("Player Two Wins!");
            }
            else if (counter == 8) {
                alert("TIE!");
            }
            counter++;
    }
    return {
        updateView: updateView
    }
})();

function createPlayer(name) {
    return {
        name: name,
        markSquare(square) {
            if (gameBoard.Board[square] === "") {
                if (counter %2 === 0) {
                    gameBoard.Board[square] = "X";
                }
                else {
                    gameBoard.Board[square] = "O";
                }
                
                displayController.updateView(square);
            }
        }
    }
}

function gameFlow() {
    let player1 = createPlayer("Phil");
    gameBoard.clickSquare(player1);

    let resetGame = document.getElementById("resetbutton");
    resetGame.addEventListener('click', function() {
        console.log("reset");
        for (let i =0; i<=8; i++) {
            document.querySelector("#_"+i).textContent="";
            gameBoard.Board[i] = "";
        }
        //gameBoard.Board = ["", "", "", "", "","","","",""];
        counter = 0;
    });
        
}
gameFlow();
body {
    margin: 0;
    font-family: 'Nunito', sans-serif;

}
h1 {
    text-align: center;
}
#playerNames {
    margin: auto;
    align-items: center;
    justify-content: center;
    display: flex;
}
input {
    width:170px;
    height: 40px;
    font-size: 30px;
    margin: 0 30px 0 30px;
}
button {
    width:100px;
    height: 100px;
    font-size: 30px;
    border-radius: 50%;
    background-color: yellow;
}
table {
    margin: auto;
}
td {
    width: 190px;
    height: 190px;
    text-align: center;
    font-size: 100px;
}
tr td:nth-of-type(2) {
    border-left: 2px solid black;
    border-right:2px solid black;
}
tr:nth-of-type(2) td {
    border-top: 2px solid black;
    border-bottom: 2px solid black;
}
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <link rel="stylesheet" type="text/css" href="TicTac.css">
    <link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
</head>
<body>
    <h1><b>Tic Tac Toe</b></h1>
    <div id="playerNames">
        <input id="pOne" placeholder="Player One" type="text">
        <button id="resetbutton">New Game</button>
        <input id="pTwo" placeholder="Player Two" type="text">
    </div>
    
    <div>
    <table>
        <tr>
            <td id="_0"></td>
            <td id="_1"></td>
            <td id="_2"></td>
        </tr>
        <tr>
            <td id="_3"></td>
            <td id="_4"></td>
            <td id="_5"></td>
        </tr>
        <tr>
            <td id="_6"></td>
            <td id="_7"></td>
            <td id="_8"></td>
        </tr>

    </table>
</div>

<script src="TicTac.js"></script>
</body>
</html>