11.11 脚本网页 跳棋

难点一,如何绘制棋盘,绘制棋盘算法还是社会工程 (本文选择查表) 已实现 ✔

难点二,后端跳棋人工智能算法,这里只提供了,前端js简单交互逻辑 未实现

下面是,只需一个页面就可以交互的跳棋。

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<title>六角星跳棋</title>

<style>

/* 样式部分保持不变 */

* {

margin: 0;

padding: 0;

box-sizing: border-box;

}

body {

font-family: 'Arial', sans-serif;

background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

min-height: 100vh;

display: flex;

flex-direction: column;

align-items: center;

padding: 10px;

overflow-x: hidden;

}

.game-container {

width: 100%;

max-width: 700px;

background: rgba(255, 255, 255, 0.95);

border-radius: 20px;

box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);

padding: 20px;

margin-top: 20px;

}

.game-header {

text-align: center;

margin-bottom: 20px;

}

h1 {

color: #333;

font-size: 2rem;

margin-bottom: 10px;

}

.game-info {

display: flex;

justify-content: space-around;

align-items: center;

margin-bottom: 15px;

padding: 10px;

background: #f8f9fa;

border-radius: 10px;

flex-wrap: wrap;

}

.player-info {

display: flex;

align-items: center;

gap: 8px;

margin: 5px;

}

.player-indicator {

width: 24px;

height: 24px;

border-radius: 50%;

border: 2px solid #333;

transition: all 0.3s ease;

}

.current-player {

transform: scale(1.3);

box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);

}

.board-container {

position: relative;

width: 100%;

height: 520px;

max-width: 600px;

margin: 0 auto;

background: #f5f5dc;

border-radius: 15px;

box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.2);

overflow: hidden;

}

.board {

position: relative;

width: 100%;

height: 100%;

}

.position {

position: absolute;

width: 20px;

height: 20px;

border-radius: 50%;

background: #e0d5c7;

border: 1px solid #999;

cursor: pointer;

transition: all 0.3s ease;

z-index: 1;

}

.position:hover {

background: #d4c4b0;

transform: scale(1.1);

}

.position.valid-move {

background: #90EE90;

animation: pulse 1s infinite;

box-shadow: 0 0 10px rgba(0, 255, 0, 0.5);

}

@keyframes pulse {

0% { transform: scale(1); }

50% { transform: scale(1.15); }

100% { transform: scale(1); }

}

.chess {

position: absolute;

width: 18px;

height: 18px;

border-radius: 50%;

cursor: pointer;

transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);

z-index: 10;

box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);

}

.chess:hover {

transform: scale(1.1);

box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);

}

.chess.selected {

transform: scale(1.2);

box-shadow: 0 0 15px rgba(255, 215, 0, 0.8);

z-index: 20;

}

.chess.moving {

z-index: 30;

transition: all 0.6s ease-in-out;

}

.controls {

display: flex;

justify-content: center;

gap: 15px;

margin-top: 20px;

}

.btn {

padding: 12px 25px;

font-size: 1rem;

font-weight: bold;

border: none;

border-radius: 25px;

cursor: pointer;

transition: all 0.3s ease;

box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);

}

.btn-primary {

background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

color: white;

}

.btn-primary:hover {

transform: translateY(-2px);

box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2);

}

.btn-secondary {

background: #6c757d;

color: white;

}

.btn-secondary:hover {

background: #5a6268;

}

.message {

text-align: center;

margin-top: 15px;

padding: 10px;

border-radius: 10px;

font-weight: bold;

min-height: 40px;

display: flex;

align-items: center;

justify-content: center;

background: #e9ecef;

color: #495057;

}

.winner-message {

background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);

color: white;

animation: celebrate 1s ease-in-out;

}

@keyframes celebrate {

0%, 100% { transform: scale(1); }

50% { transform: scale(1.05); }

}

.ai-thinking {

display: inline-block;

margin-left: 10px;

}

