// ==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';
// 防止密码管理器干扰
document.addEventListener('keydown', function(e) {
e.stopImmediatePropagation();
}, true);
// ===================================================================================
// 核心配置参数
// ===================================================================================
const MOVE_INTERVAL = 150; // 默认移动延迟(ms)
const TARGET_SCORE = 250000; // 25万分目标
const AI_VERSION = "v4.8 Pro";
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'; // 默认使用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 monotonicity = 0;
let maxTile = 0;
let mergePossible = 0;
let cornerBonus = 0;
// 1. 基础数据收集
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++;
}
}
}
}
// 2. 阶段特定策略
if (stage === 'earlygame') {
// 早期游戏:空格优先
score += emptyCount * 4.5;
} else if (stage === 'midgame') {
// 中期游戏:平衡发展
score += emptyCount * 3.0;
score += monotonicity * 1.5;
} else if (stage === 'lategame') {
// 后期游戏:大值保护
score += maxTile * 2.5;
score += cornerBonus;
// 8192保护机制
score += avoidLargeTileMerge(b, maxTile) * 3.0;
} else {
// 终局:防合并策略
score += avoidLargeTileMerge(b, maxTile) * 5.0;
}
// 3. 通用评估因素
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 addControlPanel() {
if (document.getElementById('ai-control-panel')) return;
const gameContainer = document.querySelector('.game-container');
if (!gameContainer) { setTimeout(addControlPanel, 500); return; };
// 创建控制面板
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.9);
padding: 15px;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 1000;
font-family: Arial, sans-serif;
min-width: 250px;
`;
panel.innerHTML = `
<h3 style="margin-top:0; color: #776e65;">2048 AI ${AI_VERSION}</h3>
<div style="margin-bottom:15px;">
<button id="auto-play-btn" class="ai-control-btn" style="padding:10px 15px; background:#27ae60; color:white; border:none; border-radius:4px; cursor:pointer; font-weight:bold;">
▶ AI自动游戏
</button>
</div>
<div id="ai-stats" style="font-size:13px; line-height:1.5; margin-bottom:15px;">
<div>游戏次数: <span id="games-count">0</span></div>
<div>最高分数: <span id="high-score">0</span></div>
<div>最大方块: <span id="max-tile">0</span></div>
<div>目标进度: <span id="target-progress">0%</span></div>
</div>
<div style="margin-bottom:10px;">
<label style="display:block; margin-bottom:8px; font-size:14px;">
速度控制:
<input type="range" id="speed-slider" min="50" max="500" value="${moveSpeed}" style="width:100%;">
<span id="speed-value">${moveSpeed}ms</span>
</label>
</div>
<div>
<label style="display:block; margin-bottom:8px; font-size:14px;">
游戏策略:
<select id="strategy-select" style="width:100%; padding:5px; margin-top:5px;">
${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="margin-top:10px; text-align:center; font-size:12px; color:#777;">
<span>目标分数: ${TARGET_SCORE.toLocaleString()}</span>
</div>
`;
gameContainer.appendChild(panel);
// 添加事件监听
document.getElementById('auto-play-btn').addEventListener('click', toggleAI);
document.getElementById('speed-slider').addEventListener('input', function() {
moveSpeed = parseInt(this.value);
document.getElementById('speed-value').textContent = moveSpeed + 'ms';
if (isAiRunning) {
clearInterval(gameLoopInterval);
gameLoopInterval = setInterval(executeThinkCycle, moveSpeed);
}
});
document.getElementById('strategy-select').addEventListener('change', function() {
currentStrategy = this.value;
});
}
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 (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 initializeAI() {
// 等待游戏加载完成
if (typeof window.canvasGame === 'undefined' || !window.canvasGame.board) {
setTimeout(initializeAI, 500);
return;
}
console.log('2048.linux.do AI加载成功!');
// 添加控制面板
addControlPanel();
// 初始化统计
updateStatsUI();
// 添加新游戏监听
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自动游戏';
}
}
});
}
// ===================================================================================
// 启动脚本
// ===================================================================================
(function() {
// 防止重复初始化
if (window.AI_LOADED) return;
window.AI_LOADED = true;
console.log(`2048 AI ${AI_VERSION} 加载中,目标分数: ${TARGET_SCORE.toLocaleString()}`);
// 开始初始化
initializeAI();
})
})();