11.7 脚本网站 中国象棋

本来flask部署了一下,但是太臭太长,直接给个能能玩的htnl,需要完整也可以私信我

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

display: flex;

justify-content: center;

align-items: center;

min-height: 100vh;

margin: 0;

padding: 10px;

background-color: #f0e6d2;

font-family: Arial, sans-serif;

box-sizing: border-box;

}

.game-container {

text-align: center;

max-width: 100vw;

overflow-x: auto;

}

/* 模式选择弹窗 */

.mode-selection {

position: fixed;

top: 0;

left: 0;

width: 100%;

height: 100%;

background-color: rgba(0,0,0,0.7);

display: flex;

justify-content: center;

align-items: center;

z-index: 1000;

}

.mode-box {

background-color: white;

padding: 30px;

border-radius: 10px;

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

max-width: 90vw;

}

.mode-box h2 {

margin-bottom: 20px;

color: #8b4513;

}

.mode-button {

display: block;

width: 200px;

margin: 10px auto;

padding: 15px;

font-size: 18px;

background-color: #8b4513;

color: white;

border: none;

border-radius: 5px;

cursor: pointer;

}

.mode-button:hover {

background-color: #a0522d;

}

/* 响应式棋盘样式 */

.board {

position: relative;

width: 90vw;

max-width: 600px;

height: calc(90vw * 1.1);

max-height: 660px;

background-color: #f9d4b4;

border: 3px solid #8b4513;

margin: 20px auto;

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

}

@media (min-width: 768px) {

.board {

width: 600px;

height: 660px;

}

}

.piece {

position: absolute;

border-radius: 50%;

font-weight: bold;

display: flex;

align-items: center;

justify-content: center;

cursor: pointer;

transition: all 0.3s ease;

z-index: 10;

user-select: none;

}

