您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
专为2048.linux.do设计的高性能AI
当前为
// ==UserScript== // @name linuxDo 2048 AI玩家 Plus // @namespace http://tampermonkey.net/ // @version 2.0 // @description 专为2048.linux.do设计的高性能AI // @author littleleo // @match https://2048.linux.do/* // @grant none // @run-at document-start // ==/UserScript== (function() { 'use strict'; // ======================== 核心配置 ======================== const MOVE_INTERVAL = 150; // 默认移动延迟(ms) const TARGET_SCORE = 250000; // 25万分目标 const AI_VERSION = "v2.0"; 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 }, linuxdo: { weights: [ [16, 15, 14, 13], [9, 10, 11, 12], [8, 7, 6, 5], [1, 2, 3, 4] ], emptyWeight: 4.5 } }; let currentStrategy = 'linuxdo'; let isAiRunning = false; let isThinking = false; let gameLoopInterval = null; // 游戏统计 let gamesPlayed = 0; let highestScore = 0; let highestTile = 0; let targetAchieved = false; // ======================== AI核心算法 ======================== 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; } function detectGameStage(board) { const tiles = board.flat(); const maxTile = Math.max(...tiles.filter(Boolean)); const emptyCount = 16 - tiles.filter(Boolean).length; const smallTiles = tiles.filter(t => t > 0 && t <= 64).length; if (maxTile >= 8192) return 'endgame'; if (maxTile >= 4096) return 'lategame'; if (emptyCount > 6 || smallTiles > 8) return 'earlygame'; return 'midgame'; } function enhancedEvaluate(b) { const strategy = strategies[currentStrategy]; const stage = detectGameStage(b); let score = 0; let emptyCount = 0; let smoothness = 0; let maxTile = 0; let mergePossible = 0; let cornerBonus = 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 ((r === 0 || r === 3) && (c === 0 || c === 3) && tileValue >= 1024) { cornerBonus += tileValue * 0.5; } // 平滑度评估 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++; } } } } // 阶段特定策略 if (stage === 'earlygame') { score += emptyCount * 4.5; } else if (stage === 'midgame') { score += emptyCount * 3.0; } else if (stage === 'lategame') { score += maxTile * 2.5; score += cornerBonus; score += avoidLargeTileMerge(b, maxTile) * 3.0; } else { score += avoidLargeTileMerge(b, maxTile) * 5.0; } // 通用评估因素 score += smoothness * 1.5; score += mergePossible * 2.0; score += emptyCount * strategy.emptyWeight; return score; } function avoidLargeTileMerge(board, maxTile) { if (maxTile < 4096) return 0; let riskScore = 0; const largeTiles = []; for (let r = 0; r < 4; r++) { for (let c = 0; c < 4; c++) { if (board[r][c] >= 2048) { largeTiles.push({r, c, value: board[r][c]}); } } } for (let i = 0; i < largeTiles.length; i++) { for (let j = i + 1; j < largeTiles.length; j++) { const tileA = largeTiles[i]; const tileB = largeTiles[j]; if (tileA.value === tileB.value) { const distR = Math.abs(tileA.r - tileB.r); const distC = Math.abs(tileA.c - tileB.c); if ((distR === 1 && distC === 0) || (distR === 0 && distC === 1)) { riskScore -= 50000; } else if (distR === 0 || distC === 0) { riskScore -= 20000; } } } } return riskScore; } 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; } // ======================== 游戏执行引擎 ======================== 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 > 500) { clearInterval(checkInterval); resolve(false); } }, 50); }); } async function executeThinkCycle() { if (isThinking || !isAiRunning) return; // 游戏结束检测 if (window.canvasGame.gameOver || (window.canvasGame.victory && !window.canvasGame.keepPlaying)) { const score = window.canvasGame.score; const maxTile = window.canvasGame.maxTile; console.log(`🎉 游戏结束! 得分: ${score} | 最大方块: ${maxTile}`); // 更新统计 gamesPlayed++; if (score > highestScore) { highestScore = score; if (score >= TARGET_SCORE) { targetAchieved = true; console.log(`🏆 达成目标分数: ${TARGET_SCORE}`); } } if (maxTile > highestTile) highestTile = maxTile; // 更新UI updateStatsUI(); // 停止AI isAiRunning = false; clearInterval(gameLoopInterval); // 启用按钮 const autoPlayBtn = document.getElementById('auto-play-btn'); if (autoPlayBtn) { autoPlayBtn.disabled = false; autoPlayBtn.style.backgroundColor = '#27ae60'; autoPlayBtn.textContent = 'AI自动游戏'; } return; } isThinking = true; try { const board = window.canvasGame.board; const bestMove = getNextMove(board); if (!await attemptMove(bestMove)) { // 备用移动方案 const fallbackMoves = ['ArrowRight', 'ArrowDown', 'ArrowLeft', 'ArrowUp']; for(const move of fallbackMoves) { if (await attemptMove(move)) break; } } } catch (e) { console.error("AI执行错误:", e); } finally { isThinking = false; } } // ======================== 用户界面与控制 ======================== function createControlPanel() { const panel = document.createElement('div'); panel.id = 'ai-control-panel'; panel.style.cssText = ` position: absolute; top: 20px; right: 20px; background: rgba(255, 255, 255, 0.95); padding: 15px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.25); z-index: 9999; font-family: Arial, sans-serif; min-width: 250px; border: 1px solid #ddd; `; panel.innerHTML = ` <h3 style="margin-top:0; color: #776e65; border-bottom: 1px solid #eee; padding-bottom: 10px;">2048 AI ${AI_VERSION}</h3> <div style="margin-bottom:15px;"> <button id="auto-play-btn" style="padding:10px 15px; width:100%; background:#27ae60; color:white; border:none; border-radius:4px; cursor:pointer; font-weight:bold; font-size:16px;"> ▶ 启动AI </button> </div> <div id="ai-stats" style="font-size:14px; line-height:1.8; margin-bottom:15px; background:#f9f9f9; padding:10px; border-radius:5px;"> <div>游戏次数: <span id="games-count" style="float:right;">0</span></div> <div>最高分数: <span id="high-score" style="float:right;">0</span></div> <div>最大方块: <span id="max-tile" style="float:right;">0</span></div> <div style="font-weight:bold;">目标进度: <span id="target-progress" style="float:right; color:#e74c3c;">0%</span></div> </div> <div style="margin-bottom:15px;"> <label style="display:block; margin-bottom:12px;"> <div style="margin-bottom:5px; font-weight:bold;">速度控制:</div> <input type="range" id="speed-slider" min="50" max="500" value="${moveSpeed}" style="width:100%;"> <div style="text-align:center; font-size:14px;"><span id="speed-value">${moveSpeed}ms/步</span></div> </label> </div> <div style="margin-bottom:15px;"> <label style="display:block; margin-bottom:12px;"> <div style="margin-bottom:5px; font-weight:bold;">游戏策略:</div> <select id="strategy-select" style="width:100%; padding:8px; border-radius:4px; border:1px solid #ddd;"> ${Object.keys(strategies).map(strat => `<option value="${strat}" ${strat === currentStrategy ? 'selected' : ''}> ${strat.charAt(0).toUpperCase() + strat.slice(1)} </option>` ).join('')} </select> </label> </div> <div style="color:#777; font-size:12px; text-align:center; margin-top:10px; padding-top:10px; border-top:1px solid #eee;"> 目标分数: ${TARGET_SCORE.toLocaleString()} </div> `; return panel; } function updateStatsUI() { if (!document.getElementById('games-count')) return; document.getElementById('games-count').textContent = gamesPlayed; document.getElementById('high-score').textContent = highestScore; document.getElementById('max-tile').textContent = highestTile || 0; const progress = Math.min(100, Math.round((highestScore / TARGET_SCORE) * 100)); const progressEl = document.getElementById('target-progress'); progressEl.textContent = `${progress}%`; progressEl.style.color = progress > 90 ? '#27ae60' : progress > 50 ? '#f39c12' : '#e74c3c'; progressEl.style.fontWeight = progress > 80 ? 'bold' : 'normal'; } function toggleAI() { const button = document.getElementById('auto-play-btn'); if (!button) { console.error("未找到AI按钮!"); return; } if (isAiRunning) { // 停止AI isAiRunning = false; clearInterval(gameLoopInterval); button.style.backgroundColor = '#27ae60'; button.textContent = '▶ 启动AI'; console.log('AI已停止'); } else { // 检查游戏状态 if (window.canvasGame.gameOver || (window.canvasGame.victory && !window.canvasGame.keepPlaying)) { alert("游戏已结束! 请先点击'新游戏'按钮"); return; } // 启动AI isAiRunning = true; button.style.backgroundColor = '#e74c3c'; button.textContent = '■ 停止AI'; console.log('AI开始运行...'); gameLoopInterval = setInterval(executeThinkCycle, moveSpeed); } } function handleSpeedChange() { moveSpeed = parseInt(this.value); document.getElementById('speed-value').textContent = moveSpeed + 'ms/步'; if (isAiRunning) { clearInterval(gameLoopInterval); gameLoopInterval = setInterval(executeThinkCycle, moveSpeed); } } // ======================== 初始化函数 ======================== function initializeAI() { // 等待游戏对象加载 if (typeof window.canvasGame === 'undefined' || !window.canvasGame.board) { console.log("等待游戏加载..."); setTimeout(initializeAI, 500); return; } // 确保游戏容器存在 const gameContainer = document.querySelector('.game-container'); if (!gameContainer) { console.log("等待游戏容器..."); setTimeout(initializeAI, 500); return; } // 检查是否已添加控制面板 if (document.getElementById('ai-control-panel')) { console.log("AI控制面板已存在"); return; } // 创建并添加控制面板 const panel = createControlPanel(); gameContainer.appendChild(panel); console.log("AI控制面板已添加"); // 添加事件监听 document.getElementById('auto-play-btn').addEventListener('click', toggleAI); document.getElementById('speed-slider').addEventListener('input', handleSpeedChange); document.getElementById('strategy-select').addEventListener('change', function() { currentStrategy = this.value; console.log(`策略切换为: ${currentStrategy}`); }); // 添加新游戏监听 document.querySelector('.new-game-btn')?.addEventListener('click', () => { if (isAiRunning) { isAiRunning = false; clearInterval(gameLoopInterval); const button = document.getElementById('auto-play-btn'); if (button) { button.style.backgroundColor = '#27ae60'; button.textContent = '▶ 启动AI'; } console.log("新游戏开始,AI已停止"); } }); // 初始化统计 updateStatsUI(); console.log(`2048 AI ${AI_VERSION} 初始化完成`); } // ======================== 启动脚本 ======================== (function() { // 防止重复初始化 if (window.AI_LOADED) return; window.AI_LOADED = true; console.log(`2048 AI ${AI_VERSION} 加载中,目标分数: ${TARGET_SCORE.toLocaleString()}`); // 确保页面完全加载 if (document.readyState === 'complete') { initializeAI(); } else { window.addEventListener('load', function() { setTimeout(initializeAI, 1000); // 额外等待确保完全加载 }); } // 添加键盘快捷键: Alt+A 切换AI document.addEventListener('keydown', function(e) { if (e.altKey && e.key.toLowerCase() === 'a') { const button = document.getElementById('auto-play-btn'); if (button) { button.click(); e.preventDefault(); } } }); })(); })();