背景

前段时间,闲暇时间玩了微信中的一款游戏叫 最强连一连,玩了一段时间发现手动去玩不知道要玩几个月,于是就开始各种找资料。找了几个代码,最终找到这个 大神的代码,他写了一篇文章叫 《微信小程序 最强连一连攻略 程序自动玩》,折腾了一番下来我也成功的刷完了全部关卡。

准备工作

  • 安卓手机一台
  • 电脑安装好 ADB

细节记录

  1. 先用安卓手机原装线连接PC,安装好对应的驱动。说到这里可能会有很多坑,我手上这台手机是 小米8 se,安装驱动费了小半天的时间找。
  2. 在PC上安装ADB,配置好对应的环境变量。
    配置完成之后,打开cmd 输入 adb version


3. 在cmd 中输入 adb devices , 如果一切正常这里会显示你的devices的设备号。

如果找不到,请参考以下这个链接。
adb devices找不到设备?设备VID缺失解决方案

开始自动玩游戏

手机:小米8 se
手机分辨率:2244 * 1080
电脑系统: windows7 64位

最开始用代码去玩游戏的时候,需要看原来博客中的一张图

为什么要看这张图呢,图中的 W 和 h 都是需要设置的,而且不同的关卡,这个值会变化。
说到这里我们需要关注四个值,W 和 h , 几行,几列
两列之间的值,两行之间的值。

一般情况,两列之间的值 = 两行之间的值。

部分代码如下

public final static char BAN = ' ', EMPTY = '□', EXIST = '■';// private static int startH = 537, startW = 170, offsetH = 145, offsetW = 145, rowSize = 8, colSize = 6; 21级 52 关private static int startH = 541, startW = 170, offsetH = 145, offsetW = 145, rowSize = 7, colSize = 6;// 自动玩public static void autoPlay() {try {if (Files.notExists(Paths.get("D:/link")))Files.createDirectory(Paths.get("D:/link"));} catch (IOException e) {e.printStackTrace();}while (true) {long startTime = System.currentTimeMillis();if (screenshot()) {GameStatus gameStatus = analysisScreenshot();if (gameStatus != null) {NodeTree nodeTree = new NodeTree(gameStatus.getStatus(), gameStatus.getCount(), gameStatus.getStartRow(), gameStatus.getStartCol());Node[] nodes = nodeTree.DFS();if (nodes != null) {play(nodes);nextGame();} else {System.out.println("游戏搜索失败,重新开始");}} else {System.out.println("游戏读取失败,重新开始");}System.out.println("耗费总时长:" + (System.currentTimeMillis() - startTime) + "毫秒\n");}}}

从以上代码,可以知道代码中 private static int startH = 541, startW = 170, offsetH = 145, offsetW = 145, rowSize = 7, colSize = 6;

startH : 画面顶部到第一行中间位置的高度
startW :画面左侧到第一列中金位置的宽度
offsetH :两列之间的值
offsetW :两行之间的值
rowSize :画面中的行数
colSize : 画面中的列数

以上的值是随着关卡变化而变化的,据我观察一般20-50关之内变化不大。

另外一点,需要说明一下,手机的分辨率也会影响游戏画面的呈现,比如用我的手机打开29级52关的时候两边格子只有显示一半了。

另外还有一个问题,相同的代码在windows7 下运行会一直耗内存,本机电脑16G ,代码一直运行的时候会吃内存吃到 10.5G 左右就不在吃内存了。

而把代码放在windows10 里面运行,丝毫没有吃内存的迹象,关于这点我也不知道怎么解释问了 代码原作者也表示不清楚,不过并不影响刷游戏…

在刷的过程中,连接手机之后建议使用 传输文件 模式 (不使用这个模式,后来证实也是可以的)

源码部分

以下代码 均为原作者所有

NodeUtil.java

