五子棋游戏卡密验证

2250898553 2025-10-31 4 次下载
详细描述
实时预览
源代码
<!-- 本DIY代码来自于 https://diy.zhongzhipian.top -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>五子棋验证卡密</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif;
            background-color: #f5f5f5;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 15px 0;
            min-height: 100vh;
            width: 100%;
            overflow-x: hidden;
        }

        #title {
            font-size: clamp(1.2rem, 3vw, 1.5rem);
            color: #333;
            margin: 0 15px 8px;
            text-align: center;
            width: 100%;
            max-width: 90%;
        }
        #notice {
            font-size: clamp(0.9rem, 2vw, 1rem);
            color: #666;
            margin: 0 15px 12px;
            text-align: center;
            width: 100%;
            max-width: 90%;
        }

        #difficulty-tip {
            font-size: clamp(0.85rem, 2vw, 1rem);
            color: #e63946;
            margin: 0 15px 10px;
            font-weight: bold;
            text-align: center;
            width: 100%;
            max-width: 90%;
            padding: 5px 10px;
            background-color: rgba(230, 57, 70, 0.05);
            border-radius: 4px;
        }

        #chess-color-tip {
            font-size: clamp(0.8rem, 1.8vw, 0.9rem);
            color: #e63946;
            margin: 0 15px 10px;
            font-weight: bold;
            text-align: center;
            width: 100%;
            max-width: 90%;
            line-height: 1.4;
            display: none;
        }

        #capital-tip {
            font-size: clamp(0.8rem, 1.8vw, 0.9rem);
            color: #f77f00;
            margin: 8px 15px;
            font-weight: bold;
            display: none;
            animation: flash 0.8s infinite alternate;
            text-align: center;
            width: 100%;
            max-width: 90%;
        }
        @keyframes flash {
            from {opacity: 1; transform: scale(1);}
            to {opacity: 0.7; transform: scale(1.03);}
        }

        #chess-container {
            background-color: #d18b47;
            padding: clamp(6px, 1.5vw, 8px);
            border-radius: 5px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            width: calc(100vw - 30px);
            height: calc(100vw - 30px);
            max-height: calc(100vh - 200px);
            min-width: 240px;
            min-height: 240px;
            margin: 0 auto;
            display: none;
        }
        #chess-board {
            display: grid;
            grid-template-columns: repeat(15, 1fr);
            grid-template-rows: repeat(15, 1fr);
            gap: 1px;
            width: 100%;
            height: 100%;
        }
        .chess-cell {
            position: relative;
            cursor: pointer;
        }
        .chess-cell::before {
            content: "";
            position: absolute;
            width: 100%;
            height: 1.5px;
            background-color: #333;
            top: 50%;
            left: 0;
            transform: translateY(-50%);
        }
        .chess-cell::after {
            content: "";
            position: absolute;
            width: 1.5px;
            height: 100%;
            background-color: #333;
            left: 50%;
            top: 0;
            transform: translateX(-50%);
        }

        .chess-black, .chess-white {
            position: absolute;
            width: 82%;
            height: 82%;
            border-radius: 50%;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 1;
            border: 1px solid rgba(0,0,0,0.2);
            transition: all 0.3s ease;
        }
        .chess-black {
            background-color: #000;
            box-shadow: inset 0 0 3px rgba(255,255,255,0.1);
        }
        .chess-white {
            background-color: #fff;
            border: 1px solid #bbb;
            box-shadow: 0 0 2px rgba(0,0,0,0.1);
        }

        /* 高亮棋子样式 */
        .chess-black.win-highlight {
            background: linear-gradient(45deg, #000, #ff6b6b);
            box-shadow: 0 0 15px #ff6b6b, inset 0 0 5px rgba(255,255,255,0.3);
            transform: translate(-50%, -50%) scale(1.1);
            border: 2px solid #ffeb3b;
        }

        .chess-white.win-highlight {
            background: linear-gradient(45deg, #fff, #ff6b6b);
            box-shadow: 0 0 15px #ff6b6b, 0 0 5px rgba(0,0,0,0.3);
            transform: translate(-50%, -50%) scale(1.1);
            border: 2px solid #ffeb3b;
        }

        .last-user-move {
            position: absolute;
            width: 40%;
            height: 40%;
            border: 2px solid #e63946;
            border-radius: 50%;
            background: transparent;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 2;
            pointer-events: none;
        }

        .last-ai-move {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 2;
            pointer-events: none;
            font-size: clamp(8px, 2vw, 12px);
            font-weight: bold;
            color: #fff;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
        }
        /* 修复:白棋AI标记颜色问题 */
        .chess-white .last-ai-move {
            color: #1d3557;
            text-shadow: 1px 1px 2px rgba(255,255,255,0.8);
        }

        #win-tip {
            font-size: clamp(0.9rem, 2vw, 1.1rem);
            color: #e63946;
            margin: 15px 15px 8px;
            font-weight: bold;
            display: none;
            text-align: center;
            line-height: 1.5;
            width: 100%;
            max-width: 90%;
        }

        .restart-btn {
            padding: clamp(8px, 2vw, 12px) clamp(20px, 5vw, 28px);
            background-color: #1d3557;
            color: #fff;
            border: none;
            border-radius: 4px;
            font-size: clamp(0.9rem, 2vw, 1rem);
            cursor: pointer;
            transition: background-color 0.3s;
            margin-top: 8px;
        }
        .restart-btn:hover {
            background-color: #0a1a2f;
        }
        #restart-btn-container {
            display: none;
            justify-content: center;
            margin: 0 15px 15px;
            width: 100%;
        }

        #verify-section {
            background-color: #fff;
            padding: clamp(15px, 4vw, 20px);
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            width: calc(100vw - 30px);
            max-width: 500px;
            display: none;
            margin: 10px auto 15px;
        }
        .form-group {
            margin-bottom: 15px;
            width: 100%;
        }
        .form-group label {
            display: block;
            font-size: clamp(0.9rem, 2vw, 1rem);
            color: #333;
            margin-bottom: 6px;
        }
        .form-group input {
            width: 100%;
            padding: clamp(9px, 2.2vw, 11px);
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: clamp(0.85rem, 1.8vw, 0.95rem);
            box-sizing: border-box;
        }

        .btn-group {
            display: flex;
            gap: clamp(8px, 2vw, 12px);
            margin-top: 8px;
            width: 100%;
        }
        .btn {
            flex: 1;
            padding: clamp(9px, 2.2vw, 11px);
            border: none;
            border-radius: 4px;
            font-size: clamp(0.85rem, 1.8vw, 0.95rem);
            cursor: pointer;
            transition: background-color 0.3s;
        }
        #Query_Trial {
            background-color: #457b9d;
            color: #fff;
        }
        #Query_Trial:hover {
            background-color: #1d3557;
        }
        #Verify {
            background-color: #1d3557;
            color: #fff;
        }
        #Verify:hover {
            background-color: #0a1a2f;
        }
        #Pay {
            width: 100%;
            background-color: #e63946;
            color: #fff;
            margin-top: 10px;
        }
        #Pay:hover {
            background-color: #c1121f;
        }
    </style>
