您的位置:首页 > 移动开发 > 微信开发

纯JAVA实现微信跳一跳刷分

2018-01-06 19:09 337 查看
很多人都在找跳一跳刷分辅助,网上大多是python写的,参考大神@忆虎思甜http://blog.csdn.net/lihushiwoa/article/details/78942322的博客,又整理了一些细节,以及自己遇到的坑

1.本人windows7 64位

2.跑代码使用工具eclipse mars2 , java环境jdk1.7

3.重点:下载adb驱动,最好是1.0.31版本,将adb文件夹放在任意文件夹,配个系统环境变量,这里配置变量是为了代码使用cmd命令截图的时候,能够找到adb路径,下图是配置,我的配置是android,将;%android%放到path里



4.电脑连接手机测试,出现一串字符,如13*76a   device ,表示连接上了,重点是连不上的情况,adb device offline表示adb没问题,手机处于离线状态。这时候打开任务管理器,关掉一切金山,360,qq管家之类进程,本人并没有安装任何这类软件,但是仍有一个QQ的程序,关掉就好了。(可能还有端口占用问题,自行解决)

5.电脑连上手机以后,测试cmd窗口截图功能,手机选择调试模式下,打开微信跳一跳小游戏,执行以下命令:

adb shell /system/bin/screencap -p /sdcard/screenshot.png(保存到SDCard)
adb pull /sdcard/screenshot.png d:/screenshot.png(保存到电脑)
然后到D盘目录下检查是否截图成功。

6.到这里如果截图成功的话,就可以跑代码了,代码无需改动,打开跳一跳游戏,直接运行main方法就行了。原理就是每次跳前,截图计算两图中点的距离。本代码只是辅助,本人测试三次,一次1500多分,两次700多分,可能需要多次刷才能刷出高分,只是感兴趣使用代码刷分,请勿认真。

7.以下是原博主详细代码,无需改动:

package com.yihusitian.gamehelper;  

 

import java.awt.image.BufferedImage;  

import java.io.BufferedReader;  

import java.io.File;  

import java.io.IOException;  

import java.io.InputStreamReader;  

import java.util.Arrays;  

import java.util.concurrent.TimeUnit;  

 

import javax.imageio.ImageIO;  

 

/**

 * 参考知乎   

 *  

 *  @link <a href="https://zhuanlan.zhihu.com/p/32452473" target="_blank">https://zhuanlan.zhihu.com/p/32452473</a>

 *  

 * 跳一跳辅助

 *  

 * @author LeeHo

 */  

public class JumpJumpHelper  

{  

 

    private static final String IMAGE_NAME              = "current.png";  

 

    private static final String STORE_DIR               = "d:/jump_screencapture";  

 

    //数量  

    private static final int    imageLengthLength       = 5;  

 

    //存放图片的大小  

    private static final long[] imageLength             = new long[imageLengthLength];  

 

    private final RGBInfo       rgbInfo                 = new RGBInfo();  

 

    private final String[]      ADB_SCREEN_CAPTURE_CMDS =  

                                                        { "adb shell screencap -p /sdcard/" + IMAGE_NAME,  

            "adb pull /sdcard/current.png " + STORE_DIR };  

 

    //截屏中游戏分数显示区域最下方的Y坐标,300是 1920x1080的值,根据实际情况修改  

    private final int           gameScoreBottomY        = 300;  

 

    //按压的时间系数,可根据具体情况适当调节  

    private final double        pressTimeCoefficient    = 1.35;  

 

    //按压的起始点坐标,也是再来一局的起始点坐标  

    private final int           swipeX                  = 550;  

 

    private final int           swipeY                  = 1580;  

 

    //二分之一的棋子底座高度  

    private final int           halfBaseBoardHeight     = 20;  

 

    //棋子的宽度,从截屏中量取,自行调节  

    private final int           halmaBodyWidth          = 74;  

 

    //游戏截屏里的两个跳板的中点坐标,主要用来计算角度,可依据实际的截屏计算,计算XY的比例  

    private final int           boardX1                 = 813;  

 

    private final int           boardY1                 = 1122;  

 

    private final int           boardX2                 = 310;  

 

    private final int           boardY2                 = 813;  

 

    /**

     * 获取跳棋以及下一块跳板的中心坐标

     *

     * @return

     * @author LeeHo

     * @throws IOException

     * @update 2017年12月31日 下午12:18:22

     */  

    private int[] getHalmaAndBoardXYValue(File currentImage) throws IOException  

