效果展示:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>井字棋游戏</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.game-container {
text-align: center;
width: 400px;
}
.board {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 5px;
margin-bottom: 20px;
}
.cell {
width: 100px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
border: 2px solid #ddd;
font-size: 36px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.cell:hover {
background-color: #f0f0f0;
}
.status {
font-size: 18px;
margin-bottom: 20px;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border: none;
background-color: #007bff;
color: #fff;
border-radius: 5px;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="game-container">
<h1>井字棋游戏</h1>
<div class="status">
<span id="gameStatus">玩家 X 的回合</span>
</div>
<div class="board" id="board">
<!-- 9个格子 -->
<div class="cell" data-index="0"></div>
<div class="cell" data-index="1"></div>
<div class="cell" data-index="2"></div>
<div class="cell" data-index="3"></div>
<div class="cell" data-index="4"></div>
<div class="cell" data-index="5"></div>
<div class="cell" data-index="6"></div>
<div class="cell" data-index="7"></div>
<div class="cell" data-index="8"></div>
</div>
<button onclick="restartGame()">重新开始</button>
</div>
<script>
const board = document.getElementById("board");
const gameStatus = document.getElementById("gameStatus");
let currentPlayer = "X";
let gameActive = true;
let boardState = ["", "", "", "", "", "", "", "", ""];
const winningCombinations = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
function handleCellClick(event) {
const index = event.target.getAttribute("data-index");
if (boardState[index] !== "" || !gameActive) return;
boardState[index] = currentPlayer;
event.target.textContent = currentPlayer;
if (checkWinner()) {
gameStatus.textContent = `玩家 ${currentPlayer} 胜利!`;
gameActive = false;
} else if (boardState.every(cell => cell !== "")) {
gameStatus.textContent = "平局!";
gameActive = false;
} else {
currentPlayer = currentPlayer === "X" ? "O" : "X";
gameStatus.textContent = `玩家 ${currentPlayer} 的回合`;
}
}
function checkWinner() {
for (let combination of winningCombinations) {
const [a, b, c] = combination;
if (boardState[a] && boardState[a] === boardState[b] && boardState[a] === boardState[c]) {
return true;
}
}
return false;
}
function restartGame() {
boardState = ["", "", "", "", "", "", "", "", ""];
gameActive = true;
currentPlayer = "X";
gameStatus.textContent = `玩家 ${currentPlayer} 的回合`;
const cells = document.querySelectorAll(".cell");
cells.forEach(cell => {
cell.textContent = "";
});
}
board.addEventListener("click", handleCellClick);
</script>
</body>
</html>
井字棋游戏原理与实现
井字棋(Tic-Tac-Toe)是一款经典的两人棋盘游戏,玩家通过轮流在3×3的棋盘上标记自己的符号(通常是“X”和“O”),首先在任意一行、列或对角线上连续放置三个相同符号的玩家获胜。如果所有格子都被填满而没有玩家获胜,则游戏以平局结束。在本文中,我们将介绍如何使用纯HTML和JavaScript来实现一个井字棋小游戏,分析其背后的原理与实现方法。
1. HTML结构
HTML作为网页的基础结构,主要负责界面的布局。在这个井字棋游戏中,我们使用了一个div容器来包含所有的游戏元素,包括棋盘、游戏状态和控制按钮。棋盘本身由一个包含九个子元素的div容器组成,每个子元素代表棋盘上的一个格子。每个格子通过data-index属性来标识其位置,方便后续的事件处理。
除了棋盘,页面上还有一个status区域,用于显示当前的游戏状态,如“玩家 X 的回合”或“玩家 X 胜利”。此外,还有一个“重新开始”按钮,点击后可以重置游戏。
2. CSS样式
为了增强游戏的可视化效果,CSS被用来设置游戏界面的样式。棋盘由一个3×3的网格组成,使用CSS的grid布局实现,每个格子固定大小,并且设置了合适的边框和背景颜色,使得整个棋盘看起来简洁美观。同时,给格子添加了悬停效果,鼠标移到上面时会改变背景颜色,以增加用户的交互体验。
游戏的按钮也有样式,点击时会改变背景颜色,提升了游戏的互动性。
3. JavaScript逻辑
JavaScript作为游戏的核心逻辑部分,负责处理游戏的状态变化和玩家的互动。游戏通过一个名为boardState的数组来跟踪每个格子的状态。数组中的每个元素表示棋盘上的一个格子,X或O表示该格子已经被标记。如果格子为空,数组中的值为空字符串。
- 玩家的轮流: 游戏从玩家“X”开始,每次点击空的格子时,当前玩家的标记会被添加到该格子中,之后轮到另一个玩家。玩家通过切换
currentPlayer来实现轮流。 - 获胜判定: 每次玩家进行一次标记后,系统都会检查当前棋盘状态是否满足某个玩家获胜的条件。通过
winningCombinations数组,保存了所有可能的获胜线(水平、垂直和对角线),在每次玩家标记后,检查这些线是否已被占据。如果某条线的三个格子都被同一玩家标记,则游戏结束,宣布该玩家获胜。 - 平局判定: 如果所有格子都已填满并且没有任何玩家获胜,则游戏判定为平局。
- 重新开始: 游戏提供了一个“重新开始”按钮,点击该按钮时,棋盘状态和显示内容会被重置,游戏重新开始。
4. 代码的实现过程
在代码实现过程中,我们通过添加点击事件监听器来处理玩家的每一次操作。当玩家点击某个格子时,首先判断该格子是否已经被标记,如果没有,则更新格子的状态,并检查游戏的胜负情况。如果没有人获胜且棋盘未满,则交换玩家。
此外,通过检查boardState数组是否完全填满并且没有获胜者,来判断是否发生了平局。一旦游戏结束,用户无法继续进行操作,避免了无意义的点击。
5. 总结
这个井字棋小游戏通过简洁的HTML、CSS和JavaScript实现了游戏的完整功能。HTML负责布局和结构,CSS负责美化界面,而JavaScript处理游戏逻辑和交互。通过简单的数组和事件处理,我们实现了玩家交替操作、获胜判断、平局判断以及游戏重置功能。这个游戏不仅可以作为一个娱乐项目,还能帮助初学者更好地理解前端开发中的DOM操作、事件监听、数组处理和基本的UI设计。