package com.example.lianlian;import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;import javax.imageio.ImageIO;/*** @Auther: Administrator* @Date: 2019-02-22* @Description:*/
public class NodeUtil {public final static char BAN = ' ', EMPTY = '□', EXIST = '■';// private static int startH = 537, startW = 170, offsetH = 145, offsetW = 145, rowSize = 8, colSize = 6; 21级 52 关private static int startH = 541, startW = 170, offsetH = 145, offsetW = 145, rowSize = 7, colSize = 6;// 自动玩public static void autoPlay() {try {if (Files.notExists(Paths.get("D:/link")))Files.createDirectory(Paths.get("D:/link"));} catch (IOException e) {e.printStackTrace();}while (true) {long startTime = System.currentTimeMillis();if (screenshot()) {GameStatus gameStatus = analysisScreenshot();if (gameStatus != null) {NodeTree nodeTree = new NodeTree(gameStatus.getStatus(), gameStatus.getCount(), gameStatus.getStartRow(), gameStatus.getStartCol());Node[] nodes = nodeTree.DFS();if (nodes != null) {play(nodes);nextGame();} else {System.out.println("游戏搜索失败,重新开始");}} else {System.out.println("游戏读取失败,重新开始");}System.out.println("耗费总时长:" + (System.currentTimeMillis() - startTime) + "毫秒\n");}}}// 截屏到电脑private static boolean screenshot() {try {Runtime.getRuntime().exec("adb shell /system/bin/screencap -p /sdcard/most_link_link.png").waitFor();Runtime.getRuntime().exec("adb pull /sdcard/most_link_link.png D:/link").waitFor();} catch (IOException e) {e.printStackTrace();return false;} catch (InterruptedException e) {e.printStackTrace();return false;}return true;}// 分析游戏状态public static GameStatus analysisScreenshot() {GameStatus gameStatus = new GameStatus();char[][] status = new char[rowSize][colSize];int count = 0, startPoint = 0;try {BufferedImage screenshot = ImageIO.read(new File("D:/link/most_link_link.png"));
//          Graphics graphics = screenshot.getGraphics();
//          graphics.setColor(Color.red);
//          graphics.setFont(new Font("华文行楷", Font.BOLD, 100));for (int h = startH, rowIndex = 0; rowIndex < status.length && startPoint <= 1; h += offsetH, rowIndex++) {for (int w = startW, colIndex = 0; colIndex < status[rowIndex].length && startPoint <= 1; w += offsetW, colIndex++) {int rgb = screenshot.getRGB(w, h);
//                  graphics.drawString(".", w, h);if (rgb == -3355444) { // -3355444灰色status[rowIndex][colIndex] = EMPTY;count++;} else if (rgb != -14472389) { // -14472389背景色status[rowIndex][colIndex] = EXIST;count++;gameStatus.setStartRow(rowIndex);gameStatus.setStartCol(colIndex);startPoint++;} else {status[rowIndex][colIndex] = BAN;}}}
//          ImageIO.write(screenshot, "png", new FileOutputStream("G:/link/draw_point.png"));gameStatus.setCount(count);gameStatus.setStatus(status);} catch (IOException e) {e.printStackTrace();} finally {printStatus(status);}return startPoint == 1 ? gameStatus : null;}// 点击关卡灰格private static void play(Node[] nodes) {try {for (int i = 1; i < nodes.length; i++) {int j = i;while (j + 1 < nodes.length && (nodes[i].getRow() == nodes[j + 1].getRow() || nodes[i].getCol() == nodes[j + 1].getCol())) {j++;}String command = String.format("adb shell input swipe %d %d %d %d", nodes[i].getCol() * offsetW + startW, nodes[i].getRow() * offsetH + startH, nodes[j].getCol() * offsetW + startW, nodes[j].getRow() * offsetH + startH);System.out.println(command);Runtime.getRuntime().exec(command).waitFor();i = j;}//Thread.sleep(300);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}// 下一关private static void nextGame() {try {//Runtime.getRuntime().exec("adb shell input tap 929 660").waitFor(); // 关闭双倍奖励//Runtime.getRuntime().exec("adb shell input tap 540 1600").waitFor(); // 下一关Runtime.getRuntime().exec("adb shell input tap 925 822").waitFor(); // 关闭双倍奖励Runtime.getRuntime().exec("adb shell input tap 540 1700").waitFor(); // 下一关} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}// 打印盘面状态public static void printStatus(char[][] status) {for (int row = 0; row < status.length; row++) {for (int col = 0; col < status[row].length - 1; col++) {System.out.format("%c ", status[row][col]);}System.out.format("%c%n", status[row][status[row].length - 1]);}}/* public static void printStatus(char[][] status) {for (int row = 0; row < status.length; row++) {for (int col = 0; col < status[row].length; col++) {System.out.print(status[row][col]);if (col != status[row].length - 1) {System.out.print(" ");}}System.out.println();}}*/private static class GameStatus {private char[][] status;private int count, startRow, startCol; // count方格数量public char[][] getStatus() {return status;}public void setStatus(char[][] status) {this.status = status;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}public int getStartRow() {return startRow;}public void setStartRow(int startRow) {this.startRow = startRow;}public int getStartCol() {return startCol;}public void setStartCol(int startCol) {this.startCol = startCol;}}}

NodeTree.java

package com.example.lianlian;/*** @Auther: Administrator* @Date: 2019-02-22* @Description:*/
public class NodeTree {private char[][] status;private Node[] nodes;private int count, nodesIndex, sum; // count方格数量,sum搜索的节点数量public NodeTree(char[][] status, int count, int startRow, int startCol) {this.status = status;this.count = count;this.nodes = new Node[count];Node root = new Node();root.setRow(startRow);root.setCol(startCol);this.nodes[nodesIndex] = root;this.sum++;this.count--;}private int[][] directions = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; // 上、右、下、左// 深度优先搜索public Node[] DFS() {long startTime = System.currentTimeMillis();OVER:while (nodes[0].getDirectionCount() < directions.length) {Node parent = nodes[nodesIndex];int direction = parent.getDirection();while (true) {if (nodesIndex > 0 && parent.getDirectionCount() >= directions.length) { // 节点改变方向次数大于等于4次,即4个方向均尝试过,回退一个节点status[parent.getRow()][parent.getCol()] = NodeUtil.EMPTY;count++;parent = nodes[--nodesIndex]; // 回退一个节点parent.setDirection((parent.getDirection() + 1) % directions.length); // 回退的节点改变方向parent.setDirectionCount(parent.getDirectionCount() + 1);break;}Node child = nextStep(parent, direction);if (child != null) {nodes[++nodesIndex] = parent = child;sum++;if (--count == 0) {System.out.format("搜索时间:%d毫秒, 搜索的节点数量:%d%n", System.currentTimeMillis() - startTime, sum);break OVER;}} else {direction = (direction + 1) % directions.length;parent.setDirection(direction);parent.setDirectionCount(parent.getDirectionCount() + 1);}}}return count == 0 ? nodes : null;}// 走一步private Node nextStep(Node parent, int direction) {int childRow = parent.getRow() + directions[direction][0];int childCol = parent.getCol() + directions[direction][1];if (childRow < 0 || childRow >= status.length || childCol < 0 || childCol >= status[0].length || status[childRow][childCol] != NodeUtil.EMPTY) {return null;}Node child = nodes[nodesIndex + 1]; // 之前丢弃的节点重新利用,减少new的次数if (child != null) {child.setDirectionCount(0);} else {child = new Node();}child.setRow(childRow);child.setCol(childCol);child.setDirection(direction);status[childRow][childCol] = NodeUtil.EXIST;return child;}}

Node.java

package com.example.lianlian;/*** @Auther: Administrator* @Date: 2019-02-22* @Description:*/
public class Node {private int row, col, direction, directionCount; // directionCount累计节点改变方向次数public int getRow() {return row;}public void setRow(int row) {this.row = row;}public int getCol() {return col;}public void setCol(int col) {this.col = col;}public int getDirection() {return direction;}public void setDirection(int direction) {this.direction = direction;}public int getDirectionCount() {return directionCount;}public void setDirectionCount(int directionCount) {this.directionCount = directionCount;}}

MostLinkLinkTest.java

package com.example.lianlian;/*** @Auther: Administrator* @Date: 2019-02-22* @Description:*/
public class MostLinkLinkTest {public static void main(String[] args) {//NodeUtil.screenshot();NodeUtil.autoPlay();}
}

更多游戏解析代码,可以关注 这个大神
https://blog.csdn.net/lcl1997

以上就是所有的代码了,如果不明白的地方可以加入我的Q群: 816175200

微信小程序 最强连一连攻略 程序自动玩 续集相关推荐