    {  

        BufferedImage bufferedImage = ImageIO.read(currentImage);  

        int width = bufferedImage.getWidth();  

        int height = bufferedImage.getHeight();  

        System.out.println("宽度:" + width + ",高度:" + height);  

        int halmaXSum = 0;  

        int halmaXCount = 0;  

        int halmaYMax = 0;  

        int boardX = 0;  

        int boardY = 0;  

        //从截屏从上往下逐行遍历像素点,以棋子颜色作为位置识别的依据,最终取出棋子颜色最低行所有像素点的平均值,即计算出棋子所在的坐标  

        for (int y = gameScoreBottomY; y < height; y++)  

        {  

            for (int x = 0; x < width; x++)  

            {  

                processRGBInfo(bufferedImage, x, y);  

                int rValue = this.rgbInfo.getRValue();  

                int gValue = this.rgbInfo.getGValue();  

                int bValue = this.rgbInfo.getBValue();  

                //根据RGB的颜色来识别棋子的位置,  

                if (rValue > 50 && rValue < 60 && gValue > 53 && gValue < 63 && bValue > 95 && bValue < 110)  

                {  

                    halmaXSum += x;  

                    halmaXCount++;  

                    //棋子底行的Y坐标值  

                    halmaYMax = y > halmaYMax ? y : halmaYMax;  

                }  

            }  

        }  

 

        if (halmaXSum != 0 && halmaXCount != 0)  

        {  

            //棋子底行的X坐标值  

            int halmaX = halmaXSum / halmaXCount;  

            //上移棋子底盘高度的一半  

            int halmaY = halmaYMax - halfBaseBoardHeight;  

            //从gameScoreBottomY开始  

            for (int y = gameScoreBottomY; y < height; y++)  

            {  

                processRGBInfo(bufferedImage, 0, y);  

                int lastPixelR = this.rgbInfo.getRValue();  

                int lastPixelG = this.rgbInfo.getGValue();  

                int lastPixelB = this.rgbInfo.getBValue();  

                //只要计算出来的boardX的值大于0,就表示下个跳板的中心坐标X值取到了。  

                if (boardX > 0)  

                {  

                    break;  

                }  

                int boardXSum = 0;  

                int boardXCount = 0;  

                for (int x = 0; x < width; x++)  

                {  

                    processRGBInfo(bufferedImage, x, y);  

                    int pixelR = this.rgbInfo.getRValue();  

                    int pixelG = this.rgbInfo.getGValue();  

                    int pixelB = this.rgbInfo.getBValue();  

                    //处理棋子头部比下一个跳板还高的情况  

                    if (Math.abs(x - halmaX) < halmaBodyWidth)  

                    {  

                        continue;  

                    }  

 

                    //从上往下逐行扫描至下一个跳板的顶点位置,下个跳板可能为圆形,也可能为方框,取多个点,求平均值  

                    if ((Math.abs(pixelR - lastPixelR) + Math.abs(pixelG - lastPixelG) + Math.abs(pixelB - lastPixelB)) > 10)  

                    {  

                        boardXSum += x;  

                        boardXCount++;  

                    }  

                }  

 

                if (boardXSum > 0)  

                {  

                    boardX = boardXSum / boardXCount;  

                }  

            }  

 

            //按实际的角度来算,找到接近下一个 board 中心的坐标  

            boardY = (int) (halmaY - Math.abs(boardX - halmaX) * Math.abs(boardY1 - boardY2)  

                    / Math.abs(boardX1 - boardX2));  

            if (boardX > 0 && boardY > 0)  

            {  

                int[] result = new int[4];  

                //棋子的X坐标  

                result[0] = halmaX;  

                //棋子的Y坐标  

                result[1] = halmaY;  

                //下一块跳板的X坐标  

                result[2] = boardX;  

                //下一块跳板的Y坐标  

                result[3] = boardY;  

                return result;  

            }  

        }  

 

        return null;  

    }  

 

    /**

     * 执行命令

     *

     * @param command

     * @author LeeHo

     * @update 2017年12月31日 下午12:13:39

     */  

    private void executeCommand(String command)  

    {  

        Process process = null;  

        try  

        {  

            process = Runtime.getRuntime().exec(command);  

            System.out.println("exec command start: " + command);  

            process.waitFor();  

            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream
ae63
()));  

            String line = bufferedReader.readLine();  

            if (line != null)  

            {  

                System.out.println(line);  

            }  

