JavaScript 中的井字游戏
TicTacToe Game in JavaScript
我一直在努力找出为什么我的 TicTacToe 游戏没有按照我想要的方式进行检查。因为我一直在看教程,但仍然无法弄清楚当玩家赢得游戏时正确使函数 winning
运行的逻辑。
这里我尝试将 O 或 X 推入数组,然后 console.log 看看它是什么样子以及为什么获胜条件检查不起作用。
spaces.push[id];
console.log(spaces);
我也尝试过其他方法来使程序正确,比如使用预制的获胜条件并通过映射当前数组,但也不起作用...
const winningCondition = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
对于单元格,我在 HTML 中创建了 9 个 div,并在 CSS 中使用了网格系统。
非常感谢您的帮助!以下是 TicTacToe 游戏的 JavaScript 代码:
const winning = (player) => {
if (spaces[0] === player) {
if (spaces[1] === player && spaces[2] === player) return true;
if (spaces[3] === player && spaces[6] === player) return true;
if (spaces[4] === player && spaces[8] === player) return true;
}
if (spaces[8] === player) {
if (spaces[2] === player && spaces[5] === player) return true;
if (spaces[6] === player && spaces[7] === player) return true;
}
if (spaces[4] === player) {
if (spaces[1] === player && spaces[7] === player) return true;
if (spaces[3] === player && spaces[5] === player) return true;
}
};
看起来棋盘是一个名为spaces
的数组,长度为九。看起来数组的值是 ' '
、'x'
或 'o'
,表示未被占用或被两个玩家之一占用。
您已经列举了获胜者必须占据的位置。检查获胜的简单函数将迭代该数组。
// assuming spaces is defined here as game state, an array 'x', 'o' or ' '
const winningLines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
// call with 'x' or 'o' representing player
function playerWon(player) {
const playerOccupiesLine = line => line.every(el => spaces[el] === player);
return winningLines.some(line => playerOccupiesLine(line);
}
没有理由 spaces.push(id)
将额外的元素添加到数组的末尾,只需将其删除即可。您已经有 spaces[id] = currentPlayer
将当前玩家值写入 spaces
.
中所需的位置
我发现的唯一问题是单元格应该有从 0 到 8 的数字,这些数字对应于 spaces
数组中的索引:
0
1
2
3
4
5
6
7
8
<div class="game">
<div class="cell" id="0"></div>
<div class="cell" id="1"></div>
<div class="cell" id="2"></div>
<div class="cell" id="3"></div>
<div class="cell" id="4"></div>
<div class="cell" id="5"></div>
<div class="cell" id="6"></div>
<div class="cell" id="7"></div>
<div class="cell" id="8"></div>
</div>
有 8 个获胜条件(3 行,3 列和 2 对角线)。缺少一个对角线条件:
if (spaces[4] === player) {
// ...
if (spaces[2] === player && spaces[6] === player) return true;
}
完整代码如下:
const cells = document.querySelectorAll(".cell");
const playText = document.getElementById("game-text");
const restartBtn = document.getElementById("restart");
const spaces = [];
const OPlayer = "O";
const XPlayer = "X";
let currentPlayer;
function handleClick(e) {
const id = e.target.id;
if (!spaces[id]) {
spaces[id] = currentPlayer;
console.log('[' + spaces.slice(0, 3) + ']\n[' + spaces.slice(3, 6) + ']\n[' + spaces.slice(6) + ']');
e.target.innerText = currentPlayer;
if (playerWon(currentPlayer)) {
const winningAlert = document.createElement("p");
winningAlert.setAttribute("id", "winning-text");
winningAlert.innerText = `${currentPlayer} HAS WON!`;
playText.appendChild(winningAlert);
setTimeout(() => {
restart();
}, 4000);
return;
}
currentPlayer = currentPlayer === OPlayer ? XPlayer : OPlayer;
}
}
cells.forEach((cell) => {
cell.addEventListener("click", handleClick);
});
const playerWon = (player) => {
if (spaces[0] === player) {
if (spaces[1] === player && spaces[2] === player) return true;
if (spaces[3] === player && spaces[6] === player) return true;
if (spaces[4] === player && spaces[8] === player) return true;
}
if (spaces[8] === player) {
if (spaces[2] === player && spaces[5] === player) return true;
if (spaces[6] === player && spaces[7] === player) return true;
}
if (spaces[4] === player) {
if (spaces[1] === player && spaces[7] === player) return true;
if (spaces[3] === player && spaces[5] === player) return true;
if (spaces[2] === player && spaces[6] === player) return true;
}
};
const restart = () => {
spaces.forEach((space, index) => {
console.log(space);
spaces[index] = null;
});
cells.forEach((cell) => {
cell.innerText = "";
});
playText.innerHTML = `LET'S PLAY!`;
currentPlayer = OPlayer;
};
restartBtn.addEventListener("click", restart);
restart();
* {
box-sizing: border-box;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
.game-board {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 6% 15%;
}
.game {
display: grid;
grid-gap: 1px;
grid-template-columns: repeat(3, 1fr);
}
.btn {
padding: 15px 18px;
margin: 30px auto auto auto;
width: 120px;
font-size: 18px;
border-radius: 8px;
border: none;
color: white;
background: green;
cursor: pointer;
}
.btn:hover {
transition-duration: 0.3s;
background-color: red;
transform: translateY(-5px);
}
.cell {
width: 150px;
height: 150px;
margin: 8px 8px;
border-radius: 15px;
background-color: brown;
text-align: center;
font-size: 120px;
}
#game-text {
font-size: 25px;
font-weight: bold;
text-transform: uppercase;
margin: -10px auto 25px auto;
}
#winning-text {
text-align: center;
margin-bottom: -20px;
font-size: 20px;
color: purple;
}
<section class="game-board">
<div id="game-text"></div>
<div class="game">
<div class="cell" id="0"></div>
<div class="cell" id="1"></div>
<div class="cell" id="2"></div>
<div class="cell" id="3"></div>
<div class="cell" id="4"></div>
<div class="cell" id="5"></div>
<div class="cell" id="6"></div>
<div class="cell" id="7"></div>
<div class="cell" id="8"></div>
</div>
<button class="btn" id="restart">Restart</button>
</section>
我一直在努力找出为什么我的 TicTacToe 游戏没有按照我想要的方式进行检查。因为我一直在看教程,但仍然无法弄清楚当玩家赢得游戏时正确使函数 winning
运行的逻辑。
这里我尝试将 O 或 X 推入数组,然后 console.log 看看它是什么样子以及为什么获胜条件检查不起作用。
spaces.push[id];
console.log(spaces);
我也尝试过其他方法来使程序正确,比如使用预制的获胜条件并通过映射当前数组,但也不起作用...
const winningCondition = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
对于单元格,我在 HTML 中创建了 9 个 div,并在 CSS 中使用了网格系统。
非常感谢您的帮助!以下是 TicTacToe 游戏的 JavaScript 代码:
const winning = (player) => {
if (spaces[0] === player) {
if (spaces[1] === player && spaces[2] === player) return true;
if (spaces[3] === player && spaces[6] === player) return true;
if (spaces[4] === player && spaces[8] === player) return true;
}
if (spaces[8] === player) {
if (spaces[2] === player && spaces[5] === player) return true;
if (spaces[6] === player && spaces[7] === player) return true;
}
if (spaces[4] === player) {
if (spaces[1] === player && spaces[7] === player) return true;
if (spaces[3] === player && spaces[5] === player) return true;
}
};
看起来棋盘是一个名为spaces
的数组,长度为九。看起来数组的值是 ' '
、'x'
或 'o'
,表示未被占用或被两个玩家之一占用。
您已经列举了获胜者必须占据的位置。检查获胜的简单函数将迭代该数组。
// assuming spaces is defined here as game state, an array 'x', 'o' or ' '
const winningLines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
// call with 'x' or 'o' representing player
function playerWon(player) {
const playerOccupiesLine = line => line.every(el => spaces[el] === player);
return winningLines.some(line => playerOccupiesLine(line);
}
没有理由 spaces.push(id)
将额外的元素添加到数组的末尾,只需将其删除即可。您已经有 spaces[id] = currentPlayer
将当前玩家值写入 spaces
.
我发现的唯一问题是单元格应该有从 0 到 8 的数字,这些数字对应于 spaces
数组中的索引:
0 | 1 | 2 |
---|---|---|
3 | 4 | 5 |
6 | 7 | 8 |
<div class="game">
<div class="cell" id="0"></div>
<div class="cell" id="1"></div>
<div class="cell" id="2"></div>
<div class="cell" id="3"></div>
<div class="cell" id="4"></div>
<div class="cell" id="5"></div>
<div class="cell" id="6"></div>
<div class="cell" id="7"></div>
<div class="cell" id="8"></div>
</div>
有 8 个获胜条件(3 行,3 列和 2 对角线)。缺少一个对角线条件:
if (spaces[4] === player) {
// ...
if (spaces[2] === player && spaces[6] === player) return true;
}
完整代码如下:
const cells = document.querySelectorAll(".cell");
const playText = document.getElementById("game-text");
const restartBtn = document.getElementById("restart");
const spaces = [];
const OPlayer = "O";
const XPlayer = "X";
let currentPlayer;
function handleClick(e) {
const id = e.target.id;
if (!spaces[id]) {
spaces[id] = currentPlayer;
console.log('[' + spaces.slice(0, 3) + ']\n[' + spaces.slice(3, 6) + ']\n[' + spaces.slice(6) + ']');
e.target.innerText = currentPlayer;
if (playerWon(currentPlayer)) {
const winningAlert = document.createElement("p");
winningAlert.setAttribute("id", "winning-text");
winningAlert.innerText = `${currentPlayer} HAS WON!`;
playText.appendChild(winningAlert);
setTimeout(() => {
restart();
}, 4000);
return;
}
currentPlayer = currentPlayer === OPlayer ? XPlayer : OPlayer;
}
}
cells.forEach((cell) => {
cell.addEventListener("click", handleClick);
});
const playerWon = (player) => {
if (spaces[0] === player) {
if (spaces[1] === player && spaces[2] === player) return true;
if (spaces[3] === player && spaces[6] === player) return true;
if (spaces[4] === player && spaces[8] === player) return true;
}
if (spaces[8] === player) {
if (spaces[2] === player && spaces[5] === player) return true;
if (spaces[6] === player && spaces[7] === player) return true;
}
if (spaces[4] === player) {
if (spaces[1] === player && spaces[7] === player) return true;
if (spaces[3] === player && spaces[5] === player) return true;
if (spaces[2] === player && spaces[6] === player) return true;
}
};
const restart = () => {
spaces.forEach((space, index) => {
console.log(space);
spaces[index] = null;
});
cells.forEach((cell) => {
cell.innerText = "";
});
playText.innerHTML = `LET'S PLAY!`;
currentPlayer = OPlayer;
};
restartBtn.addEventListener("click", restart);
restart();
* {
box-sizing: border-box;
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
.game-board {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 6% 15%;
}
.game {
display: grid;
grid-gap: 1px;
grid-template-columns: repeat(3, 1fr);
}
.btn {
padding: 15px 18px;
margin: 30px auto auto auto;
width: 120px;
font-size: 18px;
border-radius: 8px;
border: none;
color: white;
background: green;
cursor: pointer;
}
.btn:hover {
transition-duration: 0.3s;
background-color: red;
transform: translateY(-5px);
}
.cell {
width: 150px;
height: 150px;
margin: 8px 8px;
border-radius: 15px;
background-color: brown;
text-align: center;
font-size: 120px;
}
#game-text {
font-size: 25px;
font-weight: bold;
text-transform: uppercase;
margin: -10px auto 25px auto;
}
#winning-text {
text-align: center;
margin-bottom: -20px;
font-size: 20px;
color: purple;
}
<section class="game-board">
<div id="game-text"></div>
<div class="game">
<div class="cell" id="0"></div>
<div class="cell" id="1"></div>
<div class="cell" id="2"></div>
<div class="cell" id="3"></div>
<div class="cell" id="4"></div>
<div class="cell" id="5"></div>
<div class="cell" id="6"></div>
<div class="cell" id="7"></div>
<div class="cell" id="8"></div>
</div>
<button class="btn" id="restart">Restart</button>
</section>