用html5写一个国际象棋

<!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>

* {

margin: 0;

padding: 0;

box-sizing: border-box;

}

:root {

--primary-dark: #0f172a;

--secondary-dark: #1e293b;

--accent-gold: #f59e0b;

--accent-silver: #94a3b8;

--text-light: #f1f5f9;

--text-gray: #cbd5e1;

--board-light: #f0d9b5;

--board-dark: #8b6914;

}

body {

font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

background: linear-gradient(135deg, var(--primary-dark) 0%, #000 100%);

color: var(--text-light);

min-height: 100vh;

overflow-x: hidden;

}

/* 导航栏 */

header {

padding: 1.5rem 5%;

display: flex;

justify-content: space-between;

align-items: center;

background: rgba(15, 23, 42, 0.9);

backdrop-filter: blur(10px);

position: fixed;

width: 100%;

top: 0;

z-index: 1000;

border-bottom: 1px solid rgba(148, 163, 184, 0.1);

}

.logo {

font-size: 1.5rem;

font-weight: bold;

display: flex;

align-items: center;

gap: 0.5rem;

}

.logo::before {

content: '♔';

font-size: 2rem;

color: var(--accent-gold);

}

nav ul {

display: flex;

list-style: none;

gap: 2rem;

}

nav a {

color: var(--text-gray);

text-decoration: none;

transition: color 0.3s;

font-weight: 500;

}

nav a:hover {

color: var(--accent-gold);

}

/* 主游戏区域 */

.game-section {

margin-top: 80px;

padding: 2rem 5%;

max-width: 1400px;

margin-left: auto;

margin-right: auto;

display: grid;

grid-template-columns: 1fr 2fr 1fr;

gap: 2rem;

align-items: start;

}

/* 左侧控制面板 */

.control-panel {

background: rgba(30, 41, 59, 0.6);

border-radius: 12px;

padding: 1.5rem;

border: 1px solid rgba(148, 163, 184, 0.1);

}

.control-panel h3 {

color: var(--accent-gold);

margin-bottom: 1rem;

font-size: 1.2rem;

}

.game-controls {

display: flex;

flex-direction: column;

gap: 0.75rem;

margin-bottom: 2rem;

}

.btn {

padding: 0.75rem 1rem;

border: none;

border-radius: 6px;

font-size: 1rem;

font-weight: 600;

cursor: pointer;

transition: all 0.3s;

text-decoration: none;

display: inline-block;

text-align: center;

}

.btn-primary {

background: linear-gradient(135deg, var(--accent-gold) 0%, #d97706 100%);

color: var(--primary-dark);

}

.btn-primary:hover {

transform: translateY(-2px);

box-shadow: 0 5px 15px rgba(245, 158, 11, 0.3);

}

.btn-secondary {

background: transparent;

color: var(--accent-silver);

border: 2px solid var(--accent-silver);

}

.btn-secondary:hover {

background: var(--accent-silver);

color: var(--primary-dark);

}

.move-history {

max-height: 300px;

overflow-y: auto;

background: rgba(15, 23, 42, 0.4);

border-radius: 6px;

padding: 1rem;

font-family: 'Courier New', monospace;

font-size: 0.9rem;

}

.move-item {

padding: 0.25rem 0;

color: var(--text-gray);

border-bottom: 1px solid rgba(148, 163, 184, 0.1);

}

.move-item:last-child {

border-bottom: none;

}

/* 中央棋盘 */

.chess-board-container {

background: rgba(30, 41, 59, 0.6);

border-radius: 12px;

padding: 2rem;

border: 1px solid rgba(148, 163, 184, 0.1);

display: flex;

flex-direction: column;

align-items: center;

}

.board-status {

margin-bottom: 1rem;

text-align: center;

}

.current-player-display {

font-size: 1.5rem;

font-weight: bold;

padding: 0.5rem 2rem;

border-radius: 8px;

display: inline-block;

}

.current-player-display.white {

background: linear-gradient(135deg, #fff 0%, #f0f0f0 100%);

color: var(--primary-dark);

}

.current-player-display.black {

background: linear-gradient(135deg, #000 0%, #333 100%);

color: #fff;

}

.chess-board {

display: grid;

grid-template-columns: repeat(8, 60px);

grid-template-rows: repeat(8, 60px);

border: 3px solid var(--secondary-dark);

border-radius: 6px;

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

margin: 1rem 0;

}

.board-square {

width: 60px;

height: 60px;

display: flex;

align-items: center;

justify-content: center;

cursor: pointer;

transition: all 0.3s;

position: relative;

}

.board-square.light {

background: var(--board-light);

}

.board-square.dark {

background: var(--board-dark);

}

.board-square.selected {

background: #7fb069 !important;

box-shadow: inset 0 0 10px rgba(0,0,0,0.3);

}

.board-square.valid-move {

background: #4ecdc4 !important;

position: relative;

}

.board-square.valid-move::after {

content: '';

position: absolute;

width: 20px;

height: 20px;

background: rgba(78, 205, 196, 0.7);

border-radius: 50%;

}

.board-square.check {

background: #e74c3c !important;

}

.board-square.king-captured {

background: #9b59b6 !important;

animation: pulse 1s infinite;

}

@keyframes pulse {

0%, 100% { opacity: 1; }

50% { opacity: 0.7; }

}

.chess-piece {

font-size: 2.5rem;

cursor: pointer;

transition: transform 0.3s;

user-select: none;

z-index: 10;

}

.chess-piece:hover {

transform: scale(1.1);

}

.chess-piece.dragging {

opacity: 0.5;

cursor: grabbing;

}

/* 右侧信息面板 */

.info-panel {

background: rgba(30, 41, 59, 0.6);

border-radius: 12px;

padding: 1.5rem;

border: 1px solid rgba(148, 163, 184, 0.1);

}

.info-section {

margin-bottom: 2rem;

}

.info-section h3 {

color: var(--accent-gold);

margin-bottom: 0.75rem;

font-size: 1.1rem;

}

.info-section p {

color: var(--text-gray);

line-height: 1.6;

font-size: 0.9rem;

}

.captured-pieces {

display: flex;

gap: 0.5rem;

flex-wrap: wrap;

margin-top: 0.5rem;

}

.captured-piece {

font-size: 1.5rem;

opacity: 0.7;

}

/* 响应式设计 */

@media (max-width: 1200px) {

.game-section {

grid-template-columns: 1fr;

gap: 1rem;

}

.chess-board-container {

order: -1;

}

.chess-board {

grid-template-columns: repeat(8, 50px);

grid-template-rows: repeat(8, 50px);

}

.board-square {

width: 50px;

height: 50px;

}

.chess-piece {

font-size: 2rem;

}

}

@media (max-width: 600px) {

.chess-board {

grid-template-columns: repeat(8, 40px);

grid-template-rows: repeat(8, 40px);

}

.board-square {

width: 40px;

height: 40px;

}

.chess-piece {

font-size: 1.5rem;

}

}

/* 游戏结束覆盖层 */

.game-over-overlay {

position: fixed;

top: 0;

left: 0;

right: 0;

bottom: 0;

background: rgba(0,0,0,0.8);

display: none;

align-items: center;

justify-content: center;

z-index: 2000;

}

.game-over-modal {

background: var(--secondary-dark);

border-radius: 12px;

padding: 3rem;

text-align: center;

border: 2px solid var(--accent-gold);

max-width: 500px;

width: 90%;

}

.game-over-modal h2 {

color: var(--accent-gold);

font-size: 2.5rem;

margin-bottom: 1rem;

}

.game-over-modal p {

font-size: 1.2rem;

margin-bottom: 2rem;

color: var(--text-gray);

}

.game-over-modal .reason {

font-size: 1.4rem;

font-weight: bold;

color: #e74c3c;

margin-bottom: 1rem;

}

/* 警告提示 */

.warning-message {

position: fixed;

top: 100px;

left: 50%;

transform: translateX(-50%);

background: rgba(231, 76, 60, 0.9);

color: white;

padding: 1rem 2rem;

border-radius: 8px;

font-weight: bold;

display: none;

z-index: 1500;

animation: slideDown 0.3s ease-out;

}

@keyframes slideDown {

from {

transform: translateX(-50%) translateY(-100px);

opacity: 0;

}

to {

transform: translateX(-50%) translateY(0);

opacity: 1;

}

}

</style>

</head>

<body>

<header>

<div class="logo">国际象棋大师</div>

<nav>

<ul>

<li><a href="#play">开始对局</a></li>

<li><a href="#learn">学习规则</a></li>

<li><a href="#puzzles">战术谜题</a></li>

<li><a href="#about">关于我们</a></li>

</ul>

</nav>

</header>

<section class="game-section" id="play">

<!-- 左侧控制面板 -->

<aside class="control-panel">

<h3>游戏控制</h3>

<div class="game-controls">

<button class="btn btn-primary" onclick="resetGame()">🔄 新游戏</button>

<button class="btn btn-secondary" onclick="undoMove()">↩️ 悔棋</button>

<button class="btn btn-secondary" onclick="flipBoard()">🔄 翻转棋盘</button>

<button class="btn btn-secondary" onclick="showHint()">💡 提示</button>

</div>

<h3>对局记录</h3>

<div class="move-history" id="moveHistory">

<div class="move-item">等待开始对局...</div>

</div>

</aside>

<!-- 中央棋盘 -->

<main class="chess-board-container">

<div class="board-status">

<div class="current-player-display white" id="currentPlayerDisplay">

白方回合

</div>

</div>

<div class="chess-board" id="chessBoard"></div>

<div style="margin-top: 1rem; text-align: center;">

<small style="color: var(--text-gray);">点击棋子选择,点击目标位置移动</small>

</div>

</main>

<!-- 右侧信息面板 -->

<aside class="info-panel">

<div class="info-section">

<h3>游戏状态</h3>

<p id="gameStatus">对局进行中</p>

</div>

<div class="info-section">

<h3>被吃掉的棋子</h3>

<div class="captured-pieces" id="capturedPieces">

</div>

</div>

<div class="info-section">

<h3>快速规则</h3>

<p style="font-size: 0.85rem; line-height: 1.4;">

♔ 王:横、直、斜走一格<br>

♕ 后:横、直、斜任意格<br>

♖ 车:横、直任意格<br>

♗ 象:斜线任意格<br>

♞ 马:日字形移动<br>

♟ 兵:前进一格,吃子斜一格

</p>

</div>

<div class="info-section">

<h3>特殊规则</h3>

<p style="font-size: 0.85rem; line-height: 1.4;">

• 王车易位:王和车未移动,王车之间无棋子<br>

• 吃过路兵:对方兵跳两格时可斜吃<br>

• 升变:兵到达底线可变成后、车、象或马

</p>

</div>

</aside>

</section>

<!-- 游戏结束覆盖层 -->

<div class="game-over-overlay" id="gameOverOverlay">

<div class="game-over-modal">

<h2 id="gameOverTitle">游戏结束</h2>

<p class="reason" id="gameOverReason">王被吃掉!</p>

<p id="gameOverMessage">获胜方:白方</p>

<button class="btn btn-primary" onclick="resetGame()">再玩一局</button>

</div>

</div>

<!-- 警告提示 -->

<div class="warning-message" id="warningMessage"></div>

<script>

// 国际象棋游戏逻辑

class ChessGame {

constructor() {

this.board = \[\];

this.currentPlayer = 'white';

this.selectedSquare = null;

this.moveHistory = \[\];

this.capturedPieces = { white: \[\], black: \[\] };

this.kingPositions = { white: 7, 4, black: 0, 4 };

this.castlingRights = { white: { king: true, queen: true }, black: { king: true, queen: true } };

this.gameOver = false;

this.pieces = {

'K': '♔', 'Q': '♕', 'R': '♖', 'B': '♗', 'N': '♘', 'P': '♙',

'k': '♚', 'q': '♛', 'r': '♜', 'b': '♝', 'n': '♞', 'p': '♟'

};

this.initializeBoard();

this.renderBoard();

}

initializeBoard() {

// 初始化8x8棋盘

for (let row = 0; row < 8; row++) {

this.boardrow = \[\];

for (let col = 0; col < 8; col++) {

this.boardrowcol = '';

}

}

// 摆放棋子

// 黑方(上方)

this.board0 = 'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r';

this.board1 = 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p';

// 白方(下方)

this.board6 = 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P';

this.board7 = 'R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R';

}

renderBoard() {

const boardElement = document.getElementById('chessBoard');

boardElement.innerHTML = '';

for (let row = 0; row < 8; row++) {

for (let col = 0; col < 8; col++) {

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

square.className = `board-square ${(row + col) % 2 === 0 ? 'light' : 'dark'}`;

square.dataset.row = row;

square.dataset.col = col;

const piece = this.boardrowcol;

if (piece) {

const pieceElement = document.createElement('span');

pieceElement.className = 'chess-piece';

pieceElement.textContent = this.piecespiece;

pieceElement.dataset.piece = piece;

square.appendChild(pieceElement);

}

if (this.kingPositions.white0 === row && this.kingPositions.white1 === col && this.isKingInCheck('white')) {

square.classList.add('check');

}

if (this.kingPositions.black0 === row && this.kingPositions.black1 === col && this.isKingInCheck('black')) {

square.classList.add('check');

}

square.onclick = () => this.handleSquareClick(row, col);

boardElement.appendChild(square);

}

}

this.updateDisplay();

}

handleSquareClick(row, col) {

if (this.gameOver) return;

if (this.selectedSquare) {

const fromRow = this.selectedSquare0;

const fromCol = this.selectedSquare1;

if (fromRow === row && fromCol === col) {

// 取消选择

this.selectedSquare = null;

this.renderBoard();

} else if (this.isValidMove(fromRow, fromCol, row, col)) {

// 执行移动

this.makeMove(fromRow, fromCol, row, col);

} else {

// 重新选择

this.selectedSquare = row, col;

this.highlightMoves(fromRow, fromCol, row, col);

}

} else {

// 选择棋子

const piece = this.boardrowcol;

if (piece && this.getPieceColor(piece) === this.currentPlayer) {

this.selectedSquare = row, col;

this.highlightMoves(row, col);

}

}

}

highlightMoves(row, col) {

this.renderBoard();

const validMoves = this.getValidMoves(row, col);

validMoves.forEach((toRow, toCol) => {

const square = document.querySelector(`data-row="${toRow}"data-col="${toCol}"`);

if (square) {

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

}

});

const selectedSquare = document.querySelector(`data-row="${row}"data-col="${col}"`);

if (selectedSquare) {

selectedSquare.classList.add('selected');

}

}

getPieceColor(piece) {

return piece === piece.toUpperCase() ? 'white' : 'black';

}

isValidMove(fromRow, fromCol, toRow, toCol) {

const piece = this.boardfromRowfromCol;

const targetPiece = this.boardtoRowtoCol;

if (!piece || this.getPieceColor(piece) !== this.currentPlayer) return false;

if (targetPiece && this.getPieceColor(targetPiece) === this.currentPlayer) return false;

const moves = this.getValidMoves(fromRow, fromCol);

return moves.some((r, c) => r === toRow && c === toCol);

}

getValidMoves(row, col) {

const piece = this.boardrowcol;

const color = this.getPieceColor(piece);

const moves = \[\];

switch (piece.toUpperCase()) {

case 'P':

moves.push(...this.getPawnMoves(row, col, color));

break;

case 'R':

moves.push(...this.getRookMoves(row, col, color));

break;

case 'N':

moves.push(...this.getKnightMoves(row, col, color));

break;

case 'B':

moves.push(...this.getBishopMoves(row, col, color));

break;

case 'Q':

moves.push(...this.getQueenMoves(row, col, color));

break;

case 'K':

moves.push(...this.getKingMoves(row, col, color));

break;

}

// 过滤会导致己方被将军的走法

return moves.filter((toRow, toCol) => {

const tempBoard = this.board.map(row => ...row);

tempBoardtoRowtoCol = tempBoardrowcol;

tempBoardrowcol = '';

const tempKingPos = { ...this.kingPositions };

if (piece.toUpperCase() === 'K') {

tempKingPoscolor = toRow, toCol;

}

return !this.isKingInCheck(color, tempBoard, tempKingPos);

});

}

getPawnMoves(row, col, color) {

const moves = \[\];

const direction = color === 'white' ? -1 : 1;

const startRow = color === 'white' ? 6 : 1;

// 前进

if (this.boardrow + direction && this.boardrow + directioncol === '') {

moves.push(row + direction, col);

// 初始位置可以走两格

if (row === startRow && this.boardrow + 2 \* directioncol === '') {

moves.push(row + 2 \* direction, col);

}

}

// 吃子

-1, 1.forEach(offset => {

if (this.boardrow + direction && this.boardrow + directioncol + offset) {

const target = this.boardrow + directioncol + offset;

if (target && this.getPieceColor(target) !== color) {

moves.push(row + direction, col + offset);

}

}

});

return moves;

}

getRookMoves(row, col, color) {

return this.getLineMoves(row, col, \[0, 1, 1, 0, 0, -1, -1, 0], color);

}

getBishopMoves(row, col, color) {

return this.getLineMoves(row, col, \[1, 1, 1, -1, -1, 1, -1, -1], color);

}

getQueenMoves(row, col, color) {

return [

...this.getRookMoves(row, col, color),

...this.getBishopMoves(row, col, color)

];

}

getKnightMoves(row, col, color) {

const moves = \[\];

const knightMoves = [

2, 1, 2, -1, -2, 1, -2, -1,

1, 2\], \[1, -2\], \[-1, 2\], \[-1, -2

];

knightMoves.forEach((dr, dc) => {

const newRow = row + dr;

const newCol = col + dc;

if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8) {

const target = this.boardnewRownewCol;

if (!target || this.getPieceColor(target) !== color) {

moves.push(newRow, newCol);

}

}

});

return moves;

}

getKingMoves(row, col, color) {

const moves = \[\];

for (let dr = -1; dr <= 1; dr++) {

for (let dc = -1; dc <= 1; dc++) {

if (dr === 0 && dc === 0) continue;

const newRow = row + dr;

const newCol = col + dc;

if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8) {

const target = this.boardnewRownewCol;

if (!target || this.getPieceColor(target) !== color) {

moves.push(newRow, newCol);

}

}

}

}

return moves;

}

getLineMoves(row, col, directions, color) {

const moves = \[\];

directions.forEach((dr, dc) => {

let newRow = row + dr;

let newCol = col + dc;

while (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8) {

const target = this.boardnewRownewCol;

if (!target) {

moves.push(newRow, newCol);

} else {

if (this.getPieceColor(target) !== color) {

moves.push(newRow, newCol);

}

break;

}

newRow += dr;

newCol += dc;

}

});

return moves;

}

isKingInCheck(color, board = this.board, kingPos = this.kingPositions) {

const kingRow, kingCol = kingPoscolor;

// 检查对方所有棋子是否能吃到王

for (let row = 0; row < 8; row++) {

for (let col = 0; col < 8; col++) {

const piece = boardrowcol;

if (piece && this.getPieceColor(piece) !== color) {

const moves = this.getPotentialMoves(row, col, board);

if (moves.some((r, c) => r === kingRow && c === kingCol)) {

return true;

}

}

}

}

return false;

}

getPotentialMoves(row, col, board) {

const piece = boardrowcol;

const color = this.getPieceColor(piece);

const moves = \[\];

switch (piece.toUpperCase()) {

case 'P':

const direction = color === 'white' ? -1 : 1;

-1, 1.forEach(offset => {

if (boardrow + direction && boardrow + directioncol + offset) {

moves.push(row + direction, col + offset);

}

});

break;

case 'N':

const knightMoves = [

2, 1, 2, -1, -2, 1, -2, -1,

1, 2\], \[1, -2\], \[-1, 2\], \[-1, -2

];

knightMoves.forEach((dr, dc) => {

const newRow = row + dr;

const newCol = col + dc;

if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8) {

moves.push(newRow, newCol);

}

});

break;

case 'K':

for (let dr = -1; dr <= 1; dr++) {

for (let dc = -1; dc <= 1; dc++) {

if (dr === 0 && dc === 0) continue;

moves.push(row + dr, col + dc);

}

}

break;

case 'R':

moves.push(...this.getLineMoves(row, col, \[0, 1, 1, 0, 0, -1, -1, 0], color, board));

break;

case 'B':

moves.push(...this.getLineMoves(row, col, \[1, 1, 1, -1, -1, 1, -1, -1], color, board));

break;

case 'Q':

moves.push(...this.getLineMoves(row, col, \[0, 1, 1, 0, 0, -1, -1, 0, 1, 1, 1, -1, -1, 1, -1, -1], color, board));

break;

}

return moves;

}

makeMove(fromRow, fromCol, toRow, toCol) {

const piece = this.boardfromRowfromCol;

const capturedPiece = this.boardtoRowtoCol;

// 记录移动

const moveNotation = this.getMoveNotation(fromRow, fromCol, toRow, toCol, capturedPiece);

this.moveHistory.push(moveNotation);

// 处理被吃掉的棋子

if (capturedPiece) {

this.capturedPiecesthis.getPieceColor(capturedPiece).push(this.piecescapturedPiece);

// 检查是否吃掉王

if (capturedPiece.toUpperCase() === 'K') {

this.handleKingCaptured(this.getPieceColor(capturedPiece));

return;

}

}

// 移动棋子

this.boardtoRowtoCol = this.boardfromRowfromCol;

this.boardfromRowfromCol = '';

// 更新王的位置

if (piece.toUpperCase() === 'K') {

this.kingPositionsthis.currentPlayer = toRow, toCol;

}

// 检查升变

if (piece.toUpperCase() === 'P' && (toRow === 0 || toRow === 7)) {

this.boardtoRowtoCol = piece.toUpperCase() === 'P' ? 'Q' : 'q';

}

// 切换玩家

this.currentPlayer = this.currentPlayer === 'white' ? 'black' : 'white';

this.selectedSquare = null;

this.renderBoard();

this.updateHistory();

// 检查游戏状态

this.checkGameState();

}

handleKingCaptured(loserColor) {

this.gameOver = true;

const winner = loserColor === 'white' ? '黑方' : '白方';

const loser = loserColor === 'white' ? '白方' : '黑方';

// 显示警告动画

this.showWarning(`${loser}的王被吃掉了!`);

// 延迟显示游戏结束弹窗

setTimeout(() => {

this.showGameOver(`{winner}获胜!\`, \`{loser}的王被吃掉`, 'king-captured');

}, 1500);

// 标记被吃掉王的位置

const kingPos = this.kingPositionsloserColor;

const square = document.querySelector(`data-row="${kingPos\[0}"]data-col="${kingPos\[1}"]`);

if (square) {

square.classList.add('king-captured');

}

}

showWarning(message) {

const warningElement = document.getElementById('warningMessage');

warningElement.textContent = message;

warningElement.style.display = 'block';

setTimeout(() => {

warningElement.style.display = 'none';

}, 3000);

}

getMoveNotation(fromRow, fromCol, toRow, toCol, capturedPiece) {

const piece = this.boardfromRowfromCol;

const files = 'abcdefgh';

const ranks = '87654321';

let notation = '';

// 棋子符号(兵不写)

if (piece.toUpperCase() !== 'P') {

notation += piece.toUpperCase();

}

// 吃子标记

if (capturedPiece) {

if (piece.toUpperCase() === 'P') {

notation += filesfromCol;

}

notation += 'x';

}

// 目标位置

notation += filestoCol + rankstoRow;

return notation;

}

updateHistory() {

const historyElement = document.getElementById('moveHistory');

historyElement.innerHTML = this.moveHistory.map((move, i) => {

if (i % 2 === 0) {

return `<div class="move-item">{Math.floor(i / 2) + 1}. {move}</div>`;

} else {

return `<div class="move-item">${move}</div>`;

}

}).join('');

historyElement.scrollTop = historyElement.scrollHeight;

}

updateDisplay() {

const display = document.getElementById('currentPlayerDisplay');

if (this.gameOver) {

display.textContent = '游戏结束';

} else {

display.textContent = `{this.currentPlayer === 'white' ? '⚪' : '⚫'} {this.currentPlayer === 'white' ? '白方' : '黑方'}回合`;

}

display.className = `current-player-display ${this.currentPlayer}`;

}

checkKingExistence() {

let whiteKingExists = false;

let blackKingExists = false;

for (let row = 0; row < 8; row++) {

for (let col = 0; col < 8; col++) {

const piece = this.boardrowcol;

if (piece) {

if (piece === 'K') whiteKingExists = true;

if (piece === 'k') blackKingExists = true;

}

}

}

if (!whiteKingExists) {

return { gameOver: true, winner: 'black', loser: 'white', reason: '白方王被吃' };

}

if (!blackKingExists) {

return { gameOver: true, winner: 'white', loser: 'black', reason: '黑方王被吃' };

}

return { gameOver: false };

}

checkGameState() {

// 首先检查王是否存在

const kingCheck = this.checkKingExistence();

if (kingCheck.gameOver) {

this.handleKingCaptured(kingCheck.loser);

return;

}

// 检查是否有合法移动

let hasValidMove = false;

for (let row = 0; row < 8; row++) {

for (let col = 0; col < 8; col++) {

const piece = this.boardrowcol;

if (piece && this.getPieceColor(piece) === this.currentPlayer) {

if (this.getValidMoves(row, col).length > 0) {

hasValidMove = true;

break;

}

}

}

if (hasValidMove) break;

}

if (!hasValidMove) {

const isInCheck = this.isKingInCheck(this.currentPlayer);

if (isInCheck) {

const winner = this.currentPlayer === 'white' ? '黑方' : '白方';

const reason = '将死';

this.showGameOver(`${winner}获胜!`, reason);

} else {

this.showGameOver('平局!', '逼和');

}

}

}

showGameOver(result, reason, type = '') {

this.gameOver = true;

document.getElementById('gameOverTitle').textContent = result;

document.getElementById('gameOverReason').textContent = reason;

document.getElementById('gameOverMessage').textContent = `获胜方:${result.includes('白方') ? '白方' : '黑方'}`;

document.getElementById('gameOverOverlay').style.display = 'flex';

// 更新游戏状态显示

this.updateDisplay();

}

reset() {

this.board = \[\];

this.currentPlayer = 'white';

this.selectedSquare = null;

this.moveHistory = \[\];

this.capturedPieces = { white: \[\], black: \[\] };

this.kingPositions = { white: 7, 4, black: 0, 4 };

this.castlingRights = { white: { king: true, queen: true }, black: { king: true, queen: true } };

this.gameOver = false;

this.initializeBoard();

this.renderBoard();

this.updateHistory();

document.getElementById('gameOverOverlay').style.display = 'none';

document.getElementById('warningMessage').style.display = 'none';

}

undoMove() {

if (this.moveHistory.length > 0) {

this.moveHistory.pop();

// 简化实现:重置棋盘

this.reset();

}

}

}

// 全局实例

let game = null;

// 页面加载完成后初始化

document.addEventListener('DOMContentLoaded', function() {

game = new ChessGame();

});

// 全局函数

function resetGame() {

game.reset();

}

function undoMove() {

game.undoMove();

}

function flipBoard() {

alert('翻转棋盘功能开发中...');

}

function showHint() {

alert('提示功能开发中...');

}

</script>

</body>

</html>

相关推荐
卷帘依旧9 小时前
JavaScript 判断页面加载完成的多种场景
前端
光影少年9 小时前
React 项目常见优化方案
前端·react.js·前端框架
lichenyang4539 小时前
把 demo 里的 console.log 全换成 HiLog:从 %{private} 没脱敏的困惑说起
前端
烬羽9 小时前
JS 单线程为什么不卡?一文吃透同步异步、Event Loop 和 Promise
javascript·面试
光影少年9 小时前
组件复用:HOC、Render Props、自定义Hook 对比
前端·react.js·掘金·金石计划
Gauss松鼠会9 小时前
【GaussDB】GaussDB SMP特性调优详解
java·服务器·前端·数据库·sql·算法·gaussdb
葬送的代码人生9 小时前
JavaScript 数组完全指南:从入门到实战
前端·javascript·算法
用户938515635079 小时前
深入理解 JavaScript 同步与异步:从单线程到事件循环与 Promise
前端·javascript
搬砖的码农10 小时前
造一个 Agent 运行时 #01:我决定开干,顺便把坑都写下来
前端·agent·ai编程
yingyima10 小时前
深入解析:定时任务失败重试机制的底层原理与实践
前端