.ai-thinking span {

display: inline-block;

width: 6px;

height: 6px;

border-radius: 50%;

background: #667eea;

margin: 0 2px;

animation: thinking 1.4s infinite ease-in-out both;

}

.ai-thinking span:nth-child(1) { animation-delay: -0.32s; }

.ai-thinking span:nth-child(2) { animation-delay: -0.16s; }

@keyframes thinking {

0%, 80%, 100% {

transform: scale(0);

opacity: 0.5;

}

40% {

transform: scale(1);

opacity: 1;

}

}

@media (max-width: 600px) {

.board-container {

height: 400px;

max-width: 450px;

}

.position {

width: 16px;

height: 16px;

}

.chess {

width: 14px;

height: 14px;

}

h1 {

font-size: 1.5rem;

}

.btn {

padding: 10px 20px;

font-size: 0.9rem;

}

}

</style>

</head>

<body>

<div class="game-container">

<div class="game-header">

< 一、游戏界面 >

<h1>🎯 六角星跳棋</h1>

</div>

<div class="game-info">

<div class="player-info">

<div class="player-indicator" id="player1-indicator"></div>

<span>玩家</span>

</div>

<div class="player-info">

<div class="player-indicator" id="player2-indicator"></div>

<span>AI 1</span>

</div>

<div class="player-info">

<div class="player-indicator" id="player3-indicator"></div>

<span>AI 2</span>

</div>

</div>

<div class="board-container">

<div class="board" id="board"></div>

</div>

<div class="controls">

<button class="btn btn-primary" id="startBtn">开始游戏</button>

<button class="btn btn-secondary" id="resetBtn">重置</button>

</div>

<div class="message" id="message">点击"开始游戏"开始对战</div>

</div>

<script>

// 二、游戏主类定义