</head>
<body>
    <h1 id="title"></h1>
    <p id="notice"></p>
    <!-- 难度提示:必须保留,显示识别结果 -->
    <div id="difficulty-tip">正在识别难度...</div>
    <div id="chess-color-tip">
        你使用的棋子:<span style="color: #000; border: 1px solid #ccc; padding: 2px 6px; border-radius: 3px; font-size: 0.85rem;">黑色</span> 
        | <span style="color:#e63946">你的落棋:棋内红色圈</span> 
        | <span style="color:#1d3557">AI落棋:棋内"AI"文字</span>
    </div>
    
    <div id="capital-tip">⚠️ AI触发「资本做局」!替换你[危险等级]的最危险棋子(该棋子转为AI所有) ⚠️</div>

    <div id="chess-container">
        <div id="chess-board"></div>
    </div>

    <div id="win-tip">AI获胜,点击下方按钮重新开局</div>
    <div id="restart-btn-container">
        <button id="restart-btn" class="restart-btn" onclick="restartGame()">确认重新开局</button>
    </div>

    <!-- 查码按钮绑定 -->
    <div id="verify-section">
        <div class="form-group">
            <label for="card-code">请输入卡密</label>
            <input type="text" id="card-code" placeholder="例如:ABC123-DEF456-GHI789" />
        </div>
        <div class="btn-group">
            <button class="btn" id="Query_Trial" onclick="Call_Query_Trial(document.getElementById('card-code').value)"></button>
            <button class="btn" id="Verify" onclick="Call_Verify(document.getElementById('card-code').value)">验证</button>
        </div>
        <button class="btn" id="Pay" onclick="Call_Pay()"></button>
    </div>

    <script>
        let gameState = {
            size: 15,
            userColor: Math.random() > 0.5 ? "black" : "white",
            aiColor: "",
            currentPlayer: "",
            chessData: [],
            userChessPositions: [], 
            replacedUserPositions: new Set(), 
            isGameOver: false,
            lastUserMove: null,
            lastAIMove: null,
            difficulty: "中", // 默认难度
            capitalGameRate: {
                level1: 0.01,
                level2: 0.05,
                level3: 0.15,
                level4: 0.3,
                level5: 0.5
            },
            winHighlightPositions: [], // 存储获胜棋子的位置
            dom: {
                chessBoard: document.getElementById("chess-board"),
                winTip: document.getElementById("win-tip"),
                restartBtnContainer: document.getElementById("restart-btn-container"),
                restartBtn: document.getElementById("restart-btn"),
                verifySection: document.getElementById("verify-section"),
                chessColorTip: document.getElementById("chess-color-tip"),
                payBtn: document.getElementById("Pay"),
                capitalTip: document.getElementById("capital-tip"),
                title: document.getElementById("title"),
                notice: document.getElementById("notice"),
                queryTrialBtn: document.getElementById("Query_Trial"),
                difficultyTip: document.getElementById("difficulty-tip"),
                chessContainer: document.getElementById("chess-container")
            }
        };
        gameState.aiColor = gameState.userColor === "black" ? "white" : "black";
        gameState.currentPlayer = gameState.userColor === "black" ? "user" : "ai";
        gameState.chessData = Array(gameState.size).fill().map(() => Array(gameState.size).fill(null));

        // ------------------------------
        // 恢复核心:难度识别逻辑(从标题提取<强>/<中>/<弱>/<关>)
        // ------------------------------
        function extractDifficultyFromTitle(title) {
            // 匹配标题中的难度标记(兼容带空格格式,如< 强 >)
            const difficultyMatch = title.match(/<\s*(\S+)\s*>/);
            const validDifficulties = ["强", "中", "弱", "关"];
            
            if (difficultyMatch && difficultyMatch[1] && validDifficulties.includes(difficultyMatch[1])) {
                const difficulty = difficultyMatch[1];
                // 清理标题:移除难度标记,避免显示在页面上
                const cleanTitle = title.replace(/<\s*\S+\s*>/, "").trim();
                console.log("难度识别成功:", difficulty, "| 清理后标题:", cleanTitle);
                return { difficulty, cleanTitle, success: true };
            } else {
                console.log("未识别到有效难度标记,默认难度=中");
                return { difficulty: "中", cleanTitle: title.trim(), success: false };
            }
        }

        // 恢复:难度规则(强→中→弱→关逐级递减)
        function getDifficultyRule(difficulty) {
            const ruleMap = {
                "强": { hasCapitalGame: true, aiAttack: true, aiDefend: true, needPlayGame: true, desc: "AI有资本做局+主动进攻+防守(最难)" },
                "中": { hasCapitalGame: false, aiAttack: true, aiDefend: true, needPlayGame: true, desc: "AI无资本做局+主动进攻+防守(比强简单)" },
                "弱": { hasCapitalGame: false, aiAttack: false, aiDefend: "nearOnly", needPlayGame: true, desc: "AI无资本做局+仅附近防守(比中简单)" },
                "关": { hasCapitalGame: false, aiAttack: false, aiDefend: false, needPlayGame: false, desc: "无需下棋,直接输卡密(最简单)" }
            };
            return ruleMap[difficulty] || ruleMap["中"];
        }

        // ------------------------------
        // 修复:整合查码初始化和难度识别,不冲突
        // ------------------------------
        function initPanGolinData() {
            gameState.dom.difficultyTip.innerHTML = "正在识别难度...";
            
            try {
                // 1. 先获取PanGolin原始标题(用于难度识别)
                let originalTitle = "";
                if (typeof PanGolin !== "undefined" && typeof PanGolin.GetTitle === "function") {
                    originalTitle = PanGolin.GetTitle() || "五子棋验证卡密系统";
                } else {
                    originalTitle = "五子棋验证卡密系统";
                }

                // 2. 执行难度识别:提取难度+清理标题
                const { difficulty, cleanTitle, success } = extractDifficultyFromTitle(originalTitle);
                gameState.difficulty = difficulty;
                const difficultyRule = getDifficultyRule(difficulty);

                // 3. 严格按用户提供的JS更新标题、公告、查码按钮文本
                document.getElementById("title").innerHTML = cleanTitle; // 用清理后的标题(移除难度标记)
                document.getElementById("notice").innerHTML = (typeof PanGolin !== "undefined" && PanGolin.GetNotice) ? PanGolin.GetNotice() : "完成五子棋获胜,即可解锁卡密验证功能";
                document.getElementById("Query_Trial").innerHTML = (typeof PanGolin !== "undefined" && typeof PanGolin.Is_Trial !== "undefined") ? (PanGolin.Is_Trial() == true ? "试用" : "查码") : "查码";
                document.getElementById("Pay").style.display = (typeof PanGolin !== "undefined" && typeof PanGolin.Is_Pay !== "undefined") ? (PanGolin.Is_Pay() == true ? "block" : "none") : "none";

                // 4. 更新难度提示(让用户看到识别结果)
                if (success) {
                    gameState.dom.difficultyTip.innerHTML = `✅ 难度识别成功:${difficulty} | ${difficultyRule.desc}`;
                } else {
                    gameState.dom.difficultyTip.innerHTML = `⚠️ 未识别到难度标记(需含<强>/<中>/<弱>/<关>)| 默认难度:中 | ${difficultyRule.desc}`;
                }

                // 5. 支付按钮文本兜底
                gameState.dom.payBtn.innerHTML = (typeof PanGolin !== "undefined" && PanGolin.GetPayText) ? PanGolin.GetPayText() : "前往支付";

                // 6. 根据难度规则适配UI(棋盘/卡密区显示)
                adaptUIByRule(difficultyRule);
            } catch (e) {
                // 异常兜底:保留难度识别和查码功能
                gameState.difficulty = "中";
                const defaultRule = getDifficultyRule("中");
                document.getElementById("title").innerHTML = "五子棋验证卡密系统";
                document.getElementById("notice").innerHTML = "完成五子棋获胜,即可解锁卡密验证功能";
                document.getElementById("Query_Trial").innerHTML = "查码";
                document.getElementById("Pay").style.display = "none";
                gameState.dom.payBtn.innerHTML = "前往支付";
                gameState.dom.difficultyTip.innerHTML = `❌ 初始化出错 | 默认难度:中 | ${defaultRule.desc}`;
                adaptUIByRule(defaultRule);
                console.error("PanGolin初始化异常:", e);
            }
        }

        // 恢复:根据难度规则适配UI
        function adaptUIByRule(rule) {
            const { chessContainer, verifySection, chessColorTip } = gameState.dom;
            if (rule.needPlayGame) {
                // 需要下棋:显示棋盘,隐藏卡密区
                chessContainer.style.display = "block";
                verifySection.style.display = "none";
                chessColorTip.style.display = "block";
            } else {
                // 无需下棋(关难度):隐藏棋盘,显示卡密区
                chessContainer.style.display = "none";
                verifySection.style.display = "block";
                chessColorTip.style.display = "none";
            }
            gameState.dom.capitalTip.style.display = "none";
            gameState.dom.restartBtnContainer.style.display = "none";
        }

        // 修复:更新落棋标记 - 确保每次落子后都正确更新标记
        function updateLastUserMove(pos) {
            // 清除所有用户标记
            const oldUserMarks = document.querySelectorAll(".last-user-move");
            oldUserMarks.forEach(mark => mark.remove());
            
            gameState.lastUserMove = pos;
            if (!pos) return;
            
            const cell = document.querySelector(`.chess-cell[data-row="${pos.row}"][data-col="${pos.col}"]`);
            if (!cell) return;
            
            const userChess = cell.querySelector(`.chess-${gameState.userColor}`);
            if (userChess) {
                const userMark = document.createElement("span");
                userMark.className = "last-user-move";
                userChess.appendChild(userMark);
            }
        }

        function updateLastAIMove(pos) {
            // 清除所有AI标记
            const oldAIMarks = document.querySelectorAll(".last-ai-move");
            oldAIMarks.forEach(mark => mark.remove());
            
            gameState.lastAIMove = pos;
            if (!pos) return;
            
            const cell = document.querySelector(`.chess-cell[data-row="${pos.row}"][data-col="${pos.col}"]`);
            if (!cell) return;
            
            const aiChess = cell.querySelector(`.chess-${gameState.aiColor}`);
            if (aiChess) {
                const aiMark = document.createElement("span");
                aiMark.className = "last-ai-move";
                aiMark.textContent = "AI";
                aiChess.appendChild(aiMark);
            }
        }

        // 页面初始化:同时执行难度识别和查码初始化
        function initPage() {
            initPanGolinData(); // 一次调用,同时完成难度识别和查码配置
            const currentRule = getDifficultyRule(gameState.difficulty);
            if (currentRule.needPlayGame) {
                renderChessBoard();
                if (gameState.currentPlayer === "ai") {
                    setTimeout(() => aiFirstPlace(), 300);
                }
            }
        }

        function renderChessBoard() {
            gameState.dom.chessBoard.innerHTML = "";
            for (let i = 0; i < gameState.size; i++) {
                for (let j = 0; j < gameState.size; j++) {
                    const cell = document.createElement("div");
                    cell.className = "chess-cell";
                    cell.dataset.row = i;
                    cell.dataset.col = j;
                    cell.onclick = () => userPlaceChess(i, j);
                    gameState.dom.chessBoard.appendChild(cell);
                }
            }
            // 重新渲染已有的棋子
            for (let i = 0; i < gameState.size; i++) {
                for (let j = 0; j < gameState.size; j++) {
                    if (gameState.chessData[i][j]) {
                        const cell = document.querySelector(`.chess-cell[data-row="${i}"][data-col="${j}"]`);
                        if (cell) {
                            const chessDom = document.createElement("div");
                            chessDom.className = `chess-${gameState.chessData[i][j]}`;
                            
                            // 如果是获胜棋子,添加高亮样式
                            const isWinPiece = gameState.winHighlightPositions.some(pos => 
                                pos.row === i && pos.col === j
                            );
                            if (isWinPiece) {
                                chessDom.classList.add('win-highlight');
                            }
                            
                            cell.appendChild(chessDom);
                        }
                    }
                }
            }
            // 恢复标记 - 确保标记正确显示
            if (gameState.lastUserMove) {
                updateLastUserMove(gameState.lastUserMove);
            }
            if (gameState.lastAIMove) {
                updateLastAIMove(gameState.lastAIMove);
            }
        }

        // 弱难度:仅用户落棋附近防守
        function getUserNearEmptyPositions(lastUserPos) {
            const emptyPositions = new Set();
            if (!lastUserPos) return [];
            const { row: uRow, col: uCol } = lastUserPos;
            // 仅遍历用户落棋周围1格(3x3范围)
            for (let i = uRow - 1; i <= uRow + 1; i++) {
                for (let j = uCol - 1; j <= uCol + 1; j++) {
                    if (isInBoard(i, j) && gameState.chessData[i][j] === null) {
                        emptyPositions.add(`${i}-${j}`);
                    }
                }
            }
            return Array.from(emptyPositions).map(str => ({ row: Number(str.split('-')[0]), col: Number(str.split('-')[1]) }));
        }

        // 基础工具函数
        function isReplacedPosition(row, col) {
            return gameState.replacedUserPositions.has(`${row}-${col}`);
        }
        function getUserValidChessCount() {
            return gameState.userChessPositions.length;
        }
        function isInBoard(row, col) {
            return row >= 0 && row < gameState.size && col >= 0 && col < gameState.size;
        }

        // 资本做局(仅强难度生效)
        function triggerCapitalGameByLevel(dangerInfo, nearEmptyPos) {
            const currentRule = getDifficultyRule(gameState.difficulty);
            if (!currentRule.hasCapitalGame) return null;

            const { level, desc } = dangerInfo;
            const targetLevel = Math.min(level, 5);
            let triggerRate = gameState.capitalGameRate[`level${targetLevel}`] || 0;
            if (Math.random() > triggerRate) return null;

            const mostDangerousPos = findMostDangerousUserChess(level, nearEmptyPos);
            if (!mostDangerousPos) return null;
            const { row: dRow, col: dCol } = mostDangerousPos;
            const cellDom = document.querySelector(`.chess-cell[data-row="${dRow}"][data-col="${dCol}"]`);

            const userChessDom = cellDom.querySelector(`.chess-${gameState.userColor}`);
            if (userChessDom) userChessDom.remove();
            gameState.userChessPositions = gameState.userChessPositions.filter(p => !(p.row === dRow && p.col === dCol));
            gameState.lastUserMove = null;

            gameState.replacedUserPositions.add(`${dRow}-${dCol}`);
            gameState.chessData[dRow][dCol] = gameState.aiColor;
            const aiChessDom = document.createElement("div");
            aiChessDom.className = `chess-${gameState.aiColor}`;
            cellDom.appendChild(aiChessDom);
            
            // 修复:资本做局后立即更新AI标记
            updateLastAIMove({ row: dRow, col: dCol });

            gameState.dom.capitalTip.innerHTML = `⚠️ AI触发「资本做局」!替换你${desc}的最危险棋子(该棋子转为AI所有) ⚠️`;
            gameState.dom.capitalTip.style.display = "block";

            if (checkWin(dRow, dCol, gameState.aiColor)) {
                gameState.isGameOver = true;
                gameState.dom.winTip.textContent = "AI触发资本做局后获胜,点击下方按钮重新开局";
                gameState.dom.winTip.style.display = "block";
                gameState.dom.restartBtnContainer.style.display = "flex";
            }

            return mostDangerousPos;
        }

        // AI决策(按难度规则)
        function aiDecision(dangerInfo, nearEmptyPos) {
            const currentRule = getDifficultyRule(gameState.difficulty);
            const { level, pos: dangerPos } = dangerInfo;

            if (level >= 2 && dangerPos) return dangerPos;

            if (currentRule.aiAttack) {
                // 强/中难度:主动进攻
                let attackPos = null;
                for (let i = 0; i < nearEmptyPos.length; i++) {
                    const p = nearEmptyPos[i];
                    if (canFormLiveThree(p.row, p.col, gameState.aiColor)) {
                        attackPos = p;
                        break;
                    }
                }
                if (!attackPos) {
                    for (let i = 0; i < nearEmptyPos.length; i++) {
                        const p = nearEmptyPos[i];
                        if (canFormLiveTwo(p.row, p.col, gameState.aiColor)) {
                            attackPos = p;
                            break;
                        }
                    }
                }
                return attackPos || (nearEmptyPos.length > 0 ? nearEmptyPos[0] : null);
            } else if (currentRule.aiDefend === "nearOnly") {
                // 弱难度:仅附近防守
                const lastUserPos = gameState.userChessPositions[gameState.userChessPositions.length - 1];
                const nearPos = getUserNearEmptyPositions(lastUserPos);
                return nearPos.length > 0 ? nearPos[0] : null;
            } else {
                return null;
            }
        }

        function canFormLiveTwo(row, col, color) {
            const dirs = [[0,1],[1,0],[1,1],[1,-1]];
            gameState.chessData[row][col] = color;
            let hasLiveTwo = false;
            for (let [dx, dy] of dirs) {
                let count = 1, leftEmpty = 0, rightEmpty = 0;
                for (let i = 1; i < 4; i++) {
                    const r = row + dx * i, c = col + dy * i;
                    if (!isInBoard(r, c)) break;
                    if (gameState.chessData[r][c] === color) count++;
                    else if (gameState.chessData[r][c] === null) { rightEmpty = 1; break; }
                    else break;
                }
                for (let i = 1; i < 4; i++) {
                    const r = row - dx * i, c = col - dy * i;
                    if (!isInBoard(r, c)) break;
                    if (gameState.chessData[r][c] === color) count++;
                    else if (gameState.chessData[r][c] === null) { leftEmpty = 1; break; }
                    else break;
                }
                if (count === 2 && (leftEmpty + rightEmpty) >= 2) { hasLiveTwo = true; break; }
            }
            gameState.chessData[row][col] = null;
            return hasLiveTwo;
        }

        function canFormLiveThree(row, col, color) {
            const dirs = [[0,1],[1,0],[1,1],[1,-1]];
            gameState.chessData[row][col] = color;
            let hasLiveThree = false;
            for (let [dx, dy] of dirs) {
                let count = 1, leftEmpty = 0, rightEmpty = 0;
                for (let i = 1; i < 5; i++) {
                    const r = row + dx * i, c = col + dy * i;
                    if (!isInBoard(r, c)) break;
                    if (gameState.chessData[r][c] === color) count++;
                    else if (gameState.chessData[r][c] === null) { rightEmpty = 1; break; }
                    else break;
                }
                for (let i = 1; i < 5; i++) {
                    const r = row - dx * i, c = col - dy * i;
                    if (!isInBoard(r, c)) break;
                    if (gameState.chessData[r][c] === color) count++;
                    else if (gameState.chessData[r][c] === null) { leftEmpty = 1; break; }
                    else break;
                }
                if (count === 3 && (leftEmpty + rightEmpty) >= 2) { hasLiveThree = true; break; }
            }
            gameState.chessData[row][col] = null;
            return hasLiveThree;
        }

        // 落子逻辑
        function aiFirstPlace() {
            const centerPos = { row: 7, col: 7 };
            const cell = document.querySelector(`.chess-cell[data-row="${centerPos.row}"][data-col="${centerPos.col}"]`);
            const aiChessDom = document.createElement("div");
            aiChessDom.className = `chess-${gameState.aiColor}`;
            cell.appendChild(aiChessDom);
            gameState.chessData[centerPos.row][centerPos.col] = gameState.aiColor;
            
            // 修复:AI先手时立即更新标记
            updateLastAIMove(centerPos);
            gameState.currentPlayer = "user";
        }

        function userPlaceChess(row, col) {
            const currentRule = getDifficultyRule(gameState.difficulty);
            if (!currentRule.needPlayGame) return;
            
            gameState.dom.capitalTip.style.display = "none";
            
            if (gameState.currentPlayer !== "user" || gameState.isGameOver || gameState.chessData[row][col] !== null) return;

            const cell = document.querySelector(`.chess-cell[data-row="${row}"][data-col="${col}"]`);
            const userChessDom = document.createElement("div");
            userChessDom.className = `chess-${gameState.userColor}`;
            cell.appendChild(userChessDom);

            gameState.chessData[row][col] = gameState.userColor;
            if (isReplacedPosition(row, col)) gameState.replacedUserPositions.delete(`${row}-${col}`);
            gameState.userChessPositions.push({ row, col });
            updateLastUserMove({ row, col });

            if (checkWin(row, col, gameState.userColor)) {
                gameState.isGameOver = true;
                gameState.dom.winTip.textContent = "恭喜!五子连珠获胜,可进行卡密验证";
                gameState.dom.winTip.style.display = "block";
                gameState.dom.restartBtnContainer.style.display = "none";
                gameState.dom.verifySection.style.display = "block";
                return;
            }

            if (isBoardFull()) {
                gameState.isGameOver = true;
                gameState.dom.winTip.textContent = "棋盘已满,点击下方按钮重新开局";
                gameState.dom.winTip.style.display = "block";
                gameState.dom.restartBtnContainer.style.display = "flex";
                return;
            }

            gameState.currentPlayer = "ai";
            setTimeout(() => {
                let nearEmptyPos;
                if (currentRule.aiDefend === "nearOnly") {
                    nearEmptyPos = getUserNearEmptyPositions({ row, col });
                } else {
                    nearEmptyPos = [];
                    gameState.userChessPositions.forEach(pos => {
                        const { row: uRow, col: uCol } = pos;
                        for (let i = uRow - 2; i <= uRow + 2; i++) {
                            for (let j = uCol - 2; j <= uCol + 2; j++) {
                                if (isInBoard(i, j) && gameState.chessData[i][j] === null) {
                                    nearEmptyPos.push({ row: i, col: j });
                                }
                            }
                        }
                    });
                }

                if (nearEmptyPos.length === 0) {
                    gameState.currentPlayer = "user";
                    return;
                }

                const dangerInfo = detectUserDangerLevel(nearEmptyPos);
                const replacedPos = triggerCapitalGameByLevel(dangerInfo, nearEmptyPos);
                if (replacedPos) {
                    gameState.currentPlayer = "user";
                    return;
                }

                const aiPos = aiDecision(dangerInfo, nearEmptyPos);
                if (aiPos) {
                    aiPlaceChess(aiPos.row, aiPos.col);
                } else {
                    // 修复:如果没有找到合适位置,随机选择一个位置
                    const randomPos = nearEmptyPos[Math.floor(Math.random() * nearEmptyPos.length)];
                    if (randomPos) {
                        aiPlaceChess(randomPos.row, randomPos.col);
                    } else {
                        gameState.currentPlayer = "user";
                    }
                }
            }, 1000);
        }

        function aiPlaceChess(row, col) {
            const cell = document.querySelector(`.chess-cell[data-row="${row}"][data-col="${col}"]`);
            if (!cell) return;
            
            const aiChessDom = document.createElement("div");
            aiChessDom.className = `chess-${gameState.aiColor}`;
            cell.appendChild(aiChessDom);

            gameState.chessData[row][col] = gameState.aiColor;
            
            // 修复:确保AI落子后立即更新标记
            updateLastAIMove({ row, col });

            if (checkWin(row, col, gameState.aiColor)) {
                gameState.isGameOver = true;
                gameState.dom.winTip.textContent = "AI获胜,点击下方按钮重新开局";
                gameState.dom.winTip.style.display = "block";
                gameState.dom.restartBtnContainer.style.display = "flex";
                return;
            }

            if (isBoardFull()) {
                gameState.isGameOver = true;
                gameState.dom.winTip.textContent = "棋盘已满,点击下方按钮重新开局";
                gameState.dom.winTip.style.display = "block";
                gameState.dom.restartBtnContainer.style.display = "flex";
                return;
            }
            
            gameState.currentPlayer = "user";
        }

        // 修复:游戏状态判定 - 确保正确检测五子连线并高亮棋子
        function checkWin(row, col, color) {
            const dirs = [[0,1],[1,0],[1,1],[1,-1]];
            for (let [dx, dy] of dirs) {
                let count = 1;
                let winPositions = [{row, col}];
                
                // 正向检测
                for (let i = 1; i < 5; i++) {
                    const r = row + dx * i, c = col + dy * i;
                    if (!isInBoard(r, c) || gameState.chessData[r][c] !== color) break;
                    count++;
                    winPositions.push({row: r, col: c});
                }
                // 反向检测
                for (let i = 1; i < 5; i++) {
                    const r = row - dx * i, c = col - dy * i;
                    if (!isInBoard(r, c) || gameState.chessData[r][c] !== color) break;
                    count++;
                    winPositions.unshift({row: r, col: c});
                }
                
                if (count >= 5) {
                    // 存储获胜棋子的位置
                    gameState.winHighlightPositions = winPositions.slice(0, 5);
                    // 高亮显示获胜棋子
                    highlightWinPieces(gameState.winHighlightPositions, color);
                    return true;
                }
            }
            return false;
        }

        // 高亮显示获胜棋子
        function highlightWinPieces(positions, color) {
            // 清除之前的高亮
            const oldHighlights = document.querySelectorAll('.win-highlight');
            oldHighlights.forEach(highlight => highlight.classList.remove('win-highlight'));
            
            // 为每个获胜棋子添加高亮样式
            positions.forEach(pos => {
                const cell = document.querySelector(`.chess-cell[data-row="${pos.row}"][data-col="${pos.col}"]`);
                if (cell) {
                    const chess = cell.querySelector(`.chess-${color}`);
                    if (chess) {
                        chess.classList.add('win-highlight');
                    }
                }
            });
        }

        function isBoardFull() {
            for (let i = 0; i < gameState.size; i++) {
                for (let j = 0; j < gameState.size; j++) {
                    if (gameState.chessData[i][j] === null) return false;
                }
            }
            return true;
        }

        // 修复:重启游戏 - 确保标记正确重置
        function restartGame() {
            // 清除高亮
            const oldHighlights = document.querySelectorAll('.win-highlight');
            oldHighlights.forEach(highlight => highlight.classList.remove('win-highlight'));
            
            // 重置游戏状态
            gameState.userColor = Math.random() > 0.5 ? "black" : "white";
            gameState.aiColor = gameState.userColor === "black" ? "white" : "black";
            gameState.currentPlayer = gameState.userColor === "black" ? "user" : "ai";
            gameState.chessData = Array(gameState.size).fill().map(() => Array(gameState.size).fill(null));
            gameState.userChessPositions = [];
            gameState.replacedUserPositions.clear();
            gameState.isGameOver = false;
            gameState.lastUserMove = null;
            gameState.lastAIMove = null;
            gameState.winHighlightPositions = [];

            gameState.dom.winTip.style.display = "none";
            gameState.dom.restartBtnContainer.style.display = "none";
            gameState.dom.capitalTip.style.display = "none";
            gameState.dom.verifySection.style.display = "none";

            // 重新渲染棋盘
            renderChessBoard();
            
            // AI先手时自动落子
            if (gameState.currentPlayer === "ai") {
                setTimeout(() => aiFirstPlace(), 300);
            }
        }

        // 危险等级检测
        function detectUserDangerLevel(nearEmptyPos) {
            const dirs = [[0,1],[1,0],[1,1],[1,-1]];
            let maxDangerLevel = 1, dangerPos = null, dangerDesc = `1颗棋子(共${getUserValidChessCount()}颗)`;
            if (getUserValidChessCount() === 0) return { level: 1, pos: null, desc: "0颗有效棋子" };
            
            nearEmptyPos.forEach(pos => {
                const { row, col } = pos;
                gameState.chessData[row][col] = gameState.userColor;
                for (let [dx, dy] of dirs) {
                    let count = 1, emptyCount = 0;
                    for (let i = 1; i < 6; i++) {
                        const r = row + dx * i, c = col + dy * i;
                        if (!isInBoard(r, c) || isReplacedPosition(r, c)) break;
                        if (gameState.chessData[r][c] === gameState.userColor) count++;
                        else if (gameState.chessData[r][c] === null) { emptyCount++; break; }
                        else break;
                    }
                    for (let i = 1; i < 6; i++) {
                        const r = row - dx * i, c = col - dy * i;
                        if (!isInBoard(r, c) || isReplacedPosition(r, c)) break;
                        if (gameState.chessData[r][c] === gameState.userColor) count++;
                        else if (gameState.chessData[r][c] === null) { emptyCount++; break; }
                        else break;
                    }
                    let currentLevel = 1, currentDesc = `1颗棋子(共${getUserValidChessCount()}颗)`;
                    if (count === 5) { currentLevel = 5; currentDesc = `5颗近获胜(共${getUserValidChessCount()}颗)`; }
                    else if (count === 4 && emptyCount >= 1) { currentLevel = 4; currentDesc = `4颗即将连线(共${getUserValidChessCount()}颗)`; }
                    else if (count === 3 && emptyCount >= 1) { currentLevel = 3; currentDesc = `${emptyCount >= 2 ? '3颗活三' : '3颗冲三'}(共${getUserValidChessCount()}颗)`; }
                    else if (count === 2 && emptyCount >= 2) { currentLevel = 2; currentDesc = `2颗活二(共${getUserValidChessCount()}颗)`; }
                    if (currentLevel > maxDangerLevel) { maxDangerLevel = currentLevel; dangerPos = pos; dangerDesc = currentDesc; }
                }
                gameState.chessData[row][col] = null;
            });
            const validCount = getUserValidChessCount();
            if (maxDangerLevel === 1 && validCount >= 2) { maxDangerLevel = Math.min(validCount, 5); dangerDesc = `${validCount}颗棋子(无连续威胁)`; }
            return { level: maxDangerLevel, pos: dangerPos, desc: dangerDesc };
        }

        function findMostDangerousUserChess(dangerLevel, nearEmptyPos) {
            let mostDangerousPos = null, maxLevelDrop = 0;
            gameState.userChessPositions.forEach(uPos => {
                const { row, col } = uPos;
                gameState.chessData[row][col] = null;
                const newDangerInfo = detectUserDangerLevel(nearEmptyPos);
                const levelDrop = dangerLevel - newDangerInfo.level;
                gameState.chessData[row][col] = gameState.userColor;
                if (levelDrop > maxLevelDrop) { maxLevelDrop = levelDrop; mostDangerousPos = uPos; }
            });
            if (!mostDangerousPos && gameState.userChessPositions.length > 0) {
                mostDangerousPos = gameState.userChessPositions[gameState.userChessPositions.length - 1];
            }
            return mostDangerousPos;
        }

        // 严格按用户提供的JS编写查码函数
        function Call_Verify(data) {
            PanGolin.Verify(data);
        }

        function Call_Query_Trial(data) {
            if (PanGolin.Is_Trial()) PanGolin.Trial();
            else PanGolin.Query(data);
        }

        function Call_Pay() {
            PanGolin.Pay();
        }

        window.addEventListener('load', initPage);
    </script>
</body>
</html>
<!-- 本DIY代码来自于 https://diy.zhongzhipian.top -->