当前位置: 首页 > news >正文

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;

            width: 8.33vw;

            max-width: 50px;

            height: 8.33vw;

            max-height: 50px;

            border-radius: 50%;

            font-size: 4vw;

            max-font-size: 24px;

            font-weight: bold;

            display: flex;

            align-items: center;

            justify-content: center;

            cursor: pointer;

            transition: all 0.3s ease;

            z-index: 10;

            user-select: none;

        }

        

        @media (min-width: 768px) {

            .piece {

                width: 50px;

                height: 50px;

                font-size: 24px;

            }

        }

        

        .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;

            width: 10vw;

            max-width: 60px;

            height: 10vw;

            max-height: 60px;

            cursor: pointer;

            z-index: 1;

        }

        

        @media (min-width: 768px) {

            .grid {

                width: 60px;

                height: 60px;

            }

        }

        

        /* 棋盘线条响应式 */

        .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;

        

        // 响应式尺寸计算

        function getCellSize() {

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

            const boardWidth = board.offsetWidth;

            return boardWidth / BOARD_WIDTH;

        }

        

        function getPieceSize() {

            const cellSize = getCellSize();

            return cellSize * 0.833; // 棋子占格子的83.3%

        }

        

        // 棋子类型

        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 renderBoard() {

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

            const cellSize = getCellSize();

            const pieceSize = getPieceSize();

            

            // 清除现有的棋子和格子

            const existingPieces = boardElement.querySelectorAll('.piece, .grid');

            existingPieces.forEach(el => el.remove());

            

            // 创建点击格子

            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 + (cellSize - pieceSize) / 2}px`;

                    grid.style.top = `${row * cellSize + (cellSize - pieceSize) / 2}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);

                }

            }

            

            // 创建棋子

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

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

                    const piece = board[row][col];

                    if (piece) {

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

                        pieceElement.className = `piece ${piece.player}`;

                        pieceElement.textContent = piece.type;

                        pieceElement.style.left = `${col * cellSize + (cellSize - pieceSize) / 2}px`;

                        pieceElement.style.top = `${row * cellSize + (cellSize - pieceSize) / 2}px`;

                        pieceElement.style.width = `${pieceSize}px`;

                        pieceElement.style.height = `${pieceSize}px`;

                        pieceElement.dataset.row = row;

                        pieceElement.dataset.col = col;

                        pieceElement.onclick = (e) => {

                            e.stopPropagation();

                            handlePieceClick(row, col);

                        };

                        boardElement.appendChild(pieceElement);

                    }

                }

            }

        }

        

// 处理棋子点击

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);

            // 吃完若轮到 AI,立即思考

            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);

                    // 吃完若轮到 AI,立即思考

                    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);

                

                // AI模式下,如果轮到AI走棋

                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); // 思考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() {

            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

            };

            

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

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

                    const piece = board[row][col];

                    if (piece) {

                        const value = pieceValues[piece.type] || 0;

                        if (piece.player === 'black') {

                            score += value;

                        } else {

                            score -= value;

                        }

                    }

                }

            }

            

            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 (rowDiff > 0) return false;

                if (fromRow > 4) {

                    // 过河后可以左右移动

                    return (rowDiff === -1 && colDiff === 0) || (rowDiff === 0 && colDiff === 1);

                } else {

                    // 未过河只能向前

                    return rowDiff === -1 && colDiff === 0;

                }

            } else {

                // 黑方兵向上移动

                if (rowDiff < 0) return false;

                if (fromRow < 5) {

                    // 过河后可以左右移动

                    return (rowDiff === 1 && colDiff === 0) || (rowDiff === 0 && colDiff === 1);

                } else {

                    // 未过河只能向前

                    return rowDiff === 1 && colDiff === 0;

                }

            }

        }

        

        // 移动棋子

        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('确定要悔棋吗?')) {

                // AI模式下需要撤销两步(玩家和AI各一步)

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

                            // 深度评估这个移动(考虑3步)

                            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();

        };

    </script>

</body>

</html>

 

http://www.dtcms.com/a/581015.html

相关文章:

  • rom定制系列------红米note10 5G版camellia_OS系统安卓14批量线刷双版root 原生等【二】
  • 【高阶数据结构学习笔记】高阶数据结构之B树B+树B*树
  • 基于Qt框架开发多功能视频播放器
  • 【FPGA】现场可编程门阵列
  • Android设备推送traceroute命令
  • SuperMap iObjects .NET 11i 二次开发(十七)—— 叠加分析之擦除
  • Verilog局部参数localparam
  • RS485总线通讯中一体化电机的PDO报文分析
  • 【MCU ATS323X】PM电源管理系统
  • 建网站一定要备案吗学生个人网站建设方案书框架栏目
  • 做兼职的网站都有哪些工作内容深圳建设网站首页
  • 【深入浅出】:人工智能从入门到实战
  • 日内瓦传动装置?不就是我们叫的间歇结构吗?
  • 基于SpringBoot的乡村支教全流程数字化管理平台 基于Django的智慧乡村支教综合管理系统 基于php与智能问答的乡村支教服务平台
  • dp|中位数贪心+裴蜀定理
  • 高集成低功耗RISC-V SoC收发芯片CI24R02
  • 中国科大创建乾坤网络精确求解多电子薛定谔方程
  • 世界著名的设计公司百度优化 几个网站内容一样
  • 【Debug】ChatGPT - Cli CodeX 登录报错 409 Route Error (409 ): 解决方案
  • C11期作业23(08.30)
  • 【JavaWeb】Tlias后台管理系统
  • 硬件工程师-基础知识电阻(四)
  • 网站设计建设那家好门户网站开发项目
  • 视频号下载视频思路
  • Visual Basic 手工制作工具栏
  • 电话交换机软件和录音转文字服务器部署笔记
  • 常州建站程序衡水高端网站建设
  • Java五大排序算法详解与实现
  • [特殊字符] Vue3 + WebView 双端通信桥:用 TypeScript 构建高可维护的 JSBridge 与 JSSDK
  • 自然科学笔记-微积分