  1. 微信小程序 最强连一连攻略 程序自动玩

    微信小程序 最强连一连攻略 程序自动玩 步骤 1.截屏 2.分析游戏状态 3.搜索 4.自动触摸滑动过关路径 代码 测试结果 注意 步骤 程序将手动玩游戏的过程分四步完成 1.截屏 将手机屏幕截屏保存 ...

  2. opencv制作微信小游戏 最强连一连 辅助(1)--概述

    之前在b站上面看到一个人发布的一个视频 https://www.bilibili.com/video/av44383086?from=search&seid=34877549027742780 ...

  3. opencv制作微信小游戏 最强连一连 辅助(2)--dfs深度优先搜索算法

    深度优先搜索算法还是大二上数据结构的时候学的,工作以后都忘得差不多了.赶紧回来温习一下吧. 深度优先搜索的算法的 入参是一个地图(一般可以用二维数组表示)和一个起始点. 比如 这个就是一个5*5的二维 ...

  4. 微信小游戏最强连一连自动完成

    前言 参考 你看过/写过哪些有意思的代码?--江湖危险赶快逃的答案 adb 详细使用文档 配置环境 python adb 代码分析 函数 path_count(q) curr_point(q) eva ...

  5. opencv制作微信小游戏 最强连一连 辅助(3)--opencv matchTemplete多目标匹配

