<!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.board[row] = [];
for (let col = 0; col < 8; col++) {
this.board[row][col] = '';
}
}
// 摆放棋子
// 黑方(上方)
this.board[0] = ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'];
this.board[1] = ['p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'];
// 白方(下方)
this.board[6] = ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'];
this.board[7] = ['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.board[row][col];
if (piece) {
const pieceElement = document.createElement('span');
pieceElement.className = 'chess-piece';
pieceElement.textContent = this.pieces[piece];
pieceElement.dataset.piece = piece;
square.appendChild(pieceElement);
}
if (this.kingPositions.white[0] === row && this.kingPositions.white[1] === col && this.isKingInCheck('white')) {
square.classList.add('check');
}
if (this.kingPositions.black[0] === row && this.kingPositions.black[1] === 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.selectedSquare[0];
const fromCol = this.selectedSquare[1];
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.board[row][col];
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.board[fromRow][fromCol];
const targetPiece = this.board[toRow][toCol];
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.board[row][col];
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]);
tempBoard[toRow][toCol] = tempBoard[row][col];
tempBoard[row][col] = '';
const tempKingPos = { ...this.kingPositions };
if (piece.toUpperCase() === 'K') {
tempKingPos[color] = [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.board[row + direction] && this.board[row + direction][col] === '') {
moves.push([row + direction, col]);
// 初始位置可以走两格
if (row === startRow && this.board[row + 2 * direction][col] === '') {
moves.push([row + 2 * direction, col]);
}
}
// 吃子
-1, 1\].forEach(offset =\> { if (this.board\[row + direction\] \&\& this.board\[row + direction\]\[col + offset\]) { const target = this.board\[row + direction\]\[col + 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.board[newRow][newCol];
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.board[newRow][newCol];
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.board[newRow][newCol];
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] = kingPos[color];
// 检查对方所有棋子是否能吃到王
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
const piece = board[row][col];
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 = board[row][col];
const color = this.getPieceColor(piece);
const moves = [];
switch (piece.toUpperCase()) {
case 'P':
const direction = color === 'white' ? -1 : 1;
-1, 1\].forEach(offset =\> { if (board\[row + direction\] \&\& board\[row + direction\]\[col + 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.board[fromRow][fromCol];
const capturedPiece = this.board[toRow][toCol];
// 记录移动
const moveNotation = this.getMoveNotation(fromRow, fromCol, toRow, toCol, capturedPiece);
this.moveHistory.push(moveNotation);
// 处理被吃掉的棋子
if (capturedPiece) {
this.capturedPieces[this.getPieceColor(capturedPiece)].push(this.pieces[capturedPiece]);
// 检查是否吃掉王
if (capturedPiece.toUpperCase() === 'K') {
this.handleKingCaptured(this.getPieceColor(capturedPiece));
return;
}
}
// 移动棋子
this.board[toRow][toCol] = this.board[fromRow][fromCol];
this.board[fromRow][fromCol] = '';
// 更新王的位置
if (piece.toUpperCase() === 'K') {
this.kingPositions[this.currentPlayer] = [toRow, toCol];
}
// 检查升变
if (piece.toUpperCase() === 'P' && (toRow === 0 || toRow === 7)) {
this.board[toRow][toCol] = 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.kingPositions[loserColor];
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.board[fromRow][fromCol];
const files = 'abcdefgh';
const ranks = '87654321';
let notation = '';
// 棋子符号(兵不写)
if (piece.toUpperCase() !== 'P') {
notation += piece.toUpperCase();
}
// 吃子标记
if (capturedPiece) {
if (piece.toUpperCase() === 'P') {
notation += files[fromCol];
}
notation += 'x';
}
// 目标位置
notation += files[toCol] + ranks[toRow];
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.board[row][col];
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.board[row][col];
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>