您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
LinuxDo2048 25w分
当前为
// ==UserScript== // @name LinuxDo2048 // @namespace http://tampermonkey.net/ // @version 2025-07-02 // @author TigerWang // @description LinuxDo2048 25w分 // @license MIT // @match https://2048.linux.do/ // @icon https://www.google.com/s2/favicons?sz=64&domain=linux.do // @grant none // ==/UserScript== (function () { // 标记 AI 是否正在运行 let aiRunning = false; // Worker 内部代码(字符串形式)- 增强版本 const workerCode = `var Module = typeof Module !== "undefined" ? Module : {}; var moduleOverrides = {}; var key; for (key in Module) { if (Module.hasOwnProperty(key)) { moduleOverrides[key] = Module[key] } } // 新增: 最大化棋面价值策略 - 实现"清理与巩固" function evaluateMaximizeBoardValue(board) { let score = 0; const tiles = []; const positions = []; // 提取所有非零数值和位置 for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { const tile = (board[i] >> (12 - 4 * j)) & 0xf; if (tile > 0) { const value = 1 << tile; tiles.push(value); positions.push({i, j, value}); } } } // 计算当前棋面总价值 const totalValue = tiles.reduce((sum, tile) => sum + tile, 0); score += totalValue * 10; // 直接奖励高总分 // 检测游戏阶段 const count8192 = tiles.filter(x => x === 8192).length; const smallTiles = tiles.filter(x => x <= 32); const mediumTiles = tiles.filter(x => x >= 128 && x <= 512); // 动态策略选择 const emptySpaces = 16 - tiles.length; if (count8192 >= 2) { // 双8192模式:最大化终盘价值,但避免合并 score += evaluateEndgameValue(tiles, positions); } else if (count8192 === 1) { // 单8192策略:根据棋盘状况决定 if (smallTiles.length > 8 && emptySpaces >= 3) { // 清理模式:小瓦片过多且有空间时清理 score += evaluateCleanupPhase(tiles, positions); } else if (emptySpaces <= 2) { // 危险模式:空间不足时优先保持可玩性 score += evaluateSurvivalMode(tiles, positions); } else { // 发展模式:继续向第二个8192努力 score += evaluateSecond8192Growth(tiles, positions); } } else { // 标准发展模式 score += evaluateStandardGrowth(tiles, positions); } // 中等瓦片保护奖励 - 平衡保护与发展 if (count8192 >= 1) { // 已有8192时,适度保护中等瓦片 score += mediumTiles.length * 5000; score += tiles.filter(x => x === 256).length * 8000; score += tiles.filter(x => x === 512).length * 12000; } else { // 没有8192时,优先发展大瓦片 score += mediumTiles.length * 3000; } // 大瓦片发展奖励 score += tiles.filter(x => x === 1024).length * 25000; score += tiles.filter(x => x === 2048).length * 50000; // 4096动态保护策略 const tiles4096 = tiles.filter(x => x === 4096); if (count8192 === 0) { // 没有8192时,4096是发展目标 score += tiles4096.length * 75000; } else if (count8192 === 1 && emptySpaces > 2) { // 有1个8192且空间充足时,可以发展第二个 score += tiles4096.length * 40000; } else { // 其他情况适度保护 score += tiles4096.length * 20000; } // 单调性评估 score += getMonotonicity(board) * 1000; // 智能平滑性评估 score += getSmartSmoothness(board, positions) * 500; // 空格数量与质量 const emptyCount = 16 - tiles.length; score += emptyCount * 4000; // 增加空格权重 // 容错空间评估 if (emptyCount < 3) { score -= 50000; // 惩罚过满的棋盘 } return score; } // 新增: 清理阶段评估 function evaluateCleanupPhase(tiles, positions) { let cleanupScore = 0; // 奖励小瓦片合并潜力 const smallGroups = {}; tiles.forEach(tile => { if (tile <= 32) { smallGroups[tile] = (smallGroups[tile] || 0) + 1; } }); // 成对的小瓦片加分 Object.entries(smallGroups).forEach(([value, count]) => { if (count >= 2) { cleanupScore += parseInt(value) * count * 100; } }); // 惩罚过多的2和4 const count2 = tiles.filter(x => x === 2).length; const count4 = tiles.filter(x => x === 4).length; if (count2 + count4 > 8) { cleanupScore -= (count2 + count4 - 8) * 10000; } return cleanupScore; } // 新增: 终盘价值评估 function evaluateEndgameValue(tiles, positions) { let endgameScore = 0; // 奖励保留高价值瓦片 tiles.forEach(tile => { if (tile >= 256) { endgameScore += tile * 5; // 中高价值瓦片额外加分 } }); // 8192防合并保护 const tiles8192Count = tiles.filter(x => x === 8192).length; if (tiles8192Count >= 2) { const pos8192 = positions.filter(p => p.value === 8192); let minSeparation = Infinity; for (let i = 0; i < pos8192.length - 1; i++) { for (let j = i + 1; j < pos8192.length; j++) { const distance = Math.abs(pos8192[i].i - pos8192[j].i) + Math.abs(pos8192[i].j - pos8192[j].j); minSeparation = Math.min(minSeparation, distance); } } if (minSeparation === 1) { endgameScore -= 300000; // 相邻8192惩罚 } else if (minSeparation >= 3) { endgameScore += 100000; // 分离良好奖励 } } return endgameScore; } // 新增: 标准发展评估 function evaluateStandardGrowth(tiles, positions) { let growthScore = 0; // 奖励瓦片升级链 const upgradePotential = calculateUpgradePotential(tiles); growthScore += upgradePotential * 1000; return growthScore; } // 新增: 生存模式评估 - 棋盘满时保持可玩性 function evaluateSurvivalMode(tiles, positions) { let survivalScore = 0; // 优先保持移动可能性 survivalScore += calculateMovePossibilities(tiles, positions) * 50000; // 降低对中等瓦片的过度保护 const mediumTiles = tiles.filter(x => x >= 128 && x <= 512); if (mediumTiles.length > 4) { survivalScore -= 20000; // 中等瓦片过多时减分 } return survivalScore; } // 新增: 第二个8192发展模式 function evaluateSecond8192Growth(tiles, positions) { let growthScore = 0; // 奖励4096的存在和发展 const count4096 = tiles.filter(x => x === 4096).length; const count2048 = tiles.filter(x => x === 2048).length; const count1024 = tiles.filter(x => x === 1024).length; // 4096是第二个8192的关键 growthScore += count4096 * 80000; // 2048链条发展 growthScore += count2048 * 30000; growthScore += count1024 * 15000; // 如果有多个4096,优先合并其中一个 if (count4096 >= 2) { growthScore += 100000; } return growthScore; } // 新增: 计算移动可能性 function calculateMovePossibilities(tiles, positions) { let possibilities = 0; // 检查相邻相同瓦片(可合并) for (let i = 0; i < positions.length; i++) { for (let j = i + 1; j < positions.length; j++) { const pos1 = positions[i]; const pos2 = positions[j]; // 相邻且相同值 if (pos1.value === pos2.value && ((Math.abs(pos1.i - pos2.i) === 1 && pos1.j === pos2.j) || (Math.abs(pos1.j - pos2.j) === 1 && pos1.i === pos2.i))) { possibilities += pos1.value; // 大瓦片合并更有价值 } } } return possibilities; } // 新增: 计算升级潜力 function calculateUpgradePotential(tiles) { const tileCounts = {}; tiles.forEach(tile => { tileCounts[tile] = (tileCounts[tile] || 0) + 1; }); let potential = 0; Object.entries(tileCounts).forEach(([value, count]) => { if (count >= 2) { potential += parseInt(value) * (count - 1); } }); return potential; } // 新增: 智能平滑性评估 function getSmartSmoothness(board, positions) { let smooth = 0; // 根据瓦片大小调整平滑性权重 for (let i = 0; i < positions.length - 1; i++) { for (let j = i + 1; j < positions.length; j++) { const pos1 = positions[i]; const pos2 = positions[j]; // 相邻瓦片 if ((Math.abs(pos1.i - pos2.i) === 1 && pos1.j === pos2.j) || (Math.abs(pos1.j - pos2.j) === 1 && pos1.i === pos2.i)) { const ratio = Math.max(pos1.value, pos2.value) / Math.min(pos1.value, pos2.value); // 2倍关系最理想 if (ratio === 2) { smooth += 100; } else if (ratio === 4) { smooth += 50; } else if (ratio > 4) { smooth -= (ratio - 4) * 20; } } } } return smooth; } // 新增: 排除8192的平滑性计算 function getSmoothnessExclude8192(board, positions) { let smooth = 0; const pos8192 = positions.filter(p => p.value === 8192); for (let i = 0; i < 4; i++) { for (let j = 0; j < 3; j++) { const curr = (board[i] >> (12 - 4 * j)) & 0xf; const next = (board[i] >> (12 - 4 * (j + 1))) & 0xf; // 跳过涉及8192的平滑性计算 const currVal = curr > 0 ? (1 << curr) : 0; const nextVal = next > 0 ? (1 << next) : 0; if (currVal === 8192 || nextVal === 8192) continue; if (curr > 0 && next > 0) { smooth -= Math.abs(curr - next); } } } return smooth; } // 新增: 检测8192合并风险 function detect8192MergeRisk(board) { let riskLevel = 0; const positions8192 = []; // 找到所有8192的位置 for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { const tile = (board[i] >> (12 - 4 * j)) & 0xf; if ((1 << tile) === 8192) { positions8192.push({i, j}); } } } if (positions8192.length < 2) return 0; // 检查8192之间的关系 for (let a = 0; a < positions8192.length; a++) { for (let b = a + 1; b < positions8192.length; b++) { const pos1 = positions8192[a]; const pos2 = positions8192[b]; // 同行或同列的8192 if (pos1.i === pos2.i || pos1.j === pos2.j) { const distance = Math.abs(pos1.i - pos2.i) + Math.abs(pos1.j - pos2.j); if (distance === 1) { // 直接相邻:极高风险 riskLevel += 5; } else { // 同行/列但不相邻:检查中间是否有空格 let hasEmptyBetween = false; if (pos1.i === pos2.i) { // 同行 const minJ = Math.min(pos1.j, pos2.j); const maxJ = Math.max(pos1.j, pos2.j); for (let j = minJ + 1; j < maxJ; j++) { const tile = (board[pos1.i] >> (12 - 4 * j)) & 0xf; if (tile === 0) { hasEmptyBetween = true; break; } } } else { // 同列 const minI = Math.min(pos1.i, pos2.i); const maxI = Math.max(pos1.i, pos2.i); for (let i = minI + 1; i < maxI; i++) { const tile = (board[i] >> (12 - 4 * pos1.j)) & 0xf; if (tile === 0) { hasEmptyBetween = true; break; } } } if (!hasEmptyBetween) { // 同行/列且中间无空格:高风险 riskLevel += 3; } else { // 同行/列但中间有空格:中风险 riskLevel += 1; } } } } } return riskLevel; } // 新增: 计算8192分离度 function calculate8192Separation(board) { const positions8192 = []; for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { const tile = (board[i] >> (12 - 4 * j)) & 0xf; if ((1 << tile) === 8192) { positions8192.push({i, j}); } } } if (positions8192.length < 2) return 0; // 计算8192之间的最小距离 let minDistance = Infinity; for (let a = 0; a < positions8192.length; a++) { for (let b = a + 1; b < positions8192.length; b++) { const pos1 = positions8192[a]; const pos2 = positions8192[b]; const distance = Math.abs(pos1.i - pos2.i) + Math.abs(pos1.j - pos2.j); minDistance = Math.min(minDistance, distance); } } return minDistance; // 距离越远越好 } // 新增: 单调性计算 function getMonotonicity(board) { let mono = 0; for (let i = 0; i < 4; i++) { let inc = 0, dec = 0; for (let j = 0; j < 3; j++) { const curr = (board[i] >> (12 - 4 * j)) & 0xf; const next = (board[i] >> (12 - 4 * (j + 1))) & 0xf; if (curr > next) inc++; if (curr < next) dec++; } mono += Math.max(inc, dec); } return mono; } // 新增: 平滑性计算 function getSmoothness(board) { let smooth = 0; for (let i = 0; i < 4; i++) { for (let j = 0; j < 3; j++) { const curr = (board[i] >> (12 - 4 * j)) & 0xf; const next = (board[i] >> (12 - 4 * (j + 1))) & 0xf; if (curr > 0 && next > 0) { smooth -= Math.abs(curr - next); } } } return smooth; } var arguments_ = []; var thisProgram = "./this.program"; var quit_ = function (status, toThrow) { throw toThrow }; var scriptDirectory = ""; function locateFile(path) { if (Module["locateFile"]) { return Module["locateFile"](path, scriptDirectory) } return scriptDirectory + path } var read_, readAsync, readBinary, setWindowTitle; var nodeFS; var nodePath; scriptDirectory = self.location.href if (scriptDirectory.indexOf("blob:") !== 0) { scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf("/") + 1) } else { scriptDirectory = "" } { read_ = function shell_read(url) { var xhr = new XMLHttpRequest; xhr.open("GET", url, false); xhr.send(null); return xhr.responseText } readBinary = function readBinary(url) { var xhr = new XMLHttpRequest; xhr.open("GET", url, false); xhr.responseType = "arraybuffer"; xhr.send(null); return new Uint8Array(xhr.response) } readAsync = function readAsync(url, onload, onerror) { var xhr = new XMLHttpRequest; xhr.open("GET", url, true); xhr.responseType = "arraybuffer"; xhr.onload = function xhr_onload() { if (xhr.status == 200 || xhr.status == 0 && xhr.response) { onload(xhr.response); return } onerror() } ; xhr.onerror = onerror; xhr.send(null) } } setWindowTitle = function (title) { document.title = title } var out = Module["print"] || console.log.bind(console); var err = Module["printErr"] || console.warn.bind(console); for (key in moduleOverrides) { if (moduleOverrides.hasOwnProperty(key)) { Module[key] = moduleOverrides[key] } } moduleOverrides = null; if (Module["arguments"]) arguments_ = Module["arguments"]; if (Module["thisProgram"]) thisProgram = Module["thisProgram"]; if (Module["quit"]) quit_ = Module["quit"]; var wasmBinary; if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"]; var noExitRuntime; if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"]; if (typeof WebAssembly !== "object") { abort("no native wasm support detected") } var wasmMemory; var wasmTable; var ABORT = false; var EXITSTATUS = 0; function assert(condition, text) { if (!condition) { abort("Assertion failed: " + text) } } var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined; function UTF8ArrayToString(heap, idx, maxBytesToRead) { var endIdx = idx + maxBytesToRead; var endPtr = idx; while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr; if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) { return UTF8Decoder.decode(heap.subarray(idx, endPtr)) } else { var str = ""; while (idx < endPtr) { var u0 = heap[idx++]; if (!(u0 & 128)) { str += String.fromCharCode(u0); continue } var u1 = heap[idx++] & 63; if ((u0 & 224) == 192) { str += String.fromCharCode((u0 & 31) << 6 | u1); continue } var u2 = heap[idx++] & 63; if ((u0 & 240) == 224) { u0 = (u0 & 15) << 12 | u1 << 6 | u2 } else { u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heap[idx++] & 63 } if (u0 < 65536) { str += String.fromCharCode(u0) } else { var ch = u0 - 65536; str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023) } } } return str } function UTF8ToString(ptr, maxBytesToRead) { return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "" } var WASM_PAGE_SIZE = 65536; var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; function updateGlobalBufferAndViews(buf) { buffer = buf; Module["HEAP8"] = HEAP8 = new Int8Array(buf); Module["HEAP16"] = HEAP16 = new Int16Array(buf); Module["HEAP32"] = HEAP32 = new Int32Array(buf); Module["HEAPU8"] = HEAPU8 = new Uint8Array(buf); Module["HEAPU16"] = HEAPU16 = new Uint16Array(buf); Module["HEAPU32"] = HEAPU32 = new Uint32Array(buf); Module["HEAPF32"] = HEAPF32 = new Float32Array(buf); Module["HEAPF64"] = HEAPF64 = new Float64Array(buf) } var INITIAL_INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 134217728; if (Module["wasmMemory"]) { wasmMemory = Module["wasmMemory"] } else { wasmMemory = new WebAssembly.Memory({ "initial": INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE, "maximum": INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE }) } if (wasmMemory) { buffer = wasmMemory.buffer } INITIAL_INITIAL_MEMORY = buffer.byteLength; updateGlobalBufferAndViews(buffer); var __ATPRERUN__ = []; var __ATINIT__ = []; var __ATMAIN__ = []; var __ATPOSTRUN__ = []; var runtimeInitialized = false; var runtimeExited = false; function preRun() { if (Module["preRun"]) { if (typeof Module["preRun"] == "function") Module["preRun"] = [Module["preRun"]]; while (Module["preRun"].length) { addOnPreRun(Module["preRun"].shift()) } } callRuntimeCallbacks(__ATPRERUN__) } function initRuntime() { runtimeInitialized = true; callRuntimeCallbacks(__ATINIT__) } function preMain() { callRuntimeCallbacks(__ATMAIN__) } function exitRuntime() { runtimeExited = true } function postRun() { if (Module["postRun"]) { if (typeof Module["postRun"] == "function") Module["postRun"] = [Module["postRun"]]; while (Module["postRun"].length) { addOnPostRun(Module["postRun"].shift()) } } callRuntimeCallbacks(__ATPOSTRUN__) } function addOnPreRun(cb) { __ATPRERUN__.unshift(cb) } function addOnPostRun(cb) { __ATPOSTRUN__.unshift(cb) } var runDependencies = 0; var runDependencyWatcher = null; var dependenciesFulfilled = null; function addRunDependency(id) { runDependencies++; if (Module["monitorRunDependencies"]) { Module["monitorRunDependencies"](runDependencies) } } function removeRunDependency(id) { runDependencies--; if (Module["monitorRunDependencies"]) { Module["monitorRunDependencies"](runDependencies) } if (runDependencies == 0) { if (runDependencyWatcher !== null) { clearInterval(runDependencyWatcher); runDependencyWatcher = null } if (dependenciesFulfilled) { var callback = dependenciesFulfilled; dependenciesFulfilled = null; callback() } } } Module["preloadedImages"] = {}; Module["preloadedAudios"] = {}; function abort(what) { if (Module["onAbort"]) { Module["onAbort"](what) } what += ""; err(what); ABORT = true; EXITSTATUS = 1; what = "abort(" + what + "). Build with -s ASSERTIONS=1 for more info."; var e = new WebAssembly.RuntimeError(what); throw e } function hasPrefix(str, prefix) { return String.prototype.startsWith ? str.startsWith(prefix) : str.indexOf(prefix) === 0 } var dataURIPrefix = "data:application/octet-stream;base64,"; function isDataURI(filename) { return hasPrefix(filename, dataURIPrefix) } var fileURIPrefix = "file://"; function isFileURI(filename) { return hasPrefix(filename, fileURIPrefix) } var wasmBinaryFile = "data:application/octet-stream;base64,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"; if (!isDataURI(wasmBinaryFile)) { wasmBinaryFile = locateFile(wasmBinaryFile) } function getBinary() { try { if (wasmBinary) { return new Uint8Array(wasmBinary) } if (readBinary) { return readBinary(wasmBinaryFile) } else { throw "both async and sync fetching of the wasm failed" } } catch (err) { abort(err) } } function getBinaryPromise() { if (!wasmBinary && typeof fetch === "function" && !isFileURI(wasmBinaryFile)) { return fetch(wasmBinaryFile, { credentials: "same-origin" }).then(function (response) { if (!response["ok"]) { throw "failed to load wasm binary file at '" + wasmBinaryFile + "'" } return response["arrayBuffer"]() }).catch(function () { return getBinary() }) } return Promise.resolve().then(getBinary) } function createWasm() { var info = { "a": asmLibraryArg }; function receiveInstance(instance, module) { var exports = instance.exports; Module["asm"] = exports; wasmTable = Module["asm"]["e"]; removeRunDependency("wasm-instantiate") } addRunDependency("wasm-instantiate"); function receiveInstantiatedSource(output) { receiveInstance(output["instance"]) } function instantiateArrayBuffer(receiver) { return getBinaryPromise().then(function (binary) { return WebAssembly.instantiate(binary, info) }).then(receiver, function (reason) { err("failed to asynchronously prepare wasm: " + reason); abort(reason) }) } function instantiateAsync() { if (!wasmBinary && typeof WebAssembly.instantiateStreaming === "function" && !isDataURI(wasmBinaryFile) && !isFileURI(wasmBinaryFile) && typeof fetch === "function") { fetch(wasmBinaryFile, { credentials: "same-origin" }).then(function (response) { var result = WebAssembly.instantiateStreaming(response, info); return result.then(receiveInstantiatedSource, function (reason) { err("wasm streaming compile failed: " + reason); err("falling back to ArrayBuffer instantiation"); return instantiateArrayBuffer(receiveInstantiatedSource) }) }) } else { return instantiateArrayBuffer(receiveInstantiatedSource) } } if (Module["instantiateWasm"]) { try { var exports = Module["instantiateWasm"](info, receiveInstance); return exports } catch (e) { err("Module.instantiateWasm callback failed with error: " + e); return false } } instantiateAsync(); return {} } function callRuntimeCallbacks(callbacks) { while (callbacks.length > 0) { var callback = callbacks.shift(); if (typeof callback == "function") { callback(Module); continue } var func = callback.func; if (typeof func === "number") { if (callback.arg === undefined) { wasmTable.get(func)() } else { wasmTable.get(func)(callback.arg) } } else { func(callback.arg === undefined ? null : callback.arg) } } } function _abort() { abort() } var _emscripten_get_now = function () { return performance.now() } var _emscripten_get_now_is_monotonic = true; function setErrNo(value) { HEAP32[___errno_location() >> 2] = value; return value } function _clock_gettime(clk_id, tp) { var now; if (clk_id === 0) { now = Date.now() } else if ((clk_id === 1 || clk_id === 4) && _emscripten_get_now_is_monotonic) { now = _emscripten_get_now() } else { setErrNo(28); return -1 } HEAP32[tp >> 2] = now / 1e3 | 0; HEAP32[tp + 4 >> 2] = now % 1e3 * 1e3 * 1e3 | 0; return 0 } function _emscripten_run_script(ptr) { eval(UTF8ToString(ptr)) } __ATINIT__.push({ func: function () { ___wasm_call_ctors() } }); var asmLibraryArg = { "b": _abort, "c": _clock_gettime, "d": _emscripten_run_script, "a": wasmMemory }; var asm = createWasm(); var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function () { return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["f"]).apply(null, arguments) } ; var _jsWork = Module["_jsWork"] = function () { return (_jsWork = Module["_jsWork"] = Module["asm"]["g"]).apply(null, arguments) } ; var _main = Module["_main"] = function () { return (_main = Module["_main"] = Module["asm"]["h"]).apply(null, arguments) } ; var ___errno_location = Module["___errno_location"] = function () { return (___errno_location = Module["___errno_location"] = Module["asm"]["i"]).apply(null, arguments) } ; var calledRun; function ExitStatus(status) { this.name = "ExitStatus"; this.message = "Program terminated with exit(" + status + ")"; this.status = status } var calledMain = false; dependenciesFulfilled = function runCaller() { if (!calledRun) run(); if (!calledRun) dependenciesFulfilled = runCaller } ; function callMain(args) { var entryFunction = Module["_main"]; var argc = 0; var argv = 0; try { var ret = entryFunction(argc, argv); exit(ret, true) } catch (e) { if (e instanceof ExitStatus) { return } else if (e == "unwind") { noExitRuntime = true; return } else { var toLog = e; if (e && typeof e === "object" && e.stack) { toLog = [e, e.stack] } err("exception thrown: " + toLog); quit_(1, e) } } finally { calledMain = true } } function run(args) { args = args || arguments_; if (runDependencies > 0) { return } preRun(); if (runDependencies > 0) return; function doRun() { if (calledRun) return; calledRun = true; Module["calledRun"] = true; if (ABORT) return; initRuntime(); preMain(); if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"](); if (shouldRunNow) callMain(args); postRun() } if (Module["setStatus"]) { Module["setStatus"]("Running..."); setTimeout(function () { setTimeout(function () { Module["setStatus"]("") }, 1); doRun() }, 1) } else { doRun() } } Module["run"] = run; function exit(status, implicit) { if (implicit && noExitRuntime && status === 0) { return } if (noExitRuntime) { } else { EXITSTATUS = status; exitRuntime(); if (Module["onExit"]) Module["onExit"](status); ABORT = true } quit_(status, new ExitStatus(status)) } if (Module["preInit"]) { if (typeof Module["preInit"] == "function") Module["preInit"] = [Module["preInit"]]; while (Module["preInit"].length > 0) { Module["preInit"].pop()() } } var shouldRunNow = true; if (Module["noInitialRun"]) shouldRunNow = false; noExitRuntime = true; run(); // 增强的Worker消息处理 - 最大化棋面价值策略 self.onmessage = function(e) { const { board, dir, depth = 3, stage = 'middle' } = e.data; // 根据游戏阶段选择评估策略 let result; if (stage === 'cleanup') { // 清理阶段:专注清理小瓦片 result = evaluateMaximizeBoardValue(board); } else if (stage === 'survival') { // 生存模式:优先保持可玩性 const baseResult = Module._jsWork(board[0], board[1], board[2], board[3], dir); const valueScore = evaluateMaximizeBoardValue(board); result = baseResult * 0.7 + valueScore * 0.3; // 优先基础算法 } else if (stage === 'second8192') { // 第二个8192发展模式:平衡发展 const baseResult = Module._jsWork(board[0], board[1], board[2], board[3], dir); const valueScore = evaluateMaximizeBoardValue(board); result = baseResult * 0.6 + valueScore * 0.4; // 略偏向基础算法 } else if (stage === 'double8192' || stage === 'continue') { // 续局/终盘模式:最大化棋面价值 const baseResult = Module._jsWork(board[0], board[1], board[2], board[3], dir); const valueScore = evaluateMaximizeBoardValue(board); result = baseResult * 0.3 + valueScore * 0.7; // 价值策略占70%权重 } else if (stage === 'late') { // 后期模式:平衡发展与价值 const baseResult = Module._jsWork(board[0], board[1], board[2], board[3], dir); const valueScore = evaluateMaximizeBoardValue(board); result = baseResult * 0.5 + valueScore * 0.5; // 各占50% } else { // 早中期使用原始WASM算法 result = Module._jsWork(board[0], board[1], board[2], board[3], dir); } self.postMessage(result); }; `; // 创建 Blob 和 URL const workerBlob = new Blob([workerCode], { type: 'application/javascript' }); const workerUrl = URL.createObjectURL(workerBlob); // 创建工作线程 const workers = [ new Worker(workerUrl), new Worker(workerUrl), new Worker(workerUrl), new Worker(workerUrl) ]; let working = 0; // 当前正在执行的任务数量 let startTime, totalMove; // 记录 AI 启动时间 记录 AI 执行的总步数 let oldBoard = ""; let resultArray = [null, null, null, null]; for (let i = 0; i < 4; ++i) { // 每个工作线程在完成计算后会发送一个消息回来,包含当前方向的评估值。 workers[i].onmessage = ({ data }) => { working--; resultArray[i] = { move: i, result: data }; // 当所有方向计算完成后 if (working == 0) { // 执行最佳移动 resultArray.sort((a, b) => b.result - a.result); let bestMove = resultArray[0].move; canvasGame.handleMove(["up", "right", "down", "left"][bestMove]); // 更新步数 totalMove++; // 修改胜利检测:只有游戏结束才停止,忽略胜利状态(继续刷分) if (canvasGame.gameOver) { stopAI(); } else if (canvasGame.victory) { // 检测到胜利但不停止,继续刷分 console.log(`🎯 达成8192x2!继续刷分模式,当前分数: ${canvasGame.score || 0}`); if (aiRunning) step(); } else { if (aiRunning) step(); } } } } function currentState() { const result = new Uint16Array(4); for (let i = 0; i < 4; ++i) { for (let j = 0; j < 4; ++j) { const tile = canvasGame.board[i][j]; if (tile) result[i] = result[i] | ((Math.log2(tile) & 0xf) << (12 - 4 * j)); } } return result; } async function awaitBoardUpdate() { // 等待移动完成 let count = 0, flag = false; while (count < 300) { await new Promise(resolve => setTimeout(resolve, 10)); if (JSON.stringify(canvasGame.board) !== oldBoard) { oldBoard = JSON.stringify(canvasGame.board); flag = true; break; } count++; } return flag; } // 游戏阶段检测 - 支持"清理与巩固"模式 function getGameStage() { const board = canvasGame.board.flat().filter(x => x > 0); const maxTile = Math.max(...board); const emptySpaces = 16 - board.length; const totalScore = board.reduce((sum, tile) => sum + tile, 0); // 关键瓦片统计 const count8192 = board.filter(x => x === 8192).length; const count4096 = board.filter(x => x === 4096).length; const smallTiles = board.filter(x => x <= 32); const mediumTiles = board.filter(x => x >= 128 && x <= 512); const highValueTiles = board.filter(x => x >= 2048).length; // 动态策略选择 if (count8192 === 1) { if (smallTiles.length > 8 && emptySpaces >= 3) { // 清理模式:小瓦片过多且有空间 return { stage: 'cleanup', depth: 4, priority: 'cleanup_small_tiles' }; } else if (emptySpaces <= 2) { // 生存模式:空间不足时保持可玩性 return { stage: 'survival', depth: 5, priority: 'maintain_playability' }; } else { // 发展模式:继续向第二个8192努力 return { stage: 'second8192', depth: 4, priority: 'reach_second_8192' }; } } if (count8192 >= 2) { // 双8192模式:最大化终盘价值 return { stage: 'double8192', depth: 6, priority: 'maximize_board_value' }; } else if (count8192 === 1 && highValueTiles >= 6) { // 单8192+大量高价值瓦片:准备终盘 return { stage: 'continue', depth: 5, priority: 'prepare_endgame' }; } // 根据盘面密度和发展程度判断阶段 const boardDensity = board.length / 16; // 盘面密度 (0-1) const avgTileValue = totalScore / board.length; // 平均瓦片值 if (maxTile >= 4096 || avgTileValue > 200) { // 后期:冲击8192阶段 return { stage: 'late', depth: emptySpaces <= 4 ? 5 : 4, priority: 'reach_first_8192' }; } else if (maxTile >= 1024 || boardDensity > 0.7) { // 中期:稳健发展 return { stage: 'middle', depth: emptySpaces <= 6 ? 4 : 3, priority: 'stable_growth' }; } else { // 早期:快速发展 return { stage: 'early', depth: 2, priority: 'rapid_growth' }; } } async function step() { if (!await awaitBoardUpdate()) return stopAI(); const board = currentState(); const gameInfo = getGameStage(); // 危险局面检测 - 空格过少时需要更谨慎 const emptySpaces = canvasGame.board.flat().filter(x => x === 0).length; const searchDepth = emptySpaces <= 3 ? gameInfo.depth + 1 : gameInfo.depth; bestResult = 0; working = 4; bestMove = 0 | 4 * Math.random(); for (let i = 0; i < 4; ++i) { workers[i].postMessage({ board, dir: i, depth: searchDepth, stage: gameInfo.stage }); } } function toggleAI() { } function startAI() { totalMove = 0; startTime = Date.now(); document.getElementById("ai-start").textContent = "停止AI"; aiRunning = true; step(); toggleAI = stopAI; } function stopAI() { const endTime = Date.now(); const board = canvasGame.board.flat().filter(x => x > 0); const maxTile = Math.max(...canvasGame.board.flat()); const score = canvasGame.score || 0; const tiles8192 = board.filter(x => x === 8192).length; const mediumTiles = board.filter(x => x >= 128 && x <= 512); const boardValue = board.reduce((sum, tile) => sum + tile, 0); console.log(`=== AI性能统计 ===`); console.log(`已用时间: ${(endTime - startTime) / 1000} 秒`); console.log(`动作数: ${totalMove} 个`); console.log(`速度: ${totalMove * 1000 / (endTime - startTime)} 步/秒`); console.log(`最大数字: ${maxTile}`); console.log(`当前分数: ${score}`); console.log(`棋面价值: ${boardValue}`); console.log(`总合价值: ${score + boardValue}`); console.log(`8192数量: ${tiles8192}`); console.log(`中等瓦片: ${mediumTiles.length}个 (价值${mediumTiles.reduce((sum, tile) => sum + tile, 0)})`); // 25万分成就评估 const totalValue = score + boardValue; if (totalValue >= 250000) { console.log(`🏆 恭喜突破25万分!总价值: ${totalValue}`); } else if (totalValue >= 200000) { console.log(`🎯 接近25万分目标!当前: ${totalValue} (${(totalValue/250000*100).toFixed(1)}%)`); } if (tiles8192 >= 2) { console.log(`🎉 已达成8192x2!${mediumTiles.length > 3 ? '成功保留中等瓦片' : '可优化中等瓦片保护'}!`); } else if (tiles8192 === 1) { console.log(`🎯 已获得一个8192,继续努力!`); } document.getElementById("ai-start").textContent = "启动AI"; aiRunning = false; toggleAI = startAI; } toggleAI = startAI; function initButton() { const headerLeft = document.querySelector(".header-left"); const startBtn = document.createElement("button"); startBtn.textContent = "启动AI"; startBtn.id = "ai-start"; startBtn.addEventListener('click', () => toggleAI()); headerLeft.appendChild(startBtn); const stepBtn = document.createElement("button"); stepBtn.textContent = "下一步"; stepBtn.id = "ai-step"; stepBtn.addEventListener('click', () => step()); headerLeft.appendChild(stepBtn); const infoBtn = document.createElement("button"); infoBtn.textContent = "游戏信息"; infoBtn.id = "ai-info"; infoBtn.addEventListener('click', () => { const gameInfo = getGameStage(); const board = canvasGame.board.flat().filter(x => x > 0); const maxTile = Math.max(...board); const emptySpaces = canvasGame.board.flat().filter(x => x === 0).length; const tiles8192 = board.filter(x => x === 8192).length; const smallTiles = board.filter(x => x <= 32); const mediumTiles = board.filter(x => x >= 128 && x <= 512); const highValueTiles = board.filter(x => x >= 2048).length; const totalScore = board.reduce((sum, tile) => sum + tile, 0); const avgTileValue = totalScore / board.length; const boardDensity = board.length / 16; console.log(`=== 游戏状态分析 ===`); console.log(`游戏阶段: ${gameInfo.stage} (${gameInfo.priority})`); console.log(`搜索深度: ${gameInfo.depth}`); console.log(`最大数字: ${maxTile}`); console.log(`空格数量: ${emptySpaces}`); console.log(`8192数量: ${tiles8192}`); console.log(`小瓦片(≤32): ${smallTiles.length}`); console.log(`中等瓦片(128-512): ${mediumTiles.length}`); console.log(`高价值瓦片(≥2048): ${highValueTiles}`); console.log(`盘面密度: ${(boardDensity * 100).toFixed(1)}%`); console.log(`平均瓦片值: ${avgTileValue.toFixed(1)}`); console.log(`棋面总价值: ${totalScore}`); console.log(`当前分数: ${canvasGame.score || 0}`); // 阶段特定信息 if (gameInfo.stage === 'cleanup') { console.log(`🧹 清理模式:专注清理${smallTiles.length}个小瓦片,为终盘腾出空间`); console.log(`📊 清理效率: ${((16 - smallTiles.length) / 16 * 100).toFixed(1)}%`); } else if (gameInfo.stage === 'survival') { console.log(`⚠️ 生存模式:空间不足(${emptySpaces}格),优先保持可玩性`); console.log(`🔄 合并可能性评估中...`); } else if (gameInfo.stage === 'second8192') { const count4096 = board.filter(x => x === 4096).length; console.log(`🎯 第二8192模式:当前4096数量=${count4096},空间=${emptySpaces}格`); console.log(`📈 继续发展大瓦片链条`); } else if (gameInfo.stage === 'double8192') { console.log(`🎯 终盘模式:保持8192x2状态,最大化棋面价值`); console.log(`💎 中等瓦片价值: ${mediumTiles.reduce((sum, tile) => sum + tile, 0)}`); } else if (tiles8192 === 1) { console.log(`📈 单8192状态,策略将根据棋盘情况动态调整`); } // 25万分潜力评估 const potentialScore = totalScore + (canvasGame.score || 0); if (potentialScore > 200000) { console.log(`🏆 25万分潜力:${(potentialScore / 250000 * 100).toFixed(1)}%`); } }); headerLeft.appendChild(infoBtn); } initButton(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址