    上一篇我写了如何用dfs深度优先搜索算法来求解,入参是一个二维数组,这个二维数组是人为手动赋值的 这一篇我们来讲如何自动来完成这一过程. 也就是说 入参是一个 游戏的画面,出参是一个二维数组 如下图: ...

  6. 原创 | 微信小游戏“跳一跳”改分攻略!

    转载自:http://appscan.io/discover-discuss.html?id=1123859495 改分关键步骤: 电脑安装抓包软件,手机设置https代理到电脑 通过抓包软件,抓包拿 ...

  7. 程序员神级跳槽攻略:什么时候该跳?做什么准备?到哪里找工作?

    为什么80%的码农都做不了架构师?>>>    1.引言 每年的3.4月份都是求职高峰时期,目前已进入6.7月份了,你已经成功换工作了吗? 这次我们想聊的,就是程序员跳槽这件事儿,我 ...

  8. [转]程序员神级跳槽攻略:什么时候该跳?做什么准备?到哪里找工作?

    1.引言 每年的3.4月份都是求职高峰时期,目前已进入6.7月份了,你已经成功换工作了吗? 这次我们想聊的,就是程序员跳槽这件事儿,我打算从三个方面来说: 1)程序员什么时候该跳槽? 2)跳槽前你需要 ...

  9. 《Java程序员职场全攻略:从小工到专家》连载十二:大家都是个什么身价

    大家都是个什么身价 根治这种症状的第一步,就是让其彻底看清大家到底都是什么样的身价.不过这服药可不好熬出来,薪水这个问题,从哪个角度讲可能都不一样.横向可以分为不同学历.不同技术.不同公司.不同职位. ...

最新文章

  1. 【Sql Server】DateBase-事务
  2. 基于深度学习的三维姿态估计
  3. Membership角色与权限管理
  4. 与孩子一起学编程 python_【和孩子一起学编程】 python笔记--第五天
  5. Harbor API整理:获取项目下的所有镜像
  6. Android使用Intent实现拨打电话的动作
  7. tensorflow 启动Session(tf.Session(),tf.InteractivesSession(),tf.train.Supervisor().managed_session() )
  8. 神舟电脑装linux双系统,个人windows10和Ubuntu18.04游戏笔记本uefi双磁盘双系统安装过程...
  9. C++ opengl 绘制地面
  10. 利用LDA主题模型的生成过程仿真数据
  11. python定义fmax_Python标准库:内置函数max(iterable, *[, key, default])说明
  12. leetcode 1154 一年中的第几天
  13. 数字展示领域该这样用 沉浸式方案应用解读
  14. tiff怎么批量转化成jpg或png?
  15. 风变编程python离线版_如何看待风变编程的Python网课
  16. 计算机一级ppt加水印,2017年计算机一级WPS辅导:WPSOffice2007中插入水印和改变背景色...
  17. 电子警察的系统结构和功能设计
  18. 乐视尚酷版无线手柄PC驱动 手柄通用驱动教程
  19. 【那些年我们用过的Redis】还记得大明湖畔那些Redis数据吗?
  20. Linux: 李纳斯·托沃兹(Linus Torvalds): “使用KDE”(转)

热门文章

  1. 算法分析(1)-增长数量级分类总结
  2. python读取图片到数组
  3. 爬虫实战(二) 用Python爬取网易云歌单
  4. 2651: 城市改建 树形DP
  5. OA办公自动化系统的设计与实现
  6. bpf 跟踪功能——上手 USDT
  7. Android4.0 实现组合键重启手机
  8. ASO搜索指数是什么?对应搜索量吗?
  9. 图像形态学操作之腐蚀
  10. 关于使用西电2019年3月修订版Latex毕业论文模板的记录贴