linuxDo 2048 AI玩家

Advanced AI with expert strategies and 2-step lookahead

// ==UserScript==
// @name         linuxDo 2048 AI玩家
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Advanced AI with expert strategies and 2-step lookahead
// @match        https://2048.linux.do/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';
    
    // 防止密码管理器干扰
    document.addEventListener('keydown', function(e) {
        e.stopImmediatePropagation();
    }, true);

    // ===================================================================================
    // CONFIGURATION
    // ===================================================================================
    const MOVE_INTERVAL = 150;
    const TIMEOUT_FOR_INVALID_MOVE = 500;
    let moveSpeed = MOVE_INTERVAL;
    
    // 高级策略系统
    const strategies = {
        default: {
            weights: [
                [6, 5, 4, 3],
                [5, 4, 3, 2],
                [4, 3, 2, 1],
                [3, 2, 1, 0]
            ],
            emptyWeight: 2.7
        },
        aggressive: {
            weights: [
                [10, 8, 6, 4],
                [8, 6, 4, 2],
                [6, 4, 2, 1],
                [4, 2, 1, 0]
            ],
            emptyWeight: 2.0
        },
        expert: {
            weights: [
                [15, 14, 13, 12],
                [8,  9,  10, 11],
                [7,  6,  5,  4],
                [0,  1,  2,  3]
            ],
            emptyWeight: 4.0
        }
    };
    
    let currentStrategy = 'expert'; // 默认使用专家策略
    let isAiRunning = false;
    let isThinking = false;
    let gameLoopInterval = null;
    
    // 游戏统计
    let gamesPlayed = 0;
    let highestScore = 0;
    let highestTile = 0;

    // ===================================================================================
    // AI CORE: 增强版移动模拟和评估
    // ===================================================================================
    function simulateMove(board, direction) {
        let moved = false;
        const tempBoard = JSON.parse(JSON.stringify(board));

        function slide(row) {
            const arr = row.filter(val => val);
            const missing = 4 - arr.length;
            const zeros = Array(missing).fill(0);
            return arr.concat(zeros);
        }

        function combine(row) {
            for (let i = 0; i < 3; i++) {
                if (row[i] !== 0 && row[i] === row[i + 1]) {
                    row[i] *= 2;
                    row[i + 1] = 0;
                    moved = true;
                }
            }
            return row;
        }

        function operate(row) {
            row = slide(row);
            row = combine(row);
            return slide(row);
        }

        // 优化方向处理
        switch (direction) {
            case 'left':
                for (let r = 0; r < 4; r++) tempBoard[r] = operate(tempBoard[r]);
                break;
            case 'right':
                for (let r = 0; r < 4; r++) tempBoard[r] = operate(tempBoard[r].reverse()).reverse();
                break;
            case 'up':
                for (let c = 0; c < 4; c++) {
                    const column = [
                        tempBoard[0][c],
                        tempBoard[1][c],
                        tempBoard[2][c],
                        tempBoard[3][c]
                    ];
                    const newColumn = operate(column);
                    for (let r = 0; r < 4; r++) {
                        tempBoard[r][c] = newColumn[r];
                    }
                }
                break;
            case 'down':
                for (let c = 0; c < 4; c++) {
                    const column = [
                        tempBoard[3][c],
                        tempBoard[2][c],
                        tempBoard[1][c],
                        tempBoard[0][c]
                    ];
                    const newColumn = operate(column).reverse();
                    for (let r = 0; r < 4; r++) {
                        tempBoard[r][c] = newColumn[r];
                    }
                }
                break;
        }

        if (JSON.stringify(board) !== JSON.stringify(tempBoard)) {
            moved = true;
            Object.assign(board, tempBoard);
        }
        return moved;
    }

    // 增强版评估函数(加入2步前瞻)
    function enhancedEvaluate(b) {
        const strategy = strategies[currentStrategy];
        let score = 0;
        let emptyCount = 0;
        let smoothness = 0;
        let monotonicity = 0;
        let maxTile = 0;
        let mergePossible = 0;

        // 基本评估
        for (let r = 0; r < 4; r++) {
            for (let c = 0; c < 4; c++) {
                if (b[r][c] === 0) {
                    emptyCount++;
                } else {
                    const tileValue = b[r][c];
                    if (tileValue > maxTile) maxTile = tileValue;
                    score += Math.log2(tileValue) * strategy.weights[r][c];
                    
                    // 平滑度评估
                    if (c < 3 && b[r][c+1] !== 0) {
                        const diff = Math.abs(Math.log2(tileValue) - Math.log2(b[r][c+1]));
                        smoothness -= diff;
                        if (diff === 0) mergePossible++;
                    }
                    if (r < 3 && b[r+1][c] !== 0) {
                        const diff = Math.abs(Math.log2(tileValue) - Math.log2(b[r+1][c]));
                        smoothness -= diff;
                        if (diff === 0) mergePossible++;
                    }
                }
            }
        }
        
        // 单调性评估(专业技巧)
        for (let r = 0; r < 4; r++) {
            for (let c = 0; c < 3; c++) {
                const current = b[r][c] || 0;
                const next = b[r][c+1] || 0;
                if (current > next) monotonicity++;
            }
        }
        
        // 两步骤前瞻(模拟下一步可能的最佳移动)
        let futureBonus = 0;
        if (emptyCount > 0) {
            const directions = ['left', 'right', 'up', 'down'];
            for (const dir of directions) {
                const simBoard = JSON.parse(JSON.stringify(b));
                if (simulateMove(simBoard, dir)) {
                    // 评估移动后的空格数
                    let newEmpties = 0;
                    for (let r = 0; r < 4; r++) {
                        for (let c = 0; c < 4; c++) {
                            if (simBoard[r][c] === 0) newEmpties++;
                        }
                    }
                    futureBonus += newEmpties * 0.5;
                }
            }
        }
        
        // 最终评分公式(专业调整)
        return score + 
               smoothness * 1.5 + 
               emptyCount * strategy.emptyWeight + 
               mergePossible * 3.0 + 
               monotonicity * 0.8 +
               futureBonus;
    }

    function getNextMove(board) {
        const directions = {up: 'ArrowUp', right: 'ArrowRight', down: 'ArrowDown', left: 'ArrowLeft'};
        let bestScore = -Infinity;
        let bestDirection = 'ArrowRight';

        for (const dirKey in directions) {
            const simBoard = JSON.parse(JSON.stringify(board));
            if (simulateMove(simBoard, dirKey)) {
                const moveScore = enhancedEvaluate(simBoard);
                if (moveScore > bestScore) {
                    bestScore = moveScore;
                    bestDirection = directions[dirKey];
                }
            }
        }
        return bestDirection;
    }

    // =====================================================================
    // EXECUTION ENGINE
    // =====================================================================
    async function attemptMove(direction) {
        const stateBefore = JSON.stringify(window.canvasGame.board);
        document.body.dispatchEvent(new KeyboardEvent('keydown', { key: direction, bubbles: true }));
        return new Promise(resolve => {
            const startTime = Date.now();
            const checkInterval = setInterval(() => {
                if (JSON.stringify(window.canvasGame.board) !== stateBefore) {
                    clearInterval(checkInterval);
                    resolve(true);
                } else if (Date.now() - startTime > TIMEOUT_FOR_INVALID_MOVE) {
                    clearInterval(checkInterval);
                    resolve(false);
                }
            }, 50);
        });
    }

    async function executeThinkCycle() {
        if (isThinking || !isAiRunning) return;
        
        // 游戏结束检测
        if (window.canvasGame.gameOver || (window.canvasGame.victory && !window.canvasGame.keepPlaying)) {
            console.log("🎉 游戏结束! 最终得分: " + window.canvasGame.score);
            console.log("最大方块: " + window.canvasGame.maxTile);
            
            // 更新统计
            gamesPlayed++;
            if (window.canvasGame.score > highestScore) {
                highestScore = window.canvasGame.score;
            }
            if (window.canvasGame.maxTile > highestTile) {
                highestTile = window.canvasGame.maxTile;
            }
            
            // 停止AI
            isAiRunning = false;
            clearInterval(gameLoopInterval);
            
            // 更新UI
            const autoPlayBtn = document.getElementById('auto-play-btn');
            if (autoPlayBtn) {
                autoPlayBtn.disabled = false;
                autoPlayBtn.style.backgroundColor = '#27ae60';
                autoPlayBtn.textContent = 'AI自动游戏';
                autoPlayBtn.title = `游戏次数: ${gamesPlayed} | 最高分: ${highestScore} | 最大方块: ${highestTile}`;
            }
            
            return;
        }

        isThinking = true;

        try {
            const board = window.canvasGame.board;
            const bestMove = getNextMove(board);
            
            if (!await attemptMove(bestMove)) {
                console.warn(`最佳移动 ${bestMove} 无效,尝试备选方案...`);
                const fallbackMoves = ['ArrowRight', 'ArrowDown', 'ArrowLeft', 'ArrowUp'].filter(m => m !== bestMove);
                for(const move of fallbackMoves) {
                    if (await attemptMove(move)) break;
                }
            }
        } catch (e) {
            console.error("AI执行错误:", e);
        } finally {
            isThinking = false;
        }
    }
    
    // =====================================================================
    // UI 控制面板
    // =====================================================================
    function addControlPanel() {
        if (document.getElementById('ai-control-panel')) return;
        const gameControls = document.querySelector('.game-controls');
        if (!gameControls) { 
            setTimeout(addControlPanel, 500); 
            return; 
        };
        
        // 创建面板
        const panel = document.createElement('div');
        panel.id = 'ai-control-panel';
        panel.style.display = 'flex';
        panel.style.gap = '10px';
        panel.style.marginTop = '15px';
        panel.style.flexWrap = 'wrap';
        
        // 自动游戏按钮
        const autoPlayBtn = document.createElement('button');
        autoPlayBtn.id = 'auto-play-btn';
        autoPlayBtn.className = 'new-game-btn';
        autoPlayBtn.style.backgroundColor = '#27ae60';
        autoPlayBtn.textContent = 'AI自动游戏';
        autoPlayBtn.title = `游戏次数: 0 | 最高分: 0 | 最大方块: 0`;
        
        autoPlayBtn.onclick = function() {
            if (!isAiRunning) {
                if (window.canvasGame.gameOver || window.canvasGame.victory) {
                    alert("游戏已结束! 请先开始新游戏");
                    return;
                }

                isAiRunning = true;
                this.disabled = true;
                this.style.backgroundColor = '#7f8c8d';
                this.textContent = 'AI运行中...';
                gameLoopInterval = setInterval(executeThinkCycle, moveSpeed);
            }
        };
        
        // 速度控制
        const speedContainer = document.createElement('div');
        speedContainer.style.display = 'flex';
        speedContainer.style.alignItems = 'center';
        speedContainer.style.gap = '5px';
        
        const speedLabel = document.createElement('span');
        speedLabel.textContent = '速度:';
        
        const speedSlider = document.createElement('input');
        speedSlider.type = 'range';
        speedSlider.min = '50';
        speedSlider.max = '500';
        speedSlider.value = moveSpeed;
        speedSlider.style.width = '100px';
        
        speedSlider.oninput = function() {
            moveSpeed = parseInt(this.value);
            if (isAiRunning) {
                clearInterval(gameLoopInterval);
                gameLoopInterval = setInterval(executeThinkCycle, moveSpeed);
            }
        };
        
        speedContainer.appendChild(speedLabel);
        speedContainer.appendChild(speedSlider);
        
        // 策略选择
        const strategyContainer = document.createElement('div');
        strategyContainer.style.display = 'flex';
        strategyContainer.style.alignItems = 'center';
        strategyContainer.style.gap = '5px';
        
        const strategyLabel = document.createElement('span');
        strategyLabel.textContent = '策略:';
        
        const strategySelect = document.createElement('select');
        for (const strategy in strategies) {
            const option = document.createElement('option');
            option.value = strategy;
            option.textContent = strategy.charAt(0).toUpperCase() + strategy.slice(1);
            strategySelect.appendChild(option);
        }
        strategySelect.value = currentStrategy;
        
        strategySelect.onchange = function() {
            currentStrategy = this.value;
        };
        
        strategyContainer.appendChild(strategyLabel);
        strategyContainer.appendChild(strategySelect);
        
        // 统计显示
        const statsDisplay = document.createElement('div');
        statsDisplay.id = 'ai-stats';
        statsDisplay.style.marginLeft = '15px';
        statsDisplay.style.color = '#776e65';
        statsDisplay.textContent = '游戏次数: 0 | 最高分: 0 | 最大方块: 0';
        
        // 组装面板
        panel.appendChild(autoPlayBtn);
        panel.appendChild(speedContainer);
        panel.appendChild(strategyContainer);
        gameControls.appendChild(panel);
        gameControls.appendChild(statsDisplay);
    }

    // 初始化
    console.log('2048 Ultimate AI initialized');
    setTimeout(addControlPanel, 1000);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址