class ChineseCheckersGame {

constructor() {

// 1. 棋盘参数设置

this.width = 300;

this.height = this.width * Math.sqrt(3);

this.rotateY = Math.round((this.width * 2 * 2 / 3) * Math.sqrt(3) / 2);

this.radius = this.width * 2 / (12 + 12 * 0.4) / 2;

this.gap = 2 * 0.4 * this.radius;

// 2. 玩家设置

this.playerColors = ['pink', 'orange', 'brown']; // 使用3个颜色

this.setTargets = {

pink: { targetColor: 'orange', targetArray: [] },

orange: { targetColor: 'brown', targetArray: [] },

brown: { targetColor: 'pink', targetArray: [] }

};

// 3. 玩家信息

this.players = [

{ id: 1, name: '玩家', color: 'pink', isAI: false, pieces: [] },

{ id: 2, name: 'AI 1', color: 'orange', isAI: true, pieces: [] },

{ id: 3, name: 'AI 2', color: 'brown', isAI: true, pieces: [] }

];

// 4. 游戏状态变量

this.currentPlayerIndex = 0;

this.selectedPiece = null;

this.validMoves = [];

this.gameActive = false;

this.moveInProgress = false;

this.position = [];

// 5. 初始化棋盘和事件监听

this.initBoard();

this.setupEventListeners();

}

// 三、棋盘初始化

initBoard() {

const board = document.getElementById('board');

board.innerHTML = '';

this.position = [];

// 1. 生成三角形区域的棋子和棋盘位置

for (let k = 0; k < 6; k++) {

for (let i = 0; i < 4; i++) {

for (let j = 0; j < i + 1; j++) {

// 1.1 只在前3个角生成棋子

if (k < 3) {

const chessPos = {

key: `tri-{k}-{i}-${j}`,

isChess: true,

locate: '',

style: {

background: this.playerColors[k],

left: Math.round(Math.cos(k * 60 * 2 * Math.PI / 360) * (this.width - this.width * 2 / (4 * 3 * 2) * i + j * this.width * 2 / (4 * 3) - this.width) - Math.sin(k * 60 * 2 * Math.PI / 360) * ((i * this.gap + 2 * this.radius * i) * Math.sqrt(3) / 2 - this.rotateY) + this.width),

top: Math.round(Math.sin(k * 60 * 2 * Math.PI / 360) * (this.width - this.width * 2 / (4 * 3 * 2) * i + j * this.width * 2 / (4 * 3) - this.width) + Math.cos(k * 60 * 2 * Math.PI / 360) * ((i * this.gap + 2 * this.radius * i) * Math.sqrt(3) / 2 - this.rotateY) + this.rotateY),

zIndex: 2

}

};

this.position.push(chessPos);

}

// 1.2 所有6个角都生成棋盘位置

const boardPos = {

key: `board-tri-{k}-{i}-${j}`,

isChess: false,

style: {

left: Math.round(Math.cos(k * 60 * 2 * Math.PI / 360) * (this.width - this.width * 2 / (4 * 3 * 2) * i + j * this.width * 2 / (4 * 3) - this.width) - Math.sin(k * 60 * 2 * Math.PI / 360) * ((i * this.gap + 2 * this.radius * i) * Math.sqrt(3) / 2 - this.rotateY) + this.width),

top: Math.round(Math.sin(k * 60 * 2 * Math.PI / 360) * (this.width - this.width * 2 / (4 * 3 * 2) * i + j * this.width * 2 / (4 * 3) - this.width) + Math.cos(k * 60 * 2 * Math.PI / 360) * ((i * this.gap + 2 * this.radius * i) * Math.sqrt(3) / 2 - this.rotateY) + this.rotateY),

zIndex: 1

}

};

this.position.push(boardPos);

}

}

}

// 2. 生成六边形上半边棋盘位置

for (let i = 0; i < 5; i++) {

for (let j = 0; j < i + 5; j++) {

const hexPos = {

key: `hex-up-{i}-{j}`,

isChess: false,

style: {

left: Math.round(2 * this.width / 3 - this.width * 2 / (4 * 3 * 2) * i + (this.gap + 2 * this.radius) * j),

top: Math.round(this.rotateY / 2 + this.width * 2 / (4 * 3) * Math.sqrt(3) / 2 * i),

zIndex: 1

}

};

this.position.push(hexPos);

}

}

// 3. 生成六边形下半边棋盘位置

for (let i = 5; i < 9; i++) {

for (let j = 0; j < 13 - i; j++) {

const hexPos = {

key: `hex-down-{i}-{j}`,

isChess: false,

style: {

left: Math.round(2 * this.width / 3 - this.width * 2 / (4 * 3 * 2) * 3 + this.width * 2 / (4 * 3 * 2) * (i - 5) + (this.gap + 2 * this.radius) * j),

top: Math.round(this.rotateY * 3 / 2 - this.width * 2 / (4 * 3) * Math.sqrt(3) / 2 * 3 + this.width * 2 / (4 * 3) * Math.sqrt(3) / 2 * (i - 5)),

zIndex: 1

}

};

this.position.push(hexPos);

}

}

// 4. 处理棋盘位置数据

this.position = this.sort(this.position);

this.setTarget(this.position);

this.position = this.isOccupy(this.position);

// 5. 渲染棋盘

this.renderBoard();

}

// 四、棋盘位置排序

sort(position) {

// 1. 按y坐标排序

position = position.sort((arg1, arg2) => {

return arg1.style.top > arg2.style.top ? 1 : -1;

});

// 2. 设置位置标记

position = this.setMark('left', position);

// 3. 计算每个位置的唯一坐标标识

position = position.map((item, index) => {

let { left, top } = item.style;

let length = (Math.sqrt(3) * left + top - this.rotateY / 2) / 2;

let unit = 2 * this.width / 12 * Math.sqrt(3) / 2;

let num = Math.round((length / unit).toFixed(2)) + 1;

item.locate += `${num}-`;

length = (Math.sqrt(3) * left - top + 2 * this.rotateY * 3 / 4) / 2;

num = Math.round((length / unit).toFixed(2)) + 1;

item.locate += `${num}`;

return item;

});

return position;

}

// 五、设置位置标记

setMark(prop, arr) {

let lastTop = arr[0].style[prop], y = 0;

let sortArr = arr.map((item, index) => {

let { top } = item.style;

item.locate = item.locate || '';

if (top != lastTop) {

y++;

item.locate += `${y}-`;

} else {

item.locate += `${y}-`;

}

lastTop = top;

return item;

});

return sortArr;

}

// 六、设置目标区域

setTarget(position) {

position.map((item, index) => {

if (item.isChess) {

let color = item.style.background;

if (this.setTargets[color]) {

let targetColor = this.setTargets[color]['targetColor'];

this.setTargets[targetColor].targetArray.push(JSON.parse(JSON.stringify(item)));

}

}

});

}

// 七、判断位置是否被占用

isOccupy(position) {

let boards = position.filter((item) => {

return !item.isChess;

});

let chesses = position.filter((item) => {

return item.isChess;

});

boards = boards.map(item => {

let isOccupy = chesses.filter((chess) => {

return chess.locate === item.locate;

});

isOccupy.length > 0 ? item.isOccupy = true : item.isOccupy = false;

return item;

});

return boards.concat(chesses);

}

// 八、渲染棋盘

renderBoard() {

const board = document.getElementById('board');

board.innerHTML = '';

// 1. 计算缩放比例和偏移量

const scale = Math.min(board.offsetWidth / (this.width * 2), board.offsetHeight / (this.rotateY * 2));

const offsetX = (board.offsetWidth - this.width * 2 * scale) / 2;

const offsetY = (board.offsetHeight - this.rotateY * 2 * scale) / 2;

// 2. 渲染每个位置

this.position.forEach(item => {

if (item.isChess) {

// 2.1 渲染棋子

const chess = document.createElement('div');

chess.className = 'chess';

chess.key = item.key;

chess.style.left = (item.style.left * scale + offsetX - 9) + 'px';

chess.style.top = (item.style.top * scale + offsetY - 9) + 'px';

chess.style.background = item.style.background;

chess.dataset.locate = item.locate;

chess.dataset.key = item.key;

chess.addEventListener('click', () => this.handleChessClick(item));

board.appendChild(chess);

} else {

// 2.2 渲染棋盘位置

const pos = document.createElement('div');

pos.className = 'position';

pos.key = item.key;

pos.style.left = (item.style.left * scale + offsetX - 10) + 'px';

pos.style.top = (item.style.top * scale + offsetY - 10) + 'px';

pos.dataset.locate = item.locate;

pos.dataset.key = item.key;

pos.addEventListener('click', () => this.handlePositionClick(item));

board.appendChild(pos);

}

});

}

// 九、棋子点击处理

handleChessClick(item) {

if (!this.gameActive || this.moveInProgress) return;

const currentPlayer = this.players[this.currentPlayerIndex];

if (item.style.background !== currentPlayer.color) {

this.showMessage(`请${currentPlayer.name}走!`);

return;

}

this.clearSelection();

this.selectedPiece = item;

// 1. 高亮选中的棋子

const chessElement = document.querySelector(`.chess[data-key="${item.key}"]`);

if (chessElement) {

chessElement.classList.add('selected');

}

// 2. 计算有效移动

this.calculateValidMoves(item);

}

// 十、棋盘位置点击处理

handlePositionClick(item) {

if (!this.gameActive || this.moveInProgress || !this.selectedPiece) return;

const isValidMove = this.validMoves.some(move => move.locate === item.locate);

if (isValidMove) {

this.moveChess(this.selectedPiece, item);

}

}

// 十一、计算有效移动

calculateValidMoves(itemMove) {

let path = [];

let { locate } = itemMove;

let axises = locate.split('-');

let allPath = [];

let passNode = [];

// 1. 获取相邻的空位

let aroundPathLocate = [

`{axises\[0\] \* 1}-{axises[1] * 1 - 1}-${axises[2] * 1 - 1}`,

`{axises\[0\] \* 1}-{axises[1] * 1 + 1}-${axises[2] * 1 + 1}`,

`{axises\[0\] \* 1 - 1}-{axises[1] * 1}-${axises[2] * 1 + 1}`,

`{axises\[0\] \* 1 + 1}-{axises[1] * 1}-${axises[2] * 1 - 1}`,

`{axises\[0\] \* 1 - 1}-{axises[1] * 1 - 1}-${axises[2] * 1}`,

`{axises\[0\] \* 1 + 1}-{axises[1] * 1 + 1}-${axises[2] * 1}`

];

this.position.forEach(item => {

if (!item.isChess && !item.isOccupy) {

if (aroundPathLocate.indexOf(item.locate) > -1) {

item['parent'] = [itemMove.locate];

path.push(item);

}

}

});

// 2. 计算跳跃路径

this.getValidPoint(itemMove, this.position, allPath, passNode);

path = path.concat(passNode);

// 3. 去重

path = this.uniqPath(path);

this.validMoves = path;

// 4. 高亮有效移动位置

path.forEach(move => {

const posElement = document.querySelector(`.position[data-locate="${move.locate}"]`);

if (posElement) {

posElement.classList.add('valid-move');

}

});

}

// 十二、获取有效跳跃点

getValidPoint(itemMove, position, allPath, passNode) {

let path = [];

let { locate } = itemMove;

let axises = locate.split('-');

let nextJump = null;

let arrs = [[], [], []];

// 1. 按坐标轴分组

position.forEach(item => {

if (!item.isChess && item.locate != itemMove.locate) {

let { locate } = item;

let itemAxises = locate.split('-');

if (itemAxises[0] == axises[0]) {

arrs[0].push(item);

} else if (itemAxises[1] == axises[1]) {

arrs[1].push(item);

} else if (itemAxises[2] == axises[2]) {

arrs[2].push(item);

}

}

});

// 2. 排序并查找跳跃点

arrs = arrs.map((arr) => {

arr.push(itemMove);

arr = arr.sort((arg1, arg2) => {

return arg1.locate.split('-').slice(0, 2).join('') * 1 > arg2.locate.split('-').slice(0, 2).join('') * 1 ? 1 : -1;

});

return arr;

});

// 3. 查找跳跃路径

arrs.forEach((arr, index) => {

let pos = -1;

arr.filter((item, i) => {

return item.locate == itemMove.locate && (pos = i);

});

let left = pos - 1, right = pos + 1;

// 3.1 向左查找

for (; left >= 0;) {

if (arr[left].isOccupy) {

let flag = false;

let end = left * 2 - pos;

if (end < 0 || end >= arr.length) {

break;

}

for (let start = left + (end - left) / Math.abs(end - left);

start >= Math.min(left, end) && start <= Math.max(left, end);

start = start + (end - left) / Math.abs(end - left)) {

if (arr[start].isOccupy) {

flag = true;

break;

}

}

if (!flag) {

path.push(arr[end]);

}

flag = false;

break;

} else {

left--;

}

}

// 3.2 向右查找

for (; right < arr.length;) {

if (arr[right].isOccupy) {

let flag = false;

let end = right * 2 - pos;

if (end < 0 || end >= arr.length) {

break;

}

for (let start = right + (end - right) / Math.abs(end - right);

start >= Math.min(right, end) && start <= Math.max(right, end);

start = start + (end - right) / Math.abs(end - right)) {

if (arr[start].isOccupy) {

flag = true;

break;

}

}

if (!flag) {

path.push(arr[end]);

}

flag = false;

break;

} else {

right++;

}

}

});

// 4. 记录路径

path.forEach(node => {

if (!node['parent']) {

node['parent'] = [];

}

node['parent'].push(itemMove.locate);

});

allPath.push(...path);

// 5. 递归查找更多跳跃点

if (allPath.length >= 1) {

nextJump = allPath[0];

passNode.push(nextJump);

allPath.splice(0, 1);

return nextJump ? this.getValidPoint(nextJump, position, allPath, passNode) : passNode;

}

return passNode;

}

// 十三、路径去重

uniqPath(path) {

let newPath = [];

if (path.length > 0) {

path.forEach(pathNode => {

let index;

let tempoPath = newPath.filter((keyPathNode, i) => {

if (pathNode.key === keyPathNode.key) {

index = i;

return true;

} else {

return false;

}

});

if (tempoPath.length === 0) {

if (!pathNode['parent']) pathNode['parent'] = [];

newPath.push(pathNode);

} else {

let firstPathNode = JSON.parse(JSON.stringify(newPath[index]));

for (let i = 0; i < tempoPath.length; i++) {

firstPathNode['parent'] = firstPathNode['parent'].concat(tempoPath[i]['parent']);

firstPathNode['parent'] = [...new Set(firstPathNode['parent'])];

}

newPath[index] = firstPathNode;

}

});

}

return newPath;

}

// 十四、移动棋子

moveChess(fromItem, toItem) {

if (this.moveInProgress) return;

this.moveInProgress = true;

const fromElement = document.querySelector(`.chess[data-key="${fromItem.key}"]`);

const toPosition = document.querySelector(`.position[data-locate="${toItem.locate}"]`);

if (!fromElement || !toPosition) return;

// 1. 更新位置数据

fromItem.locate = toItem.locate;

// 2. 动画移动棋子

fromElement.classList.add('moving');

fromElement.style.left = (parseInt(toPosition.style.left) + 1) + 'px';

fromElement.style.top = (parseInt(toPosition.style.top) + 1) + 'px';

fromElement.dataset.locate = toItem.locate;

// 3. 移动完成后的处理

setTimeout(() => {

fromElement.classList.remove('moving');

this.clearSelection();

this.moveInProgress = false;

// 3.1 更新占用状态

this.position = this.isOccupy(this.position);

// 3.2 检查胜利

if (this.checkWin(fromItem.style.background)) {

this.endGame(fromItem.style.background);

return;

}

// 3.3 切换玩家

this.nextTurn();

}, 600);

}

// 十五、检查胜利条件

checkWin(color) {

let target = this.setTargets[color];

if (!target) return false;

let colorChess = this.position.filter(item => {

return item.style.background === color;

});

let targetArray = target['targetArray'];

let count = 0;

// 1. 统计在目标区域的棋子数量

targetArray.forEach(item => {

let { locate } = item;

colorChess.forEach(chess => {

if (locate === chess.locate) {

count++;

}

});

});

// 2. 全部棋子到达目标区域则获胜

return count === targetArray.length;

}

// 十六、切换回合

nextTurn() {

this.currentPlayerIndex = (this.currentPlayerIndex + 1) % this.players.length;

this.updatePlayerIndicators();

const currentPlayer = this.players[this.currentPlayerIndex];

this.showMessage(`${currentPlayer.name}的回合`);

// 1. AI回合处理

if (currentPlayer.isAI) {

this.showAIThinking();

setTimeout(() => this.makeAIMove(), 1500);

}

}

// 十七、AI移动逻辑

makeAIMove() {

const currentPlayer = this.players[this.currentPlayerIndex];

const aiPieces = this.position.filter(item =>

item.isChess && item.style.background === currentPlayer.color

);

let bestMove = null;

let maxMoves = 0;

// 1. 选择能移动最远的棋子

aiPieces.forEach(piece => {

this.calculateValidMoves(piece);

if (this.validMoves.length > maxMoves) {

maxMoves = this.validMoves.length;

bestMove = { piece, moves: [...this.validMoves] };

}

this.clearSelection();

});

// 2. 执行移动

if (bestMove && bestMove.moves.length > 0) {

const targetMove = bestMove.moves[Math.floor(Math.random() * bestMove.moves.length)];

this.selectedPiece = bestMove.piece;

this.moveChess(bestMove.piece, targetMove);

} else {

this.nextTurn();

}

}

// 十八、清除选择状态

clearSelection() {

document.querySelectorAll('.chess.selected').forEach(el => {

el.classList.remove('selected');

});

document.querySelectorAll('.position.valid-move').forEach(el => {

el.classList.remove('valid-move');

});

this.selectedPiece = null;

this.validMoves = [];

}

// 十九、更新玩家指示器

updatePlayerIndicators() {

document.querySelectorAll('.player-indicator').forEach((el, index) => {

if (index < this.players.length) {

if (index === this.currentPlayerIndex) {

el.classList.add('current-player');

} else {

el.classList.remove('current-player');

}

el.style.background = this.players[index].color;

}

});

}

// 二十、显示消息

showMessage(text) {

const messageEl = document.getElementById('message');

messageEl.textContent = text;

messageEl.classList.remove('winner-message');

}

// 二十一、显示AI思考状态

showAIThinking() {

const messageEl = document.getElementById('message');

messageEl.innerHTML = `AI思考中<div class="ai-thinking"><span></span><span></span><span></span></div>`;

}

// 二十二、游戏结束处理

endGame(color) {

this.gameActive = false;

const winner = this.players.find(p => p.color === color);

const messageEl = document.getElementById('message');

messageEl.textContent = `🎉 ${winner.name} 获胜!`;

messageEl.classList.add('winner-message');

}

// 二十三、开始游戏

startGame() {

this.gameActive = true;

this.currentPlayerIndex = 0;

this.initBoard();

this.updatePlayerIndicators();

this.showMessage('游戏开始!你的回合');

}

// 二十四、重置游戏

resetGame() {

this.gameActive = false;

this.currentPlayerIndex = 0;

this.selectedPiece = null;

this.validMoves = [];

this.moveInProgress = false;

this.initBoard();

this.updatePlayerIndicators();

this.showMessage('点击"开始游戏"开始对战');

}

// 二十五、设置事件监听

setup

setupEventListeners() {

document.getElementById('startBtn').addEventListener('click', () => this.startGame());

document.getElementById('resetBtn').addEventListener('click', () => this.resetGame());

}

}

