在 [...HTMLCollection] 上使用 arr.every() 不会返回真正的元素更改

问题描述 投票:0回答:2

我正在尝试构建一个 Tic Tac Toe 游戏,因此我尝试先使用

getElementsByClassName()
来收集数组中的游戏框区域,然后再使用展开运算符将集合转换为数组。 但是当我尝试使用
arr.every()
方法来检查是否所有的盒子都被播放时,即使所有的盒子都被填满了我仍然得到
false

这是我的HTML代码

<div class="board">
  <div class="board-sections">
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
   </div>
</div>

首先我收集了所有的游戏盒。

let boxes = document.getElementsByClassName("play-box");
let numOfBoxes = boxes.length;

然后我将集合转换为数组并应用条件来检查所有框是否不为空

let boxesArr = [...boxes];
let checkBoxes = boxesArr.every(function(box) {
  return box.innerHTML !== "";
});

然后我创建了一个函数来检查是否所有的框都不为空

function checkBoard() {
  if (checkBoxes) {
    console.log("All Filled");
  }
}

然后我创建了一个函数来向每个框添加文本,并通过调用 checkBoard() 函数 onclick 检查是否所有框都已填充。

for (var i = 0; i < numOfBoxes; i++) {
  boxes[i].addEventListener("click", addChip);
}

addChip()
函数在单击时向每个框添加文本,然后检查是否所有框都已填充

function addChip() {
  this.innerHTML = "X";
  checkBoard();
}

框在单击时被填充,我希望

checkBoard()
函数在所有框都填充后返回
true
,但是在所有框都填充后
checkBoard()
函数仍然返回
false.

这是完整代码的样子

let boxes = document.getElementsByClassName("play-box");
let numOfBoxes = boxes.length;

let boxesArr = [...boxes];
let checkBoxes = boxesArr.every(function(box) {
  return box.innerHTML !== "";
});

function checkBoard() {
  if (checkBoxes) {
    console.log("All Filled");
  }
}

for (var i = 0; i < numOfBoxes; i++) {
  boxes[i].addEventListener("click", addChip);
}

function addChip() {
  this.innerHTML = "X";
  checkBoard();
}
.board {
  text-align: center;
  max-width: 100%;
  width: 500px;
  margin: auto;
}

.board-sections {
  display: grid;
  grid-template-columns: auto auto auto;
  background: #ccc;
  gap: 5px;
  align-content: center;
}

.play-box {
  height: 100px;
  background: transparent;
  border: 1px solid #000;
  min-width: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="board">
  <div class="board-sections">
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
    <div class="play-box"></div>
  </div>
</div>

javascript arrays function tic-tac-toe htmlcollection
2个回答
0
投票

没有实际代码很难回答你的问题。下面我组装了一个实际可行的可能场景。或许对你有帮助?

const pb=[...document.querySelectorAll(".play-box")];
document.querySelectorAll("button").forEach(b=>{
 b.addEventListener("click",ev=>{
  if(b.textContent=="check")
   console.log(pb.every(p=>p.textContent!=""))
  else
   pb.forEach(p=>p.textContent="X");
 })
})
.play-box {display:inline-block; width:40px;height:40px; border:1px solid grey}
<div class="board">
  <div class="board-sections">
<div class="play-box"></div>
<div class="play-box"></div>
<div class="play-box"></div><br>
<div class="play-box"></div>
<div class="play-box"></div>
<div class="play-box"></div><br>
<div class="play-box"></div>
<div class="play-box"></div>
<div class="play-box"></div>
   </div>
</div>
<button>check</button> <button>fill</button>

我想说的是,

.textContent
元素的
.play-box
必须在after 被填充后进行检查。 OP 的原始脚本只在页面加载后立即进行了一次检查。

解释:
上面代码片段中的关键部分是表达式

pb.every(p=>p.textContent!="")

如果所有的盒子都以某种方式填满,它会返回

true
。在您的井字游戏中,这需要在每次设置“X”或“O”后执行。

你的

checkBoard
函数应该是这样的:

function checkBoard() {
  if (boxesArr.every(p=>p.textContent!="")) {
    console.log("All Filled");
  }
}

0
投票

你的

checkBoxes
持有一个布尔值,而不是一个函数:

// This is wrong
let checkBoxes = boxesArr.every(function(box) {
  return box.innerHTML !== "";
});

它只会返回游戏开始前的状态值。你不能在游戏中像

if (checkBoxes)
那样重复使用它并期望更新值。
相反,返回一个返回布尔值的函数,就像
if (checkBoxes()) {
:

const boxes = document.querySelectorAll(".board-box");
const numOfBoxes = boxes.length;

const checkBoxes = () => [...boxes].every((box) => box.textContent.trim() !== "");

function checkBoard() {
  if (checkBoxes()) {
    console.log("All Filled");
  }
}

boxes.forEach((box) => {
  box.addEventListener("click", addChip);
});


function addChip() {
  this.textContent = "X";
  checkBoard();
}
.board {
  text-align: center;
  max-width: 100%;
  width: 500px;
  margin: auto;
}

.board-sections {
  display: grid;
  grid-template-columns: auto auto auto;
  background: #ccc;
  gap: 5px;
  align-content: center;
}

.board-box {
  height: 100px;
  background: transparent;
  border: 1px solid #000;
  min-width: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="board">
  <div class="board-sections">
    <div class="board-box"></div>
    <div class="board-box"></div>
    <div class="board-box"></div>
    <div class="board-box"></div>
    <div class="board-box"></div>
    <div class="board-box"></div>
    <div class="board-box"></div>
    <div class="board-box"></div>
    <div class="board-box"></div>
  </div>
</div>

此外,使用

textContent
返回 text 而不是
innerHTML


此外,您可以将代码简化为:

const boxes = document.querySelectorAll(".board-box");
const tot = boxes.length;
let turn = 0;

const isBoxEmpty = (box) => box.textContent.trim() === "";

const checkBoard = () => {
  if (![...boxes].some(isBoxEmpty)) {
    console.log("All Filled");
  }
};

const addChip = (ev) => {
  const box = ev.currentTarget;
  if (!isBoxEmpty(box)) return; // Not an empty box. Exit function here.
  
  this.textContent = (turn % 2) ? "O" : "X";
  checkBoard();
  // Increment turn
  turn += 1;
}

boxes.forEach((box) => box.addEventListener("click", addChip));
.board {
  font: 14vmin/1 sans-serif;
  margin: auto;
  display: inline-grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
}

.board-box {
  height: 20vmin;
  aspect-ratio: 1;
  border: 2px solid #000;
  display: flex;
  align-items: center;
  justify-content: center;
  user-select: none;
}
<div class="board">
  <div class="board-box"></div>
  <div class="board-box"></div>
  <div class="board-box"></div>
  <div class="board-box"></div>
  <div class="board-box"></div>
  <div class="board-box"></div>
  <div class="board-box"></div>
  <div class="board-box"></div>
  <div class="board-box"></div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.