const winCombos = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[6, 4, 2]
];
let playerTurn = 'X';
for(let i = 0; i < 9; i++) {
const cell = document.getElementById('c' + i);
cell.addEventListener('click', startGame);
function startGame() {
cell.innerHTML = playerTurn;
if(checkForWin()) {
alert('game over');
}
}
}
function checkForWin() {
for(let i = 0; i < winCombos.length; i++) {
const c0 = document.getElementById('c' + winCombos[i][0]);
const c1 = document.getElementById('c' + winCombos[i][1]);
const c2 = document.getElementById('c' + winCombos[i][2]);
if(c0.innerHTML===playerTurn&&
c1.innerHTML===playerTurn&&
c2.innerHTML===playerTurn) {
return true;
} else {
return false;
}
}
}
td {
border: 2px solid #333;
height: 100px;
width: 100px;
text-align: center;
vertical-align: middle;
font-family: "Comic Sans MS", cursive, sans-serif;
font-size: 70px;
cursor: pointer;
}
table {
border-collapse: collapse;
position: absolute;
left: 50%;
margin-left: -155px;
top: 220px;
}
table tr:first-child td {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child {
border-left: 0;
}
table tr td:last-child {
border-right: 0;
}
.endgame {
display: none;
width: 200px;
top: 120px;
background-color: red;
position: absolute;
left: 50%;
margin-left: -100px;
padding-top: 50px;
padding-bottom: 50px;
text-align: center;
border-radius: 5px;
color: white;
font-size: 2em;
}
<!DOCTYPE html>
<html>
<head>
<title>tic tac toe</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<table>
<tr>
<td class="cell" id="c0"></td>
<td class="cell" id="c1"></td>
<td class="cell" id="c2"></td>
</tr>
<tr>
<td class="cell" id="c3"></td>
<td class="cell" id="c4"></td>
<td class="cell" id="c5"></td>
</tr>
<tr>
<td class="cell" id="c6"></td>
<td class="cell" id="c7"></td>
<td class="cell" id="c8"></td>
</tr>
<div class="endgame">
<div class="text">Cant see this text</div>
</div>
</table>
<script type="text/javascript" src="script2.js"></script>
</body>
</html>
嘿,我正在尝试制作一个简单的JS tic tac toe游戏。现在,我要做的只是第3行'X'向上,一旦放置第3个X以构成获胜组合,我就希望收到警报消息。但是,当您单击以放置第三个“ X”以赢得游戏时,警报消息立即显示,然后显示了第三个“ X”?为什么会这样,谢谢您的帮助。
答案 0 :(得分:1)
这里要了解的重要事项是javascript在单线程模型中运行。现在,让我们看一下您的代码:
cell.addEventListener('click', startGame);
function startGame() {
cell.innerHTML = playerTurn;
if(checkForWin()) {
alert('game over');
}
}
在click事件处理程序中,您需要执行以下操作:
从CPU的角度来看,所有这些“动作”都是顺序执行的,因此您希望单元的内容首先被呈现,对吧?但是,事实并非如此。当您设置单元格的innerHTML时,DOM将变脏,并且更改将在下一个渲染线程循环中呈现,这将在您的JavaScript线程变为空闲状态时发生。但是,您仍然有待执行的操作2和3,因此将首先执行它们,然后在javascript线程变为空闲时,您的渲染线程将占据主导地位并更新屏幕。
我希望您现在对javascript的工作方式有一个清晰的认识。
现在,要解决您的问题,您可以在显示警报之前设置次超时,以便在显示警报之前更新页面。
答案 1 :(得分:0)
点击发生后,requestAnimationFrame
侦听器正在同步运行 ,并且alert
阻止了浏览器 -它阻止了进一步的Javascript和从重新渲染开始直到警报被消除为止。该功能运行时,浏览器还没有时间重新绘制。
您可以使用x
来确保 window.requestAnimationFrame(() => {
setTimeout(() => {
alert('game over');
});
});
仅在之后显示,浏览器完成了重新渲染以显示新的const winCombos = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[6, 4, 2]
];
let playerTurn = 'X';
for (let i = 0; i < 9; i++) {
const cell = document.getElementById('c' + i);
cell.addEventListener('click', startGame);
function startGame() {
cell.innerHTML = playerTurn;
if (checkForWin()) {
window.requestAnimationFrame(() => {
setTimeout(() => {
alert('game over');
});
});
}
}
}
function checkForWin() {
for (let i = 0; i < winCombos.length; i++) {
const c0 = document.getElementById('c' + winCombos[i][0]);
const c1 = document.getElementById('c' + winCombos[i][1]);
const c2 = document.getElementById('c' + winCombos[i][2]);
if (c0.innerHTML === playerTurn &&
c1.innerHTML === playerTurn &&
c2.innerHTML === playerTurn) {
return true;
} else {
return false;
}
}
}
:>
td {
border: 2px solid #333;
height: 100px;
width: 100px;
text-align: center;
vertical-align: middle;
font-family: "Comic Sans MS", cursive, sans-serif;
font-size: 70px;
cursor: pointer;
}
table {
border-collapse: collapse;
position: absolute;
left: 50%;
margin-left: -155px;
top: 220px;
}
table tr:first-child td {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child {
border-left: 0;
}
table tr td:last-child {
border-right: 0;
}
.endgame {
display: none;
width: 200px;
top: 120px;
background-color: red;
position: absolute;
left: 50%;
margin-left: -100px;
padding-top: 50px;
padding-bottom: 50px;
text-align: center;
border-radius: 5px;
color: white;
font-size: 2em;
}
<!DOCTYPE html>
<html>
<head>
<title>tic tac toe</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<table>
<tr>
<td class="cell" id="c0"></td>
<td class="cell" id="c1"></td>
<td class="cell" id="c2"></td>
</tr>
<tr>
<td class="cell" id="c3"></td>
<td class="cell" id="c4"></td>
<td class="cell" id="c5"></td>
</tr>
<tr>
<td class="cell" id="c6"></td>
<td class="cell" id="c7"></td>
<td class="cell" id="c8"></td>
</tr>
<div class="endgame">
<div class="text">Cant see this text</div>
</div>
</table>
<script type="text/javascript" src="script2.js"></script>
</body>
</html>
alert
for
或者,甚至更好的是,使用适当的模态。 checkForWin
和相关的阻止功能非常不友好。
还请注意,将函数声明悬挂在其包含函数(或顶层)的顶部(或顶层)–不应位于const winCombos = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[6, 4, 2]
];
function startGame() {
cell.innerHTML = playerTurn;
if (checkForWin()) {
document.querySelector('.endgame').style.display = 'block';
}
}
let playerTurn = 'X';
for (let i = 0; i < 9; i++) {
const cell = document.getElementById('c' + i);
cell.addEventListener('click', startGame);
}
const checkForWin = () => winCombos.some((combo) => (
combo.map(i => document.getElementById('c' + i))
.every(cell => cell.textContent === playerTurn)
))
块内。
如果您改为使用数组方法,还可以将td {
border: 2px solid #333;
height: 100px;
width: 100px;
text-align: center;
vertical-align: middle;
font-family: "Comic Sans MS", cursive, sans-serif;
font-size: 70px;
cursor: pointer;
}
table {
border-collapse: collapse;
position: absolute;
left: 50%;
margin-left: -155px;
top: 220px;
}
table tr:first-child td {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child {
border-left: 0;
}
table tr td:last-child {
border-right: 0;
}
.endgame {
display: none;
width: 200px;
top: 120px;
background-color: red;
position: absolute;
left: 50%;
margin-left: -100px;
padding-top: 50px;
padding-bottom: 50px;
text-align: center;
border-radius: 5px;
color: white;
font-size: 2em;
}
函数减少到三行:
<table>
<tr>
<td class="cell" id="c0"></td>
<td class="cell" id="c1"></td>
<td class="cell" id="c2"></td>
</tr>
<tr>
<td class="cell" id="c3"></td>
<td class="cell" id="c4"></td>
<td class="cell" id="c5"></td>
</tr>
<tr>
<td class="cell" id="c6"></td>
<td class="cell" id="c7"></td>
<td class="cell" id="c8"></td>
</tr>
<div class="endgame">
<div class="text">Game is over</div>
</div>
</table>
for
void DisplayDirectoryContents()
{
// Get files and folders from directory
list<File> files = this->getFiles();
// Iterate over each item in the list.
// Use a reference to avoid copying of the items.
for ( File& file : files )
{
cout << file.getFileName();
}
}