.piece.red {

background: radial-gradient(circle at 30% 30%, #ff6b6b, #cc0000);

color: #fff;

border: 2px solid #990000;

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

}

.piece.black {

background: radial-gradient(circle at 30% 30%, #666, #000);

color: #fff;

border: 2px solid #000;

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

}

.piece.selected {

transform: scale(1.1);

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

border-color: #ffff00;

}

.piece.hint {

animation: pulse 1s infinite;

}

@keyframes pulse {

0% { transform: scale(1); }

50% { transform: scale(1.15); }

100% { transform: scale(1); }

}

.grid {

position: absolute;

cursor: pointer;

z-index: 1;

}

/* 棋盘线条响应式 */

.board-lines {

position: absolute;

top: 5vw;

left: 5vw;

width: 80vw;

max-width: 540px;

height: calc(80vw * 1.11);

max-height: 600px;

}

@media (min-width: 768px) {

.board-lines {

top: 30px;

left: 30px;

width: 540px;

height: 600px;

}

}

.horizontal-line {

position: absolute;

width: 80vw;

max-width: 540px;

height: 1px;

background-color: #000;

}

@media (min-width: 768px) {

.horizontal-line {

width: 540px;

}

}

.vertical-line {

position: absolute;

width: 1px;

height: calc(80vw * 1.11);

max-height: 600px;

background-color: #000;

}

@media (min-width: 768px) {

.vertical-line {

height: 600px;

}

}

.river {

position: absolute;

top: calc(45vw - 5vw);

left: 5vw;

width: 80vw;

max-width: 540px;

height: 10vw;

max-height: 60px;

background-color: rgba(135, 206, 235, 0.3);

pointer-events: none;

}

@media (min-width: 768px) {

.river {

top: 270px;

left: 30px;

width: 540px;

height: 60px;

}

}

.controls {

margin-top: 20px;

display: flex;

flex-wrap: wrap;

justify-content: center;

gap: 10px;

}

button {

padding: 10px 20px;

font-size: 16px;

background-color: #8b4513;

color: white;

border: none;

border-radius: 5px;

cursor: pointer;

margin: 5px;

}

button:hover {

background-color: #a0522d;

}

.status {

margin-top: 10px;

font-size: 18px;

font-weight: bold;

}

.hint-text {

margin-top: 10px;

font-size: 14px;

color: #666;

min-height: 20px;

}

.move-history {

margin-top: 20px;

max-height: 150px;

overflow-y: auto;

background-color: rgba(255, 255, 255, 0.5);

padding: 10px;

border-radius: 5px;

width: 90vw;

max-width: 300px;

margin-left: auto;

margin-right: auto;

}

.move-item {

font-size: 12px;

margin: 2px 0;

padding: 2px 5px;

background-color: rgba(255, 255, 255, 0.8);

border-radius: 3px;

}

.move-item.red {

color: #cc0000;

}

.move-item.black {

color: #000;

}

.stats-btn {

display: inline-block;

padding: 6px 14px;

background: #f9d4b4;

border: 2px solid #8b4513;

border-radius: 6px;

color: #8b4513;

text-decoration: none;

font-weight: bold;

margin-left: 20px;

transition: all 0.3s ease;

}

.stats-btn:hover {

background: #8b4513;

color: #fff;

}

</style>

</head>

<body>

<!-- 模式选择 -->

<div class="mode-selection" id="modeSelection">

<div class="mode-box">

<h2>选择游戏模式</h2>

<button class="mode-button" onclick="startGame('pvp')">双人对战</button>

<button class="mode-button" onclick="startGame('ai')">AI对战</button>

</div>

</div>

<div class="game-container">

<h1>中国象棋</h1>

<a href="/stats.html" class="stats-btn">📊 数据排行</a>

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

<div class="board-lines">

<div class="horizontal-line" style="top: 0%;"></div>

<div class="horizontal-line" style="top: 10%;"></div>

<div class="horizontal-line" style="top: 20%;"></div>

<div class="horizontal-line" style="top: 30%;"></div>

<div class="horizontal-line" style="top: 40%;"></div>

<div class="horizontal-line" style="top: 50%;"></div>

<div class="horizontal-line" style="top: 60%;"></div>

<div class="horizontal-line" style="top: 70%;"></div>

<div class="horizontal-line" style="top: 80%;"></div>

<div class="horizontal-line" style="top: 90%;"></div>

<div class="horizontal-line" style="top: 100%;"></div>

<div class="vertical-line" style="left: 0%;"></div>

<div class="vertical-line" style="left: 12.5%;"></div>

<div class="vertical-line" style="left: 25%;"></div>

<div class="vertical-line" style="left: 37.5%;"></div>

<div class="vertical-line" style="left: 50%;"></div>

<div class="vertical-line" style="left: 62.5%;"></div>

<div class="vertical-line" style="left: 75%;"></div>

<div class="vertical-line" style="left: 87.5%;"></div>

<div class="vertical-line" style="left: 100%;"></div>

<div class="river"></div>

<div class="diagonal" style="left: 37.5%; top: 0%; transform: rotate(45deg);"></div>

<div class="diagonal" style="left: 87.5%; top: 0%; transform: rotate(-45deg);"></div>

<div class="diagonal" style="left: 37.5%; top: 75%; transform: rotate(-45deg);"></div>

<div class="diagonal" style="left: 87.5%; top: 75%; transform: rotate(45deg);"></div>

</div>

</div>

<div class="controls">

<button onclick="resetGame()">重新开始</button>

<button onclick="showRules()">规则说明</button>

<button onclick="undoMove()">悔棋</button>

<button onclick="getHint()">提示走法</button>

</div>

<div class="status">

当前玩家:<span id="currentPlayer" class="current-player">红方</span>

<span id="gameMode" style="margin-left: 20px; color: #666;"></span>

</div>

<div class="hint-text" id="hintText"></div>

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

<h4>走棋记录</h4>

<div id="moveList"></div>

</div>

</div>

<script>

// 棋盘尺寸

const BOARD_WIDTH = 9;

const BOARD_HEIGHT = 10;

// 棋子类型

const PIECE_TYPES = {

SHUAI: '帅',

SHI: '士',

XIANG: '相',

MA: '马',

JU: '车',

PAO: '炮',

BING: '兵'

};

// 游戏状态

let board = [];

let selectedPiece = null;

let currentPlayer = 'red';

let gameOver = false;

let moveHistory = [];

let gameMode = '';

let aiThinking = false;

// 初始化棋盘

function initBoard() {

board = Array(BOARD_HEIGHT).fill(null).map(() => Array(BOARD_WIDTH).fill(null));

// 红方棋子

const redPieces = [

{type: PIECE_TYPES.JU, row: 9, col: 0, player: 'red'},

{type: PIECE_TYPES.MA, row: 9, col: 1, player: 'red'},

{type: PIECE_TYPES.XIANG, row: 9, col: 2, player: 'red'},

{type: PIECE_TYPES.SHI, row: 9, col: 3, player: 'red'},

{type: PIECE_TYPES.SHUAI, row: 9, col: 4, player: 'red'},

{type: PIECE_TYPES.SHI, row: 9, col: 5, player: 'red'},

{type: PIECE_TYPES.XIANG, row: 9, col: 6, player: 'red'},

{type: PIECE_TYPES.MA, row: 9, col: 7, player: 'red'},

{type: PIECE_TYPES.JU, row: 9, col: 8, player: 'red'},

{type: PIECE_TYPES.PAO, row: 7, col: 1, player: 'red'},

{type: PIECE_TYPES.PAO, row: 7, col: 7, player: 'red'},

{type: PIECE_TYPES.BING, row: 6, col: 0, player: 'red'},

{type: PIECE_TYPES.BING, row: 6, col: 2, player: 'red'},

{type: PIECE_TYPES.BING, row: 6, col: 4, player: 'red'},

{type: PIECE_TYPES.BING, row: 6, col: 6, player: 'red'},

{type: PIECE_TYPES.BING, row: 6, col: 8, player: 'red'}

];

// 黑方棋子

const blackPieces = [

{type: PIECE_TYPES.JU, row: 0, col: 0, player: 'black'},

{type: PIECE_TYPES.MA, row: 0, col: 1, player: 'black'},

{type: PIECE_TYPES.XIANG, row: 0, col: 2, player: 'black'},

{type: PIECE_TYPES.SHI, row: 0, col: 3, player: 'black'},

{type: PIECE_TYPES.SHUAI, row: 0, col: 4, player: 'black'},

{type: PIECE_TYPES.SHI, row: 0, col: 5, player: 'black'},

{type: PIECE_TYPES.XIANG, row: 0, col: 6, player: 'black'},

{type: PIECE_TYPES.MA, row: 0, col: 7, player: 'black'},

{type: PIECE_TYPES.JU, row: 0, col: 8, player: 'black'},

{type: PIECE_TYPES.PAO, row: 2, col: 1, player: 'black'},

{type: PIECE_TYPES.PAO, row: 2, col: 7, player: 'black'},

{type: PIECE_TYPES.BING, row: 3, col: 0, player: 'black'},

{type: PIECE_TYPES.BING, row: 3, col: 2, player: 'black'},

{type: PIECE_TYPES.BING, row: 3, col: 4, player: 'black'},

{type: PIECE_TYPES.BING, row: 3, col: 6, player: 'black'},

{type: PIECE_TYPES.BING, row: 3, col: 8, player: 'black'}

];

// 将所有棋子放置到棋盘上

...redPieces, ...blackPieces\].forEach(piece =\> { board\[piece.row\]\[piece.col\] = piece; }); } // 获取格子尺寸(带缓存,防止频繁重算) function getCellSize() { const board = document.getElementById('board'); return board.offsetWidth / BOARD_WIDTH; } // 渲染棋盘(棋子/格子/棋盘线 三线对齐) function renderBoard() { const boardElement = document.getElementById('board'); const cellSize = getCellSize(); const pieceSize = Math.round(cellSize \* 0.70); // 想再小就调 0.65 const pieceOff = Math.round((cellSize - pieceSize) / 2); // 1. 清空旧内容 boardElement.querySelectorAll('.piece, .grid').forEach(el =\> el.remove()); // 2. 创建点击格子(满格,不缩放) for (let row = 0; row \< BOARD_HEIGHT; row++) { for (let col = 0; col \< BOARD_WIDTH; col++) { const grid = document.createElement('div'); grid.className = 'grid'; grid.style.left = \`${col \* cellSize}px\`; grid.style.top = \`${row \* cellSize}px\`; grid.style.width = \`${cellSize}px\`; grid.style.height = \`${cellSize}px\`; grid.dataset.row = row; grid.dataset.col = col; grid.onclick = () =\> handleGridClick(row, col); boardElement.appendChild(grid); } } // 3. 创建棋子(居中) for (let row = 0; row \< BOARD_HEIGHT; row++) { for (let col = 0; col \< BOARD_WIDTH; col++) { const piece = board\[row\]\[col\]; if (!piece) continue; const el = document.createElement('div'); el.className = \`piece ${piece.player}\`; el.textContent = piece.type; el.style.left = \`${col \* cellSize + pieceOff}px\`; el.style.top = \`${row \* cellSize + pieceOff}px\`; el.style.width = \`${pieceSize}px\`; el.style.height = \`${pieceSize}px\`; el.style.fontSize = \`${Math.round(pieceSize \* 0.5)}px\`; el.dataset.row = row; el.dataset.col = col; el.onclick = (e) =\> { e.stopPropagation(); handlePieceClick(row, col); }; boardElement.appendChild(el); } } // 4. 把棋盘线移到交叉点(只做一次) const lines = document.querySelector('.board-lines'); if (lines) { lines.style.left = \`${cellSize / 2}px\`; lines.style.top = \`${cellSize / 2}px\`; lines.style.width = \`${cellSize \* (BOARD_WIDTH - 1)}px\`; lines.style.height = \`${cellSize \* (BOARD_HEIGHT - 1)}px\`; } } // 处理棋子点击 function handlePieceClick(row, col) { if (gameOver \|\| aiThinking) return; const piece = board\[row\]\[col\]; if (!piece) return; // 情况1:已选中己方棋子,再点对方棋子 → 直接吃 if (selectedPiece \&\& piece.player !== currentPlayer) { if (isValidMove(selectedPiece.row, selectedPiece.col, row, col)) { movePiece(selectedPiece.row, selectedPiece.col, row, col); if (gameMode === 'ai' \&\& currentPlayer === 'black' \&\& !gameOver) { setTimeout(() =\> aiMove(), 500); } } return; } // 情况2:没选中己方棋子,点对方棋子 → 自动找能吃它的己方棋子 if (piece.player !== currentPlayer) { for (let r = 0; r \< BOARD_HEIGHT; r++) { for (let c = 0; c \< BOARD_WIDTH; c++) { const my = board\[r\]\[c\]; if (my \&\& my.player === currentPlayer \&\& isValidMove(r, c, row, col)) { movePiece(r, c, row, col); if (gameMode === 'ai' \&\& currentPlayer === 'black' \&\& !gameOver) { setTimeout(() =\> aiMove(), 500); } return; } } } return; } // 情况3:点己方棋子 → 正常选中 clearSelection(); selectedPiece = {row, col, piece}; highlightPiece(row, col); showValidMoves(row, col); } // 处理格子点击 function handleGridClick(row, col) { if (gameOver \|\| !selectedPiece \|\| aiThinking) return; const targetPiece = board\[row\]\[col\]; if (targetPiece \&\& targetPiece.player === currentPlayer) { handlePieceClick(row, col); return; } if (isValidMove(selectedPiece.row, selectedPiece.col, row, col)) { movePiece(selectedPiece.row, selectedPiece.col, row, col); if (gameMode === 'ai' \&\& currentPlayer === 'black' \&\& !gameOver) { setTimeout(() =\> aiMove(), 500); } } } // AI走棋 function aiMove() { if (gameOver \|\| aiThinking) return; aiThinking = true; document.getElementById('hintText').textContent = 'AI正在思考...'; setTimeout(() =\> { const bestMove = findBestMove(3); if (bestMove) { movePiece(bestMove.from.row, bestMove.from.col, bestMove.to.row, bestMove.to.col); } aiThinking = false; }, 1000); } // 使用Minimax算法找到最佳移动 function findBestMove(depth) { const possibleMoves = getAllPossibleMoves('black'); if (possibleMoves.length === 0) return null; let bestMove = null; let bestScore = -Infinity; for (const move of possibleMoves) { const moveData = executeMove(move); const score = minimax(depth - 1, -Infinity, Infinity, false); undoMoveData(moveData); if (score \> bestScore) { bestScore = score; bestMove = move; } } return bestMove; } // Minimax算法 function minimax(depth, alpha, beta, isMaximizing) { if (depth === 0 \|\| gameOver) { return evaluateBoard(); } const player = isMaximizing ? 'black' : 'red'; const possibleMoves = getAllPossibleMoves(player); if (isMaximizing) { let maxEval = -Infinity; for (const move of possibleMoves) { const moveData = executeMove(move); const eval = minimax(depth - 1, alpha, beta, false); undoMoveData(moveData); maxEval = Math.max(maxEval, eval); alpha = Math.max(alpha, eval); if (beta \<= alpha) break; } return maxEval; } else { let minEval = Infinity; for (const move of possibleMoves) { const moveData = executeMove(move); const eval = minimax(depth - 1, alpha, beta, true); undoMoveData(moveData); minEval = Math.min(minEval, eval); beta = Math.min(beta, eval); if (beta \<= alpha) break; } return minEval; } } // 获取所有可能的移动 function getAllPossibleMoves(player) { const moves = \[\]; for (let row = 0; row \< BOARD_HEIGHT; row++) { for (let col = 0; col \< BOARD_WIDTH; col++) { const piece = board\[row\]\[col\]; if (piece \&\& piece.player === player) { for (let toRow = 0; toRow \< BOARD_HEIGHT; toRow++) { for (let toCol = 0; toCol \< BOARD_WIDTH; toCol++) { if (isValidMove(row, col, toRow, toCol)) { moves.push({ from: {row, col}, to: {row: toRow, col: toCol}, piece: piece }); } } } } } } return moves; } // 执行移动并返回移动数据 function executeMove(move) { const piece = board\[move.from.row\]\[move.from.col\]; const targetPiece = board\[move.to.row\]\[move.to.col\]; const moveData = { from: {...move.from}, to: {...move.to}, piece: {...piece}, captured: targetPiece ? {...targetPiece} : null, board: board.map(row =\> row.map(cell =\> cell ? {...cell} : null)) }; board\[move.to.row\]\[move.to.col\] = piece; board\[move.from.row\]\[move.from.col\] = null; return moveData; } // 撤销移动数据 function undoMoveData(moveData) { board = moveData.board.map(row =\> row.map(cell =\> cell ? {...cell} : null)); } // 评估棋盘局面 function evaluateBoard() { const value = { '兵': 10, '卒': 10, '炮': 30, '马': 30, '相': 20, '象': 20, '士': 20, '仕': 20, '车': 50, '車': 50, '帅': 1000, '将': 1000 }; let score = 0; for (let r = 0; r \< BOARD_HEIGHT; r++) { for (let c = 0; c \< BOARD_WIDTH; c++) { const p = board\[r\]\[c\]; if (!p) continue; let v = value\[p.type\] \|\| 0; // 过河兵额外 +8 分,鼓励前进 if ((p.player === 'red' \&\& p.type === '兵' \&\& r \<= 4) \|\| (p.player === 'black' \&\& p.type === '卒' \&\& r \>= 5)) v += 8; // 控制中心区域 +3 分 if (r \>= 2 \&\& r \<= 7 \&\& c \>= 2 \&\& c \<= 6) v += 3; score += (p.player === 'black' ? v : -v); } } return score; } // 清除选中状态 function clearSelection() { selectedPiece = null; document.querySelectorAll('.piece.selected').forEach(el =\> { el.classList.remove('selected'); }); document.querySelectorAll('.piece.hint').forEach(el =\> { el.classList.remove('hint'); }); document.querySelectorAll('.piece.valid-move').forEach(el =\> { el.classList.remove('valid-move'); }); } // 高亮选中的棋子 function highlightPiece(row, col) { const pieceElement = document.querySelector(\`.piece\[data-row="${row}"\]\[data-col="${col}"\]\`); if (pieceElement) { pieceElement.classList.add('selected'); } } // 显示有效移动位置 function showValidMoves(row, col) { for (let r = 0; r \< BOARD_HEIGHT; r++) { for (let c = 0; c \< BOARD_WIDTH; c++) { if (isValidMove(row, col, r, c)) { const pieceElement = document.querySelector(\`.piece\[data-row="${r}"\]\[data-col="${c}"\]\`); if (pieceElement) { pieceElement.classList.add('valid-move'); } } } } } // 检查移动是否有效 function isValidMove(fromRow, fromCol, toRow, toCol) { const piece = board\[fromRow\]\[fromCol\]; if (!piece) return false; const targetPiece = board\[toRow\]\[toCol\]; if (targetPiece \&\& targetPiece.player === piece.player) return false; const rowDiff = toRow - fromRow; const colDiff = toCol - fromCol; const absRowDiff = Math.abs(rowDiff); const absColDiff = Math.abs(colDiff); switch (piece.type) { case PIECE_TYPES.SHUAI: return isValidShuaiMove(fromRow, fromCol, toRow, toCol); case PIECE_TYPES.SHI: if (piece.player === 'red') { return toRow \>= 7 \&\& toRow \<= 9 \&\& toCol \>= 3 \&\& toCol \<= 5 \&\& absRowDiff === 1 \&\& absColDiff === 1; } else { return toRow \>= 0 \&\& toRow \<= 2 \&\& toCol \>= 3 \&\& toCol \<= 5 \&\& absRowDiff === 1 \&\& absColDiff === 1; } case PIECE_TYPES.XIANG: if (piece.player === 'red' \&\& toRow \< 5) return false; if (piece.player === 'black' \&\& toRow \> 4) return false; if (absRowDiff !== 2 \|\| absColDiff !== 2) return false; const midRow = fromRow + rowDiff / 2; const midCol = fromCol + colDiff / 2; return board\[midRow\]\[midCol\] === null; case PIECE_TYPES.MA: if (!((absRowDiff === 2 \&\& absColDiff === 1) \|\| (absRowDiff === 1 \&\& absColDiff === 2))) return false; if (absRowDiff === 2) { const midRow = fromRow + rowDiff / 2; return board\[midRow\]\[fromCol\] === null; } else { const midCol = fromCol + colDiff / 2; return board\[fromRow\]\[midCol\] === null; } case PIECE_TYPES.JU: return isValidJuMove(fromRow, fromCol, toRow, toCol); case PIECE_TYPES.PAO: return isValidPaoMove(fromRow, fromCol, toRow, toCol); case PIECE_TYPES.BING: return isValidBingMove(fromRow, fromCol, toRow, toCol); default: return false; } } // 检查帅的移动 function isValidShuaiMove(fromRow, fromCol, toRow, toCol) { const piece = board\[fromRow\]\[fromCol\]; const targetPiece = board\[toRow\]\[toCol\]; if (piece.player === 'red') { if (toRow \< 7 \|\| toRow \> 9 \|\| toCol \< 3 \|\| toCol \> 5) return false; } else { if (toRow \< 0 \|\| toRow \> 2 \|\| toCol \< 3 \|\| toCol \> 5) return false; } const rowDiff = Math.abs(toRow - fromRow); const colDiff = Math.abs(toCol - fromCol); if (!((rowDiff === 1 \&\& colDiff === 0) \|\| (rowDiff === 0 \&\& colDiff === 1))) { return false; } if (targetPiece \&\& targetPiece.type === PIECE_TYPES.SHUAI) { if (fromCol === toCol) { const minRow = Math.min(fromRow, toRow); const maxRow = Math.max(fromRow, toRow); for (let row = minRow + 1; row \< maxRow; row++) { if (board\[row\]\[fromCol\] !== null) return false; } return true; } } return true; } // 检查车的移动 function isValidJuMove(fromRow, fromCol, toRow, toCol) { if (fromRow !== toRow \&\& fromCol !== toCol) return false; if (fromRow === toRow) { const minCol = Math.min(fromCol, toCol); const maxCol = Math.max(fromCol, toCol); for (let col = minCol + 1; col \< maxCol; col++) { if (board\[fromRow\]\[col\] !== null) return false; } } else { const minRow = Math.min(fromRow, toRow); const maxRow = Math.max(fromRow, toRow); for (let row = minRow + 1; row \< maxRow; row++) { if (board\[row\]\[fromCol\] !== null) return false; } } return true; } // 检查炮的移动 function isValidPaoMove(fromRow, fromCol, toRow, toCol) { if (fromRow !== toRow \&\& fromCol !== toCol) return false; const targetPiece = board\[toRow\]\[toCol\]; let pieceCount = 0; if (fromRow === toRow) { const minCol = Math.min(fromCol, toCol); const maxCol = Math.max(fromCol, toCol); for (let col = minCol + 1; col \< maxCol; col++) { if (board\[fromRow\]\[col\] !== null) pieceCount++; } } else { const minRow = Math.min(fromRow, toRow); const maxRow = Math.max(fromRow, toRow); for (let row = minRow + 1; row \< maxRow; row++) { if (board\[row\]\[fromCol\] !== null) pieceCount++; } } if (targetPiece) { return pieceCount === 1; } else { return pieceCount === 0; } } // 兵(卒)合法移动判断 function isValidBingMove(fromRow, fromCol, toRow, toCol) { const piece = board\[fromRow\]\[fromCol\]; const rowDiff = toRow - fromRow; const colDiff = Math.abs(toCol - fromCol); if (piece.player === 'red') { if (fromRow \> 4) { return rowDiff === -1 \&\& colDiff === 0; } else { return (rowDiff === -1 \&\& colDiff === 0) \|\| (rowDiff === 0 \&\& colDiff === 1); } } else { if (fromRow \< 5) { return rowDiff === 1 \&\& colDiff === 0; } else { return (rowDiff === 1 \&\& colDiff === 0) \|\| (rowDiff === 0 \&\& colDiff === 1); } } } // 移动棋子 function movePiece(fromRow, fromCol, toRow, toCol) { const piece = board\[fromRow\]\[fromCol\]; const targetPiece = board\[toRow\]\[toCol\]; const moveData = { from: {row: fromRow, col: fromCol}, to: {row: toRow, col: toCol}, piece: {...piece}, captured: targetPiece ? {...targetPiece} : null, board: board.map(row =\> row.map(cell =\> cell ? {...cell} : null)) }; board\[toRow\]\[toCol\] = piece; board\[fromRow\]\[fromCol\] = null; addMoveToHistory(moveData); if (targetPiece) { if (targetPiece.type === PIECE_TYPES.SHUAI) { gameOver = true; setTimeout(() =\> { alert(\`${currentPlayer === 'red' ? '红方' : '黑方'}获胜!\`); }, 100); } } currentPlayer = currentPlayer === 'red' ? 'black' : 'red'; updateStatus(); document.getElementById('hintText').textContent = ''; clearSelection(); renderBoard(); } // 添加移动到历史记录 function addMoveToHistory(moveData) { const moveList = document.getElementById('moveList'); const moveItem = document.createElement('div'); moveItem.className = \`move-item ${currentPlayer}\`; const fromPos = \`${9 - moveData.from.row}${String.fromCharCode(97 + moveData.from.col)}\`; const toPos = \`${9 - moveData.to.row}${String.fromCharCode(97 + moveData.to.col)}\`; const captureText = moveData.captured ? \` 吃${moveData.captured.type}\` : ''; moveItem.textContent = \`${moveData.piece.type}: ${fromPos} → ${toPos}${captureText}\`; moveList.insertBefore(moveItem, moveList.firstChild); moveHistory.push(moveData); } // 悔棋 function undoMove() { if (moveHistory.length === 0) { alert('没有可以悔棋的记录了!'); return; } if (gameMode === 'ai' \&\& moveHistory.length \< 2) { alert('AI模式下至少需要走两步才能悔棋!'); return; } if (confirm('确定要悔棋吗?')) { const steps = gameMode === 'ai' ? 2 : 1; for (let i = 0; i \< steps; i++) { if (moveHistory.length === 0) break; const lastMove = moveHistory.pop(); board = lastMove.board.map(row =\> row.map(cell =\> cell ? {...cell} : null)); const moveList = document.getElementById('moveList'); if (moveList.firstChild) { moveList.removeChild(moveList.firstChild); } } currentPlayer = currentPlayer === 'red' ? 'black' : 'red'; updateStatus(); clearSelection(); document.getElementById('hintText').textContent = ''; renderBoard(); } } // 获取提示 function getHint() { if (gameOver \|\| aiThinking) return; const playerPieces = \[\]; for (let row = 0; row \< BOARD_HEIGHT; row++) { for (let col = 0; col \< BOARD_WIDTH; col++) { const piece = board\[row\]\[col\]; if (piece \&\& piece.player === currentPlayer) { playerPieces.push({row, col, piece}); } } } const possibleMoves = \[\]; for (const pieceInfo of playerPieces) { for (let toRow = 0; toRow \< BOARD_HEIGHT; toRow++) { for (let toCol = 0; toCol \< BOARD_WIDTH; toCol++) { if (isValidMove(pieceInfo.row, pieceInfo.col, toRow, toCol)) { const score = evaluateMoveDeep(pieceInfo.row, pieceInfo.col, toRow, toCol, 3); possibleMoves.push({ from: {row: pieceInfo.row, col: pieceInfo.col}, to: {row: toRow, col: toCol}, piece: pieceInfo.piece, score: score }); } } } } if (possibleMoves.length === 0) { document.getElementById('hintText').textContent = '没有可走的棋子了!'; return; } possibleMoves.sort((a, b) =\> b.score - a.score); const bestMove = possibleMoves\[0\]; const hintText = document.getElementById('hintText'); const fromPos = \`${9 - bestMove.from.row}${String.fromCharCode(97 + bestMove.from.col)}\`; const toPos = \`${9 - bestMove.to.row}${String.fromCharCode(97 + bestMove.to.col)}\`; let reason = ''; if (bestMove.score \> 50) { reason = ' (可以吃掉对方重要棋子)'; } else if (bestMove.score \< -20) { reason = ' (可能被吃,谨慎考虑)'; } else { reason = ' (较为安全的走法)'; } hintText.textContent = \`建议走法:${bestMove.piece.type} 从 ${fromPos} 走到 ${toPos}${reason}\`; hintText.style.color = currentPlayer === 'red' ? '#cc0000' : '#000'; clearSelection(); const pieceElement = document.querySelector(\`.piece\[data-row="${bestMove.from.row}"\]\[data-col="${bestMove.from.col}"\]\`); if (pieceElement) { pieceElement.classList.add('hint'); } } // 深度评估移动 function evaluateMoveDeep(fromRow, fromCol, toRow, toCol, depth) { if (depth === 0) return 0; const piece = board\[fromRow\]\[fromCol\]; const targetPiece = board\[toRow\]\[toCol\]; let score = 0; const pieceValues = { \[PIECE_TYPES.BING\]: 10, \[PIECE_TYPES.PAO\]: 30, \[PIECE_TYPES.MA\]: 30, \[PIECE_TYPES.XIANG\]: 20, \[PIECE_TYPES.SHI\]: 20, \[PIECE_TYPES.JU\]: 50, \[PIECE_TYPES.SHUAI\]: 1000 }; if (targetPiece) { score += pieceValues\[targetPiece.type\] \|\| 0; } const originalBoard = board.map(row =\> row.map(cell =\> cell ? {...cell} : null)); const originalGameOver = gameOver; board\[toRow\]\[toCol\] = piece; board\[fromRow\]\[fromCol\] = null; let canBeCaptured = false; let captureValue = 0; for (let row = 0; row \< BOARD_HEIGHT; row++) { for (let col = 0; col \< BOARD_WIDTH; col++) { const enemyPiece = board\[row\]\[col\]; if (enemyPiece \&\& enemyPiece.player !== currentPlayer) { if (isValidMove(row, col, toRow, toCol)) { canBeCaptured = true; const value = pieceValues\[piece.type\] \|\| 0; captureValue = Math.max(captureValue, value); } } } } if (canBeCaptured) { score -= captureValue \* 0.8; } if (depth \> 1 \&\& !gameOver) { const nextPlayer = currentPlayer === 'red' ? 'black' : 'red'; const nextMoves = getAllPossibleMoves(nextPlayer); if (nextMoves.length \> 0) { let worstResponse = Infinity; for (const nextMove of nextMoves.slice(0, 10)) { const nextScore = evaluateMoveDeep(nextMove.from.row, nextMove.from.col, nextMove.to.row, nextMove.to.col, depth - 1); worstResponse = Math.min(worstResponse, nextScore); } score += worstResponse \* 0.3; } } board = originalBoard; gameOver = originalGameOver; if (piece.player === 'red' \&\& toRow \< fromRow) score += 2; if (piece.player === 'black' \&\& toRow \> fromRow) score += 2; if (toRow \>= 2 \&\& toRow \<= 7 \&\& toCol \>= 2 \&\& toCol \<= 6) { score += 3; } if (piece.type === PIECE_TYPES.SHUAI) { const inPalace = piece.player === 'red' ? (toRow \>= 7 \&\& toRow \<= 9 \&\& toCol \>= 3 \&\& toCol \<= 5) : (toRow \>= 0 \&\& toRow \<= 2 \&\& toCol \>= 3 \&\& toCol \<= 5); if (!inPalace) score -= 50; } return score; } // 开始游戏 function startGame(mode) { gameMode = mode; document.getElementById('modeSelection').style.display = 'none'; document.getElementById('gameMode').textContent = mode === 'ai' ? '(AI对战)' : '(双人对战)'; if (mode === 'ai' \&\& currentPlayer === 'black') { setTimeout(() =\> aiMove(), 1000); } } // 更新状态显示 function updateStatus() { const statusElement = document.getElementById('currentPlayer'); statusElement.textContent = currentPlayer === 'red' ? '红方' : '黑方'; statusElement.style.color = currentPlayer === 'red' ? '#cc0000' : '#000'; } // 重置游戏 function resetGame() { if (confirm('确定要重新开始游戏吗?')) { gameOver = false; currentPlayer = 'red'; selectedPiece = null; moveHistory = \[\]; aiThinking = false; document.getElementById('moveList').innerHTML = ''; document.getElementById('hintText').textContent = ''; initBoard(); renderBoard(); updateStatus(); if (gameMode === 'ai' \&\& currentPlayer === 'black') { setTimeout(() =\> aiMove(), 1000); } } } // 显示规则 function showRules() { alert(\`象棋规则: 1. 帅(将):只能在九宫格内移动,每次只能走一格 2. 士(仕):只能在九宫格内斜走一格 3. 象(相):走田字,不能过河,不能塞象眼 4. 马:走日字,不能蹩马腿 5. 车:直线行走,格数不限 6. 炮:直线行走,吃子时需要隔一个棋子 7. 兵(卒):过河前只能向前,过河后可以左右移动 操作说明: - 点击棋子选中,再点击目标位置移动 - 点击"悔棋"按钮可以撤销上一步 - 点击"提示走法"可以获得AI建议(考虑3步) - AI对战模式下,AI会自动走棋 吃掉对方的将/帅即可获胜!\`); } // 窗口大小改变时重新渲染 window.addEventListener('resize', () =\> { if (board.length \> 0) { renderBoard(); } }); // 初始化游戏 window.onload = function() { initBoard(); renderBoard(); updateStatus(); }; \ \ \ \ \ \ \ \ \中国象棋\ \ /\* 一. 基础样式 - 添加响应式设计 \*/ body { display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; padding: 10px; background-color: #f0e6d2; font-family: Arial, sans-serif; box-sizing: border-box; } .game-container { text-align: center; max-width: 100vw; overflow-x: auto; } /\* 二. 模式选择弹窗 \*/ .mode-selection { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.7); display: flex; justify-content: center; align-items: center; z-index: 1000; } .mode-box { background-color: white; padding: 30px; border-radius: 10px; box-shadow: 0 0 20px rgba(0,0,0,0.5); max-width: 90vw; } .mode-box h2 { margin-bottom: 20px; color: #8b4513; } .mode-button { display: block; width: 200px; margin: 10px auto; padding: 15px; font-size: 18px; background-color: #8b4513; color: white; border: none; border-radius: 5px; cursor: pointer; } .mode-button:hover { background-color: #a0522d; } /\* 三. 响应式棋盘样式 \*/ .board { position: relative; width: 90vw; max-width: 600px; height: calc(90vw \* 1.1); max-height: 660px; background-color: #f9d4b4; border: 3px solid #8b4513; margin: 20px auto; box-shadow: 0 0 20px rgba(0,0,0,0.3); } @media (min-width: 768px) { .board { width: 600px; height: 660px; } } /\* 四. 棋子样式 \*/ .piece { position: absolute; border-radius: 50%; font-weight: bold; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; z-index: 10; user-select: none; } .piece.red { background: radial-gradient(circle at 30% 30%, #ff6b6b, #cc0000); color: #fff; border: 2px solid #990000; box-shadow: 2px 2px 4px rgba(0,0,0,0.3); } .piece.black { background: radial-gradient(circle at 30% 30%, #666, #000); color: #fff; border: 2px solid #000; box-shadow: 2px 2px 4px rgba(0,0,0,0.3); } .piece.selected { transform: scale(1.1); box-shadow: 0 0 20px #ffff00, 2px 2px 4px rgba(0,0,0,0.3); border-color: #ffff00; } .piece.hint { animation: pulse 1s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.15); } 100% { transform: scale(1); } } /\* 五. 棋盘网格样式 \*/ .grid { position: absolute; cursor: pointer; z-index: 1; } /\* 六. 棋盘线条响应式 \*/ .board-lines { position: absolute; top: 5vw; left: 5vw; width: 80vw; max-width: 540px; height: calc(80vw \* 1.11); max-height: 600px; } @media (min-width: 768px) { .board-lines { top: 30px; left: 30px; width: 540px; height: 600px; } } .horizontal-line { position: absolute; width: 80vw; max-width: 540px; height: 1px; background-color: #000; } @media (min-width: 768px) { .horizontal-line { width: 540px; } } .vertical-line { position: absolute; width: 1px; height: calc(80vw \* 1.11); max-height: 600px; background-color: #000; } @media (min-width: 768px) { .vertical-line { height: 600px; } } .river { position: absolute; top: calc(45vw - 5vw); left: 5vw; width: 80vw; max-width: 540px; height: 10vw; max-height: 60px; background-color: rgba(135, 206, 235, 0.3); pointer-events: none; } @media (min-width: 768px) { .river { top: 270px; left: 30px; width: 540px; height: 60px; } } /\* 七. 控制按钮样式 \*/ .controls { margin-top: 20px; display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; } button { padding: 10px 20px; font-size: 16px; background-color: #8b4513; color: white; border: none; border-radius: 5px; cursor: pointer; margin: 5px; } button:hover { background-color: #a0522d; } /\* 八. 状态显示样式 \*/ .status { margin-top: 10px; font-size: 18px; font-weight: bold; } .hint-text { margin-top: 10px; font-size: 14px; color: #666; min-height: 20px; } /\* 九. 走棋记录样式 \*/ .move-history { margin-top: 20px; max-height: 150px; overflow-y: auto; background-color: rgba(255, 255, 255, 0.5); padding: 10px; border-radius: 5px; width: 90vw; max-width: 300px; margin-left: auto; margin-right: auto; } .move-item { font-size: 12px; margin: 2px 0; padding: 2px 5px; background-color: rgba(255, 255, 255, 0.8); border-radius: 3px; } .move-item.red { color: #cc0000; } .move-item.black { color: #000; } /\* 十. 数据排行按钮样式 \*/ .stats-btn { display: inline-block; padding: 6px 14px; background: #f9d4b4; border: 2px solid #8b4513; border-radius: 6px; color: #8b4513; text-decoration: none; font-weight: bold; margin-left: 20px; transition: all 0.3s ease; } .stats-btn:hover { background: #8b4513; color: #fff; } \ \ \ \

相关推荐
WenGyyyL2 小时前
微信小程序开发——第二章:微信小程序开发环境搭建
开发语言·python·微信小程序
循环过三天2 小时前
3.2、Python-元组
开发语言·python
Q_Q5110082853 小时前
python+django/flask的篮球馆/足球场地/运动场地预约系统
spring boot·python·django·flask·node.js·php
云雾J视界3 小时前
AI驱动半导体良率提升:基于机器学习的晶圆缺陷分类系统搭建
人工智能·python·机器学习·智能制造·数据驱动·晶圆缺陷分类
朝凡FR3 小时前
AIShareTxt入门:快速准确高效的为金融决策智能体提供股票技术指标上下文
python·ai编程
Q_Q5110082853 小时前
python+django/flask的城市供水管网爆管预警系统-数据可视化
spring boot·python·django·flask·node.js·php
小白学大数据5 小时前
增量爬取策略:如何持续监控贝壳网最新成交数据
爬虫·python·性能优化
@forever@10 小时前
【JAVA】LinkedList与链表
java·python·链表
程序员爱钓鱼11 小时前
Python编程实战:面向对象与进阶语法——类型注解与代码规范(PEP 8)
后端·python·ipython