// 二十六、初始化游戏

document.addEventListener('DOMContentLoaded', () => {

new ChineseCheckersGame();

});

</script>

</body>

</html>

相关推荐
拉拉拉拉拉拉拉马2 小时前
HTML 快速入门指南
前端·html
万少2 小时前
记第一次鸿蒙应用上架之旅:一场略带遗憾的旅途
前端·harmonyos
鹏多多2 小时前
H5开发避坑!解决Safari浏览器的video会覆盖z-index:1的绝对定位元素
前端·javascript·vue.js
恋猫de小郭2 小时前
来了解一下,为什么你的 Flutter WebView 在 iOS 26 上有点击问题?
android·前端·flutter
charlie1145141913 小时前
CSS学习笔记5:CSS 盒模型 & Margin 注意事项
前端·css·笔记·学习·教程
CodeSheep3 小时前
稚晖君公司的最新工资和招人标准
前端·后端·程序员
亿元程序员3 小时前
今天我去面试游戏开发,说我回答得不全面...
前端
一只小阿乐3 小时前
vue3封装alert 提示组件 仿element-plus
前端·javascript·vue.js·vue3
IT_陈寒3 小时前
SpringBoot实战避坑指南:我在微服务项目中总结的12条高效开发经验
前端·人工智能·后端