JavaScript/练习/井字棋
外观
< JavaScript | 练习
井字棋
井字棋 是一款两人游戏。他们选择 3 x 3 棋盘中的方格。
首先,我们需要一个 HTML 文件加上 CSS 来实现用户界面。它应该包含:
- 一个标题
- 一个包含九个按钮的容器,以 3 x 3 棋盘的形式排列
- 两个按钮“开始 X”和一个按钮“开始 O”,以决定哪位玩家先开始
- 一个“重置”按钮
- 一个文本字段,用于向用户反馈游戏的当前状态
HTML 代码可能如下所示
点击查看解决方案
<!DOCTYPE html>
<html>
<head>
<title>TicTacToe</title>
<script>
// ...
</script>
<style>
.container {
display: grid;
grid-template-columns: 32% 32% 32%;
grid-template-rows: 6em 6em 6em;
gap: 1%;
background-color: aliceblue;
margin: 2em;
padding: 2em;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
}
.button {
height:2.4em;
width: 2.4em;
font-size: 2em;
background-color: aqua;
}
.containerCmd {
display: flex;
justify-content: flex-end;
}
.buttonCmd {
padding: 0.6em 2em 0.6em 2em;
font-size: 1em;
margin-right: 2em;
}
.feedback {
padding: 0.8em 1em 0.8em 1em;
margin: 1em;
font-size: 1.4em;
background-color: green;
}
</style>
</head>
<body>
<h1 style="text-align: center;">TicTacToe</h1>
<!-- The container with the nine clickable buttons -->
<div class="container">
<div class="cell"><button id="b1" class="button" disabled /></div>
<div class="cell"><button id="b2" class="button" disabled /></div>
<div class="cell"><button id="b3" class="button" disabled /></div>
<div class="cell"><button id="b4" class="button" disabled /></div>
<div class="cell"><button id="b5" class="button" disabled /></div>
<div class="cell"><button id="b6" class="button" disabled /></div>
<div class="cell"><button id="b7" class="button" disabled /></div>
<div class="cell"><button id="b8" class="button" disabled /></div>
<div class="cell"><button id="b9" class="button" disabled /></div>
</div>
<!-- buttons for start and reset the game -->
<div class="containerCmd">
<button class="buttonCmd" id="startX">Start: X</button>
<button class="buttonCmd" id="startO">Start: O</button>
<p style="padding-right:3em"></p> <!-- a small spacer -->
<button class="buttonCmd">Reset</button>
</div>
<!-- feedback from the script to the players -->
<p id="feedback" class="feedback">Click to one of the 'Start' buttons</p>
</body>
</html>
接下来,通过向按钮添加事件和在脚本元素中添加函数,来开发应用程序的逻辑。
- 当游戏开始或重置时,九个 X/O 按钮和反馈区域必须被清空。
- 九个 X/O 按钮调用同一个事件处理程序会很有帮助。
event.target.id
提供了按钮的 ID,通过document.getElementById(event.target.id)
可以访问该按钮。 - 每当点击九个 X/O 按钮中的一个时,必须阻止该按钮被再次点击
elem.disabled = true
。 - 我们需要一个函数来判断一行、一列或一条对角线(共 8 种可能)是否包含 3 个 'X' 或 3 个 'O'。
- 考虑没有人获胜的情况。
总的来说,应用程序可能看起来像这样
点击查看解决方案
<!DOCTYPE html>
<html>
<head>
<title>TicTacToe</title>
<script>
"use strict";
// global variable for X/O
let user = "";
// -------- start: decide which user has the first click ----------------
function startXO(userXO) {
if (userXO === "X") {
user = "X";
} else {
user = "O";
}
// disable / enable certain buttons
document.getElementById("startX").disabled = true;
document.getElementById("startO").disabled = true;
["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9"]
.forEach((button) => {
document.getElementById(button).disabled = false;
});
document.getElementById("feedback").innerHTML = "";
}
// -------- regular action ----------------------------------------------
function buttonClicked(event) {
const elem = document.getElementById(event.target.id);
elem.innerHTML = user;
elem.disabled = true;
// check for end of game
switch (isFinished()) {
case "tie":
document.getElementById("feedback").innerHTML = "No winner. Tie.";
["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9"]
.forEach((button) => {
document.getElementById(button).disabled = true;
});
break;
case true:
document.getElementById("feedback").innerHTML = "The winner is: " + user;
["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9"]
.forEach((button) => {
document.getElementById(button).disabled = true;
});
break;
default:
// toggle user and go on
if (user === "X") {
user = "O";
} else {
user = "X";
}
}
}
// -------- check for end of game ----------------------
function isFinished() {
const xo_b1 = document.getElementById("b1").innerHTML;
const xo_b2 = document.getElementById("b2").innerHTML;
const xo_b3 = document.getElementById("b3").innerHTML;
const xo_b4 = document.getElementById("b4").innerHTML;
const xo_b5 = document.getElementById("b5").innerHTML;
const xo_b6 = document.getElementById("b6").innerHTML;
const xo_b7 = document.getElementById("b7").innerHTML;
const xo_b8 = document.getElementById("b8").innerHTML;
const xo_b9 = document.getElementById("b9").innerHTML;
// check for 'tie' in a loop over all buttons
let tmp = 0;
[xo_b1, xo_b2, xo_b3, xo_b4, xo_b5, xo_b6, xo_b7, xo_b8, xo_b9]
.forEach((elem) => {if (elem !== "") tmp++});
if (tmp === 9) {
return "tie";
}
// check for winner
if ( // horizontal
(xo_b1 === user && xo_b2 === user && xo_b3 === user) ||
(xo_b4 === user && xo_b5 === user && xo_b6 === user) ||
(xo_b7 === user && xo_b8 === user && xo_b9 === user) ||
// vertical
(xo_b1 === user && xo_b4 === user && xo_b7 === user) ||
(xo_b2 === user && xo_b5 === user && xo_b8 === user) ||
(xo_b3 === user && xo_b6 === user && xo_b9 === user) ||
// diagonal
(xo_b1 === user && xo_b5 === user && xo_b9 === user) ||
(xo_b3 === user && xo_b5 === user && xo_b7 === user)
)
{
return true;
} else {
return false;
}
}
// -------- reset game -------------------------------------
function reset() {
// disable / enable certain buttons
["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9"]
.forEach((button) => {
document.getElementById(button).innerHTML = "";
document.getElementById(button).disabled = true;
});
document.getElementById("feedback").innerHTML = "Click to 'Start'";
document.getElementById("startX").disabled = false;
document.getElementById("startO").disabled = false;
}
</script>
<style>
.container {
display: grid;
grid-template-columns: 32% 32% 32%;
grid-template-rows: 6em 6em 6em;
gap: 1%;
background-color: aliceblue;
margin: 2em;
padding: 2em;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
}
.button {
height:2.4em;
width: 2.4em;
font-size: 2em;
background-color: aqua;
}
.containerCmd {
display: flex;
justify-content: flex-end;
}
.buttonCmd {
padding: 0.6em 2em 0.6em 2em;
font-size: 1em;
margin-right: 2em;
}
.feedback {
padding: 0.8em 1em 0.8em 1em;
margin: 1em;
font-size: 1.4em;
background-color: green;
}
</style>
</head>
<body>
<h1 style="text-align: center;">TicTacToe</h1>
<!-- The container with the nine clickable buttons -->
<div class="container">
<div class="cell"><button id="b1" class="button" onclick="buttonClicked(event)" disabled /></div>
<div class="cell"><button id="b2" class="button" onclick="buttonClicked(event)" disabled /></div>
<div class="cell"><button id="b3" class="button" onclick="buttonClicked(event)" disabled /></div>
<div class="cell"><button id="b4" class="button" onclick="buttonClicked(event)" disabled /></div>
<div class="cell"><button id="b5" class="button" onclick="buttonClicked(event)" disabled /></div>
<div class="cell"><button id="b6" class="button" onclick="buttonClicked(event)" disabled /></div>
<div class="cell"><button id="b7" class="button" onclick="buttonClicked(event)" disabled /></div>
<div class="cell"><button id="b8" class="button" onclick="buttonClicked(event)" disabled /></div>
<div class="cell"><button id="b9" class="button" onclick="buttonClicked(event)" disabled /></div>
</div>
<!-- buttons for start and reset the game -->
<div class="containerCmd">
<button class="buttonCmd" id="startX" onClick="startXO('X')">Start: X</button>
<button class="buttonCmd" id="startO" onClick="startXO('O')">Start: O</button>
<p style="padding-right:3em"></p> <!-- a small spacer -->
<button class="buttonCmd" onClick="reset()">Reset</button>
</div>
<!-- feedback from the script to the players -->
<p id="feedback" class="feedback">Click to one of the 'Start' buttons</p>
</body>
</html>