            System.out.println("exec command end: " + command);  

        }  

        catch (Exception e)  

        {  

            e.printStackTrace();  

        }  

        finally  

        {  

            if (process != null)  

            {  

                process.destroy();  

            }  

        }  

    }  

 

    /**

     * ADB获取安卓截屏

     *  

     * @author LeeHo

     * @update 2017年12月31日 下午12:11:42

     */  

    private void executeADBCaptureCommands()  

    {  

        for (String command : ADB_SCREEN_CAPTURE_CMDS)  

        {  

            executeCommand(command);  

        }  

    }  

 

    /**

     * 跳一下

     *

     * @param distance

     * @author LeeHo

     * @update 2017年12月31日 下午12:23:19

     */  

    private void doJump(double distance)  

    {  

        System.out.println("distance: " + distance);  

        //计算按压时间,最小200毫秒  

        int pressTime = (int) Math.max(distance * pressTimeCoefficient, 200);  

        System.out.println("pressTime: " + pressTime);  

        //执行按压操作  

        String command = String.format("adb shell input swipe %s %s %s %s %s", swipeX, swipeY, swipeX, swipeY,  

                pressTime);  

        System.out.println(command);  

        executeCommand(command);  

    }  

 

    /**

     * 再来一局

     *  

     * @author LeeHo

     * @update 2017年12月31日 下午12:47:06

     */  

    private void replayGame()  

    {  

        String command = String.format("adb shell input tap %s %s", swipeX, swipeY);  

        executeCommand(command);  

    }  

 

    /**

     * 计算跳跃的距离,也即两个点之间的距离

     *

     * @param halmaX

     * @param halmaY

     * @param boardX

     * @param boardY

     * @return

     * @author LeeHo

     * @update 2017年12月31日 下午12:27:30

     */  

    private double computeJumpDistance(int halmaX, int halmaY, int boardX, int boardY)  

    {  

        return Math.sqrt(Math.pow(Math.abs(boardX - halmaX), 2) + Math.pow(Math.abs(boardY - halmaY), 2));  

    }  

 

    public static void main(String[] args)  

    {  

        try  

        {  

            File storeDir = new File(STORE_DIR);  

            if (!storeDir.exists()) {  

               boolean flag = storeDir.mkdir();  

               if (!flag) {  

                   System.err.println("创建图片存储目录失败");  

                   return;  

               }  

            }  

              

            JumpJumpHelper jumpjumpHelper = new JumpJumpHelper();  

            //执行次数  

            int executeCount = 0;  

            for (;;)  

            {  

                //执行ADB命令,获取安卓截屏  

                jumpjumpHelper.executeADBCaptureCommands();  

                File currentImage = new File(STORE_DIR, IMAGE_NAME);  

                if (!currentImage.exists())  

                {  

                    System.out.println("图片不存在");  

                    continue;  

                }  

 

                long length = currentImage.length();  

                imageLength[executeCount % imageLengthLength] = length;  

                //查看是否需要重新开局  

                jumpjumpHelper.checkDoReplay();  

                executeCount++;  

                System.out.println("当前第" + executeCount + "次执行!");  

                //获取跳棋和底板的中心坐标  

                int[] result = jumpjumpHelper.getHalmaAndBoardXYValue(currentImage);  

                if (result == null)  

                {  

                    System.out.println("The result of method getHalmaAndBoardXYValue is null!");  

                    continue;  

                }  

                int halmaX = result[0];  

                int halmaY = result[1];  

                int boardX = result[2];  

                int boardY = result[3];  

                System.out.println("halmaX: " + halmaX + ", halmaY: " + halmaY + ", boardX: " + boardX + ", boardY: "  

                        + boardY);  

                //计算跳跃的距离  

                double jumpDistance = jumpjumpHelper.computeJumpDistance(halmaX, halmaY, boardX, boardY);  

                jumpjumpHelper.doJump(jumpDistance);  

                //每次停留2.5秒  

                TimeUnit.MILLISECONDS.sleep(2500);  

            }  

        }  

        catch (Exception e)  

        {  

            e.printStackTrace();  

        }  

    }  

 

    /**

     * 检查是否需要重新开局

     *  

     * @author LeeHo

     * @update 2017年12月31日 下午1:39:18

     */  

    private void checkDoReplay()  

    {  

        if (imageLength[0] > 0 && imageLength[0] == imageLength[1] && imageLength[1] == imageLength[2]  

                && imageLength[2] == imageLength[3] && imageLength[3] == imageLength[4])  

        {  

            //此时表示已经连续5次图片大小一样了,可知当前屏幕处于再来一局  

            Arrays.fill(imageLength, 0);  

            //模拟点击再来一局按钮重新开局  

            replayGame();  

        }  

    }  

 

    /**

     * 获取指定坐标的RGB值

     *

     * @param bufferedImage

     * @param x

     * @param y

     * @author LeeHo

     * @update 2017年12月31日 下午12:12:43

     */  

    private void processRGBInfo(BufferedImage bufferedImage, int x, int y)  

    {  

        this.rgbInfo.reset();  

        int pixel = bufferedImage.getRGB(x, y);  

        //转换为RGB数字    

        this.rgbInfo.setRValue((pixel & 0xff0000) >> 16);  

        this.rgbInfo.setGValue((pixel & 0xff00) >> 8);  

        this.rgbInfo.setBValue((pixel & 0xff));  

    }  

 

    class RGBInfo  

    {  

        private int RValue;  

 

        private int GValue;  

 

        private int BValue;  

 

        public int getRValue()  

        {  

            return RValue;  

        }  

 

        public void setRValue(int rValue)  

        {  

            RValue = rValue;  

        }  

 

        public int getGValue()  

        {  

            return GValue;  

        }  

 

        public void setGValue(int gValue)  

        {  

            GValue = gValue;  

        }  

 

        public int getBValue()  

        {  

            return BValue;  

        }  

 

        public void setBValue(int bValue)  

        {  

            BValue = bValue;  

        }  

 

        public void reset()  

        {  

            this.RValue = 0;  

            this.GValue = 0;  

            this.BValue = 0;  

        }  

    }  



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: