《剖析五子棋游戏代码:从HTML到JavaScript的逻辑构建》
一、整体结构
这个HTML文档构建了一个简单的双人手动PK五子棋游戏。整体结构上,HTML部分定义了页面的基本布局和样式,而JavaScript部分则负责处理游戏的逻辑,如棋盘的创建、棋子的放置、胜负的判断以及游戏的重新开始等功能。
二、HTML部分分析
-
<head>
标签内的设置<title>
标签将页面标题设置为“五子棋游戏”,这是在浏览器标签上显示的标题。- 在
<style>
标签中,定义了页面的样式。body
的背景颜色被设置为#be9416d9
。- 对于表格(
<table>
),设置了border - collapse: collapse
,使表格边框合并。 - 表格中的单元格(
<td>
)被定义了宽度为30px
,高度为30px
,带有2px
的黑色边框,并且文本居中。
-
<body>
标签内的元素- 有一个
<h1>
标签,显示“双人手动PK五子棋”,清晰地表明游戏的类型和模式。 - 定义了玩家1(白棋)和玩家2(黑棋),虽然只是简单的文字标识,但能让玩家清楚各自的角色。
- 有一个
<button>
按钮,其onclick
属性绑定了restartGame()
函数,用于重新开始游戏。 - 最重要的是创建了一个空的
<table>
表格,其id
为“board”,这是后续通过JavaScript创建棋盘的基础。
- 有一个
三、JavaScript部分分析
-
棋盘创建
- 通过
getElementById
获取到<table>
元素,然后使用循环嵌套创建棋盘。 - 外层循环控制行数,内层循环控制列数。对于每一个单元格
<td>
,设置了data - x
和data - y
属性,这可能是为了方便后续获取棋子的坐标位置。并且将创建好的单元格添加到行<tr>
中,行再添加到棋盘表格中。 - 同时,创建了一个二维数组
boardState
来存储棋盘上每个位置的棋子状态,初始值都为0,表示空位置。
- 通过
-
下棋逻辑
- 定义了一个变量
currentPlayer
来标记当前轮到哪个玩家下棋,1代表白棋,2代表黑棋。 placePiece
函数用于处理下棋操作。首先获取点击单元格的坐标,然后判断该位置是否为空(即boardState[y][x]!== 0
),如果不为空则直接返回,不进行下棋操作。- 如果位置为空,则根据当前玩家创建一个圆形的棋子
<div>
元素,设置其颜色(白棋或黑棋)、大小和边距等样式,然后添加到点击的单元格中,并更新boardState
数组中对应位置的值为当前玩家的值。 - 在下完棋后,调用
checkWin
函数来检查当前玩家是否获胜,如果获胜则弹出提示框显示获胜玩家。 - 最后通过
currentPlayer = currentPlayer === 1? 2 : 1
切换玩家。
- 定义了一个变量
-
胜负判断逻辑(
checkWin
函数)- 这个函数从四个方向检查是否有五子连珠。
- 横向检查:通过两层嵌套循环,外层循环遍历每一行,内层循环遍历每一列。当遇到当前玩家的棋子时,计数器
count
加1,如果count
达到5则返回true
表示获胜,否则遇到其他玩家的棋子或者空位置时将count
重置为0。 - 纵向检查:与横向检查类似,只是外层循环控制列数,内层循环控制行数。
- 对角线检查(左上 - 右下):通过一个循环遍历所有可能的对角线,根据对角线的索引
k
计算起始行iStart
和结束行iEnd
,然后在内层循环中获取对应的列j = k - i
,再按照与横向检查类似的逻辑判断是否有五子连珠。 - 对角线检查(右上 - 左下):同样通过循环遍历对角线,计算起始行和结束行,然后获取对应的列
j = size - 1-(k - i)
,进行胜负判断。
-
重新开始游戏(
restartGame
函数)- 这个函数非常简单,直接调用
location.reload()
,这会重新加载整个页面,从而达到重新开始游戏的目的。
- 这个函数非常简单,直接调用
-
添加点击事件
- 通过
querySelectorAll
获取所有的<td>
单元格,然后使用forEach
方法为每个单元格添加点击事件,点击事件绑定到placePiece
函数上,这样玩家点击单元格时就能下棋了。
- 通过
这个五子棋游戏代码虽然简单,但涵盖了HTML和JavaScript在构建交互式游戏方面的基本用法,从页面布局到游戏逻辑的完整实现都有涉及。
完整代码:
<!DOCTYPE html>
<html>
<head>
<title>五子棋游戏</title>
<style>
body {
background-color: #be9416d9;
}
table {
border-collapse: collapse;
}
td {
width: 30px;
height: 30px;
border: 2px solid black;
text-align: center;
}
</style>
</head>
<body>
<h1>双人手动PK五子棋</h1>
玩家1: 白棋
玩家2: 黑棋
<br>
<button onclick="restartGame()">重新开始</button>
<br>
<br>
<table id="board">
</table>
<script>
// 创建棋盘
const board = document.getElementById('board');
const size = 15;
for (let i = 0; i < size; i++) {
const row = document.createElement('tr');
for (let j = 0; j < size; j++) {
const cell = document.createElement('td');
cell.dataset.x = j;
cell.dataset.y = i;
row.appendChild(cell);
}
board.appendChild(row);
}
// 存储棋子状态的数组
const boardState = [];
for (let i = 0; i < size; i++) {
boardState[i] = [];
for (let j = 0; j < size; j++) {
boardState[i][j] = 0;
}
}
// 标记当前轮到哪个玩家下棋,1为白棋,2为黑棋
let currentPlayer = 1;
// 下棋函数
function placePiece(cell) {
const x = parseInt(cell.dataset.x);
const y = parseInt(cell.dataset.y);
if (boardState[y][x] !== 0) {
return;
}
const piece = document.createElement('div');
piece.style.width = '20px';
piece.style.height = '20px';
piece.style.borderRadius = '50%';
piece.style.margin = '5px';
if (currentPlayer === 1) {
piece.style.backgroundColor = 'white';
} else {
piece.style.backgroundColor = 'black';
}
cell.appendChild(piece);
boardState[y][x] = currentPlayer;
if (checkWin(currentPlayer)) {
alert('玩家' + currentPlayer + '获胜!');
}
// 切换玩家
currentPlayer = currentPlayer === 1 ? 2 : 1;
}
// 检查是否获胜
function checkWin(player) {
// 检查横向
for (let i = 0; i < size; i++) {
let count = 0;
for (let j = 0; j < size; j++) {
if (boardState[i][j] === player) {
count++;
if (count === 5) {
return true;
}
} else {
count = 0;
}
}
}
// 检查纵向
for (let j = 0; j < size; j++) {
let count = 0;
for (let i = 0; i < size; i++) {
if (boardState[i][j] === player) {
count++;
if (count === 5) {
return true;
}
} else {
count = 0;
}
}
}
// 检查左上 - 右下对角线
for (let k = 0; k < size * 2 - 1; k++) {
let count = 0;
let iStart = Math.max(0, k - size + 1);
let iEnd = Math.min(size - 1, k);
for (let i = iStart; i <= iEnd; i++) {
let j = k - i;
if (boardState[i][j] === player) {
count++;
if (count === 5) {
return true;
}
} else {
count = 0;
}
}
}
// 检查右上 - 左下对角线
for (let k = 0; k < size * 2 - 1; k++) {
let count = 0;
let iStart = Math.max(0, k - size + 1);
let iEnd = Math.min(size - 1, k);
for (let i = iStart; i <= iEnd; i++) {
let j = size - 1 - (k - i);
if (boardState[i][j] === player) {
count++;
if (count === 5) {
return true;
}
} else {
count = 0;
}
}
}
return false;
}
// 给每个格子添加点击事件
const cells = document.querySelectorAll('td');
cells.forEach(cell => {
cell.addEventListener('click', () => {
placePiece(cell);
});
});
function restartGame() {
location.reload();
}
</script>
</body>
</html>