您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Lie back and watch the dumb bot play!
// ==UserScript== // @name 2048bot // @namespace http://tampermonkey.net/ // @version 0.9415 // @description Lie back and watch the dumb bot play! // @author boynextdesk // @match https://play2048.co/* // @icon https://play2048.co/favicon.ico // @grant none // @license GNU General Public License v3.0 // ==/UserScript== /* * 128 64 32 16 * 64 32 16 8 * 32 16 8 4 * 16 8 4 2 * * */ (function() { // todo: inspect whether game is over // todo: train strategy after game-over // todo: set speed and strategy through page // todo: beautify layout // todo: everlasting game - auto retry until winning // todo: bundle direction-ava functinos into an object to global users 'use strict'; const eventUp = new KeyboardEvent('keydown', { key: "w", keyCode: 87, which: 87, code: "KeyW", location: 0, description: "w" }); const eventLeft = new KeyboardEvent('keydown', { key: "a", keyCode: 65, which: 65, code: "KeyA", location: 0, description: "a" }); const eventRight = new KeyboardEvent('keydown', { key: "d", keyCode: 68, which: 68, code: "KeyD", location: 0, description: "d" }); const eventDown = new KeyboardEvent('keydown', { key: "s", keyCode: 83, which: 83, code: "KeyS", location: 0, description: "s" }); // thanks to https://zeit.co/blog/async-and-await function sleep (time) { return new Promise((resolve) => setTimeout(resolve, time)); } function lose() { return document.getElementsByClassName("game-message game-over")[0] != null } function win() { return document.getElementsByClassName("game-message game-win")[0] != null } function over() { return lose() || win() } function inspect() { const board = Array(); for(let j = 1 ; j <= 4 ; j++) // row { const unit4 = Array(); for(let i = 1 ; i <= 4 ; i++) //column { const className = "tile-position-"+i+"-"+j const tiles = document.getElementsByClassName(className) const len = tiles.length const tile = tiles[len - 1] /// console.log(className) let val = 0; if(tile != null){ val = tile.firstChild.lastChild.nodeValue val = Number(val) /// console.log(val) } unit4[i] = val } board[j] = unit4 } return board } const aboveBox = document.getElementsByClassName("above-game")[0]; const btnTemplate = document.getElementsByClassName("restart-button")[0]; let speed = 10; let speedIndex = 0; let switchU = true; aboveBox.appendChild(btnTemplate.cloneNode(false)); aboveBox.appendChild(btnTemplate.cloneNode(false)); aboveBox.appendChild(btnTemplate.cloneNode(false)); // const btns = document.getElementsByClassName("restart-button"); // const btnStartAuto = btns[1]; const startText = document.createTextNode("Start Auto"); btnStartAuto.appendChild(startText) // const btnStopAuto = btns[2]; const stopText = document.createTextNode("Stop Auto"); btnStopAuto.appendChild(stopText) // const btnSpeedAuto = btns[3]; const speedText = document.createTextNode("Change Speed"); btnSpeedAuto.appendChild(speedText) // let moveOn = false; let moveCnt = 0; let globalBoard = null; document.tagName = "not input" const strategy01 = function () { const num = Math.random(); let dispatchee = null; moveCnt += 1 const rate = 1 - Math.min(48 / moveCnt, 0.8) const downL = 0.02 * rate const rightL = downL + 0.02 * rate; if (num < downL) { dispatchee = eventDown; console.log("down"); } else if (num < rightL) { dispatchee = eventRight; console.log("right"); } else if (switchU) { dispatchee = eventLeft console.log("left") switchU = false } else { dispatchee = eventUp console.log("up") switchU = true } return dispatchee }; const strategy02 = function () { const board = globalBoard if(board == null) return eventLeft const directionAvailable = function(offsetI, offsetJ){ for(let i = 1 ; i <= 4 ; i++){ for(let j = 1 ; j <= 4 ; j++){ const ni = i + offsetI const nj = j + offsetJ if(ni < 1 || ni > 4) continue if(nj < 1 || nj > 4) continue if(board[i][j] === 0) continue; if(board[ni][nj] === board[i][j] || board[ni][nj] === 0) return true } } return false } const dir = [[0, -1], [-1, 0], [1, 0], [0, 1]] const msg = ["left", "up", "down", "right"] const funcArr = [eventLeft, eventUp, eventDown, eventRight] for(let i = 0 ; i < 4 ; i++){ const con = directionAvailable(dir[i][0], dir[i][1]) if(con){ console.log(msg[i]) return funcArr[i] } //console.log(msg[i] + " unavailable") } return funcArr[0] } const moveOneKey = function () { if (!moveOn) { console.log("Cancelled.") return } const dispatchee = strategy02(); document.dispatchEvent(dispatchee) }; const startListener = async function () { console.log("start") moveOn = true; while (moveOn) { await sleep(10 * speed).then(() => { if(over()){ moveOn = false console.log("Game over.") } const board = inspect(); console.log(board) globalBoard = board }) await sleep(70 * speed).then(moveOneKey) } }; const stopListener = function () { moveOn = false; moveCnt = 0 } const speedListener = function () { const speeds = [10, 5, 1]; const words = ["switch to low speed", "switch to fast speed", "switch to super fast speed"]; const len = 3 speedIndex = (speedIndex + 1) % len speed = speeds[speedIndex] console.log(words[speedIndex]) } btnStartAuto.addEventListener('click', startListener) btnStopAuto.addEventListener('click', stopListener) btnSpeedAuto.addEventListener('click', speedListener) })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址