1. 程式人生 > >一百行java程式碼實現自動玩微信跳一跳遊戲演算法詳解

一百行java程式碼實現自動玩微信跳一跳遊戲演算法詳解

前兩週用java實現了自動玩微信跳一跳遊戲,經過兩次優化,目前每次計算的準確率得到了大幅提升,跟大家分享一下實現演算法。

首先看一下自動玩微信跳一跳遊戲的實現原理:

  1. 手機開啟USB除錯模式,通過adb連線手機
  2. 通過adb命令截圖抓取遊戲頁面:adb shell screencap 及adb pull 命令
  3. 計算出螢幕中黑棋到目標塊的距離
  4. 根據距離及時間係數計算出按壓時間
  5. 通過adb命令按壓螢幕,實現跳到下一步:adb shell input swipe 命令

可以看出,要提高準確率,關鍵要提高獲取黑棋到目標塊的距離。

獲取黑棋的中心座標方法

BufferedImage bi = ImageIO.read(pic);
//獲取影象的寬度和高度
int width = bi.getWidth(); int height = bi.getHeight(); int x1 = 0, y1 = 0; for (int i = 50; i < width; i++) { for (int flag = 0, j=height*3/4; j>height/3; j -= 5) { //判斷點的顏色是否跟RGB(55,58,100)黑色相近 if (!colorDiff(bi.getRGB(i,j),55<<16|58<<8|100)) flag++; //如果有3個以上的點是黑色,則認為找到了黑棋
if (flag > 3) { x1 = i + 13;//相加少量修正值 y1 = j + 2; //相加少量修正值 break; } } if (x1 > 0) break; } System.out.println(x1+":"+y1);

其中以上用於判斷顏色相近的方法為:

boolean colorDiff(int c1, int c2){
    int c11 = c1>>16 & 0xFF,c12 = c1>>8 & 0xFF
,c13 = c1 & 0xFF; int c21 = c2>>16 & 0xFF,c22 = c2>>8 & 0xFF,c23 = c2 & 0xFF; return Math.abs(c11 - c21) > 5 || Math.abs(c12 - c22) > 5 || Math.abs(c13 - c23) > 5; }

獲取目標塊的中心座標方法

int x2 = 0, y2 = 0;
for (int i = height / 3; i < y1; i++) {
    int p1 = bi.getRGB(99, i);//獲取掃描起始點顏色
    for (int j = 100; j < width; j++) {
        //找到不是純色的線條,從而找到目標塊頂點
        if (colorDiff(bi.getRGB(j,i),p1)) {
            if(Math.abs(j-x1)<50) {//黑棋比目標塊高
                j = j + 50;
            }else {//找到了目標塊頂點
                x2 = j;
                y2 = i;
                break;
            }
        }
    }
    if (x2 > 0) {//找到了目標塊頂點
        int p2 = bi.getRGB(x2, y2 - 10),j,max = -1;
        //固定頂點橫座標,計算目標塊的寬度
        for (; i < y1-50;i += 5 ) {
            for (j = x2; colorDiff(bi.getRGB(j,i),p2) && j<x2+200;) j++;
            //如果目標是圓形,頂點會是一條線,需要修頂點正橫座標
            if(max < 0 && j-x2>0) x2 = x2 + (j-x2)/2;
            if(max < j - x2) max = j - x2;//找到目標塊最長寬度
            else break;
        }
        //頂點橫座標及目標塊最長寬度所線上縱座標即目標塊中心點座標
        y2 = i - 5;//減去少量修正值
        break;
    }
}
//通過以上方法能獲取到大部分目標圖形的中心點,除了咖啡杯等圖案稍微不太準確

通過以上方法獲取到兩個中心點的座標後,只要計算出距離,就可以計算出需要按壓的時間

計算按壓時間

double distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
if (distance < 150) distance = 150;
//距離需要乘一定的時間係數,才能得到對應的時間
int time = (int) (distance * rate);