井字游戏:重置游戏后无限获胜
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.log
s 来确保不仅 运行 是正确的,而且还可以查看变量中的值。它帮助我快速确定单击按钮时未调用“重置”方法,并确认数据未按预期更新。我留在了这些日志中,因此您可以将它们视为如何使用它们的示例。我还留下了我注释掉的代码以显示一些差异,所以不要忘记清理所有这些。
顺便说一句,有些事情可以做得更好,但到目前为止做得很好。这在工作时确实相当干净简洁。
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>
我正在使用 HTML、CSS 和 JS 重新创建经典的井字游戏。
我已经让游戏 运行 成功进行了一场比赛,但在创建新游戏选项后功能似乎有一些错误。点击新游戏后,每次玩家标记一个方块时都会弹出获胜者消息。
游戏检查算法在 gameBoard 变量中,名为 checkWin。它在更新视图后在 displayController 内部调用。
图片显示问题:
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.log
s 来确保不仅 运行 是正确的,而且还可以查看变量中的值。它帮助我快速确定单击按钮时未调用“重置”方法,并确认数据未按预期更新。我留在了这些日志中,因此您可以将它们视为如何使用它们的示例。我还留下了我注释掉的代码以显示一些差异,所以不要忘记清理所有这些。
顺便说一句,有些事情可以做得更好,但到目前为止做得很好。这在工作时确实相当干净简洁。
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>