javascript - 在第一个事件侦听器单击执行后退出 for 循环
问题描述
我正在开发井字游戏,我希望用户能够单击板上的九个框之一。我实现了一个for loop
在每个 div 上运行,允许用户单击每个 div。
在他们选择了他们的盒子后,计算机将开始移动。
一旦用户选择了他们的框,我该如何停止循环?先感谢您
//initial variables
let box = document.querySelectorAll(".box");
let letter = document.querySelector('.letter');
let turn = 0;
//START GAME
let userXorO = function() { //function to determine whose x and o
let X = 1;
let O = 2;
let random = Math.floor(Math.random() * 2) + 1; //randomizes between x and o
if (random == X) {
return 'X'
}
if (random == O) {
return 'O'
}
return random; //returns random number to function
}
//PLAYER ONE INITIAL TURN
function turn_one() {
for (let i = 0; i < box.length; i++) {
if (turn === 0) {
box[i].addEventListener("click", function(e) {
box[i].textContent = userXorO(); //draws first user X or O
turn ++;
});
}
}
}
turn_one();
.game-board {
width: 600px;
height: 600px;
margin: 0 auto;
background-color: #34495e;
color: #fff;
border: 6px solid #2c3e50;
border-radius: 10px;
display: grid;
grid-template: repeat(3, 1fr) / repeat(3, 1fr);
}
.box {
border: 6px solid #2c3e50;
border-radius: 2px;
font-family: Helvetica;
font-weight: bold;
font-size: 4em;
display: flex;
justify-content: center;
align-items: center;
}
.player_one {
background-color: red;
}
<div class="game-board">
<div id="1" class="box"><span id="1" class="letter"></span></div>
<div id="2" class="box"><span id="2" class="letter"></span></div>
<div class="box"><span id="3" class="letter"></span></div>
<div class="box"><span id="" class="letter"></span></div>
<div class="box"><span id="" class="letter"></span></div>
<div class="box"><span id="" class="letter"></span></div>
<div class="box"><span id="" class="letter"></span></div>
<div class="box"><span id="" class="letter"></span></div>
<div class="box"><span id="" class="letter"></span></div>
</div>
解决方案
与其在人类第一次选择一个框后添加许多您可能会尝试删除的侦听器,不如在整个容器中仅添加一个侦听器(这称为事件委托),您可能会发现逻辑更容易遵循,并且使用类似的变量检查点击当前是否有效isHumanTurn
。(当然,如果计算机立即轮到它,则无需isHumanTurn
检查。)
另请注意,同一文档中的重复 ID 是无效的 HTML - 最好将其删除。(要检查在其容器中单击的索引div
,您可以indexOf
在 s 的数组上使用div
)
另一个问题是你应该在游戏开始时构建 randomX
或O
once,而不是在每次点击时,否则它会不一致。
例如:
const humanTile = ['X', 'O'][Math.floor(Math.random() * 2)];
let isHumanTurn = true;
function handleClick({ target }) {
if (!target.matches('.box')) return;
if (!isHumanTurn) return console.log('It is not your turn!');
target.textContent = humanTile; //draws first user X or O
isHumanTurn = false;
console.log('insert function call for computer to take its turn...');
}
document.querySelector('.game-board').addEventListener('click', handleClick);
.game-board {
width: 600px;
height: 600px;
margin: 0 auto;
background-color: #34495e;
color: #fff;
border: 6px solid #2c3e50;
border-radius: 10px;
display: grid;
grid-template: repeat(3, 1fr) / repeat(3, 1fr);
}
.box {
border: 6px solid #2c3e50;
border-radius: 2px;
font-family: Helvetica;
font-weight: bold;
font-size: 4em;
display: flex;
justify-content: center;
align-items: center;
}
.player_one {
background-color: red;
}
<div class="game-board">
<div class="box"><span class="letter"></span></div>
<div class="box"><span class="letter"></span></div>
<div class="box"><span class="letter"></span></div>
<div class="box"><span class="letter"></span></div>
<div class="box"><span class="letter"></span></div>
<div class="box"><span class="letter"></span></div>
<div class="box"><span class="letter"></span></div>
<div class="box"><span class="letter"></span></div>
<div class="box"><span class="letter"></span></div>
</div>
推荐阅读
- javascript - rxjs - how do I debounceTime for multiple incoming events target multiple different objects dependent of an internal identifier
- c# - 将复杂的源扁平化到目标时如何重用现有的映射配置?
- php - 从 Woocommerce 中删除数量字段,而不阻止添加多个购物车?
- c++ - sizeof unsigned char,将 std::string 转换为 unsigned char
- azure - 默认情况下,Azure 子网中的 VM 之间的所有端口是否都打开
- sql - 在 T-SQL 中解析对象内的 JSON 数组
- django - Django AJAX删除deleteView中的对象
- wordpress - Wordpress /Cloudflare(完整 SSL)的这个 GTmetrix SSL 错误是什么意思?
- laravel - 如何解决 Laravel6 中的控制器错误?
- vba - 通过 VBA 检查文件是否存在于 OneDrive 中