【learning】微信跳一跳輔助c++詳解 輕鬆上萬 【上】

寫在前面node

        17年年末Wechat出了這個跳一跳的小遊戲,今年2月份的時候簡單地玩了一下,發現被遊戲虐了(手太殘了只能跳20多)。c++

     今天恰好有點空,因而就花了一個下午的時間寫了一個跳一跳的c++輔助。算法

       因爲本OIER既不會Python,也不會安卓的USB調試,更不會單片機,故寫了一一個操做安卓模擬器的輔助。小程序

       先放下效果:(只是先截個圖而已,截止至目前跳了2150次,運行1小時55分鐘)【未完待續】windows

據以前的跳一跳大賽的結果,儘管人類的第一爲1.2W分,但仍被本半天速成輔助輕鬆碾在地上。函數

--------------------------------------------------------------------------------我是分割線-----------------------------------------------------------------------------------------------oop

一些最基礎的東西測試

完成一次跳躍,你須要獲得棋子位置及方塊位置。進而計算出二者之間的距離,隨後跳躍相應的距離。優化

在我尚不瞭解跳一跳底層的數據的時候,抓屏分析幾乎是惟一選項。spa

因此你要先完成抓屏。

 

如何抓屏

在不額外導庫的狀況下,windows.h下提供了一個函數叫作getpixel,然而這個函數效率太低,顯然不合適如此大面積的圖像處理。

然而我又比較懶,不想去裝庫,但碰巧手頭有我半年前手寫的bmp庫。

我從網上找了個快捷鍵自動截屏的小程序,經過發送快捷鍵將屏幕數據轉爲bmp存入磁盤,再用bmp讀取(捂臉)。

反正這種簡單遊戲對輔助的吞吐量要求不高,就先這麼湊合着用吧....

代碼就不單獨拎出來了

 

完成抓屏後,爲了可以實現準確地識別棋子位置及方塊位置,咱們要先對界面作一些處理。

顯然,咱們要把背景和圖形陰影給過濾掉。

通過屢次抓屏分析,咱們獲得了跳一跳背景和陰影的一些特徵:

1,對於同行不一樣列,陰影部分的RGB數據徹底相同,背景部分的RGB數據也徹底相同,且陰影的RGB數據=背景的RGB數據/k (k約等於1.4356)

2,杜宇不一樣行的同列,背景部分的RGB數據可能不一樣,且對於所有行,$\Delta R,\ \Delta G,\ \Delta B≤50$。

咱們基於這兩個性質,對遊戲界面進行背景和陰影過濾。

如圖所示,過濾前與過濾後。(請先無視除背景顏色變化外的全部東西)

 

【實現方法】

咱們對於每一行分開處理,對於一個正在處理的行,找出該行內出現次數最多的顏色,隨後經過計算算出該行陰影的rgb數據。隨後將這兩種顏色的像素設爲黑色(#000000)

該方法的缺點也是顯而易見的,首先,沒法過濾陰影的邊框,且對於方塊分佈較密集的部分,該過濾方式可能會出現一些問題。

所幸的是,不過濾邊框幾乎不會影響到接下來的斷定,且目標點附近不會出現許多個方塊(僅1個嘛....)

濾色部分代碼:

 1      for(int i=1;i<=P.n;i++){
 2         mp.clear();//該map用於判斷顏色衆數,因爲對吞吐量要求不高,故沒有進一步優化
 3         for(int j=1;j<=P.m;j++)
 4         mp[node(P.r[i][j],P.g[i][j],P.b[i][j])]++;
 5         map<node,int>::iterator it; 
 6         node maxid,maxid2; int maxn=0;
 7         for(it=mp.begin();it!=mp.end();it++){
 8             if(maxn<it->second){
 9                 maxn=it->second;
10                 maxid=it->first;
11             }
12         }
13         maxid2.r=maxid.r/conY;//cony即爲上文所說的某個常數
14         maxid2.g=maxid.g/conY;
15         maxid2.b=maxid.b/conY;
16         for(int j=1;j<=P.m;j++){
17             if(maxid.cmp(P.r[i][j],P.g[i][j],P.b[i][j]))
18                 P.r[i][j]=P.g[i][j]=P.b[i][j]=0;
19             if(maxid2.cmp(P.r[i][j],P.g[i][j],P.b[i][j]))
20                 P.r[i][j]=P.g[i][j]=P.b[i][j]=0;
21         }
22     }

 

 

如何找到棋子

筆者經過簡單地分析,發現棋子的色域很是特殊,幾乎不存在與棋子相同顏色的方塊。

根據此特徵,咱們只須要求出在特定色域內的點所構成的點集,隨後對這些點求一個平均座標,再加上一個常數項的偏移,便可求出棋子的近似座標。

用於斷定點集的色域:$R∈[43,68],G∈[49,57],B∈[76,102]$。

捕捉到的棋子:

被染成灰色的部分爲在色域內的點,白色點即爲全部灰色點的平均加偏座標。

通過近萬次實際捕捉,能夠證實大膽猜測該方法是有效的。

代碼以下:

 

 1 #define LR 43
 2 #define RR 68
 3 #define LG 49
 4 #define RG 57
 5 #define LB 76
 6 #define RB 102
 7     
 8     int sumx=0,sumy=0,cntx=0;
 9     for(int i=1;i<=P.n;i++)
10     for(int j=1;j<=P.m;j++){
11         int dR=abs(P.r[i][j]);
12         int dG=abs(P.g[i][j]);
13         int dB=abs(P.b[i][j]);
14         int cnt=0;
15         if(LR<=dR&&dR<=RR) cnt++;
16         if(LG<=dG&&dG<=RG) cnt++;
17         if(LB<=dB&&dB<=RB) cnt++;
18         if(cnt==3){
19             P.r[i][j]=P.g[i][j]=P.b[i][j]=100;
20             sumx+=i; sumy+=j; cntx++;
21         }
22     }//識別棋子 

 

如何肯定目標點

咱們先大膽假設,我上一次跳到了中心點!!!

咱們不難發現,在下個方塊的正中心,出現了大大的白點?

通過反覆的抓屏,咱們發現這個白點具備如下幾個性質:

1,永遠在目標的正中心。

2,除了邊界顏色與目標自己稍有混合外,其他部分相同且不變(#F1F1F1)

3,該點不變色部分的顏色具備近似惟一性(除了藥瓶瓶口附近外,其他的格子均不會出現這種顏色,包括看起來很白的幾個方塊)。

基於這三個特性,咱們不妨大膽猜出一個抓白點的方法:

在全屏範圍內搜索,是否存在一個色塊,知足其大小爲12*8px,且顏色均爲#F1F1F1。

經過屢次測試能夠發現知足此條件的色塊均在白點內,藥瓶子是找不到這樣的位子的。

在符合條件的色塊中,任意選出一個色塊,則目標點的座標即爲該色塊的中點(由於色塊數量很是少,且很是集中,經測試該方法偏移僅爲±2px,和因模擬器卡頓形成的偏移已相差無幾,故幾乎不用擔憂精度問題)。

因爲存在機器卡頓,偏差累計等問題,故沒法保證每次跳躍均落在中心點(目前中心率爲89.1%),目前最好的記錄是連續50次跳到中心點。

這個記錄,我相信不採用輔助人手是徹底沒法作到的。

代碼:

 1   CAP.readfile("0000white.bmp");//對白點的特殊優化,因爲趕工,採用了直接讀取bmp的方法
 2     int minn=1234567890,maxx=0,maxy=0;
 3     for(int j=chessX;j>=chessX-300;j--)
 4     for(int i=1;i<=P.m-CAP.m;i++){
 5         int sum=0,pcnt=0; 
 6         for(int ii=1;ii<CAP.m;ii++)
 7         for(int jj=1;jj<CAP.n;jj++){
 8             sum+=pf(P.r[j+jj][i+ii]-CAP.r[jj][ii]);
 9             sum+=pf(P.g[j+jj][i+ii]-CAP.g[jj][ii]);
10             sum+=pf(P.b[j+jj][i+ii]-CAP.b[jj][ii]);
11         }
12         if(sum==0){
13             minn=sum,maxx=i,maxy=j;
14             break;
15         }
16     }
17     //cout<<minn<<endl;
18     if(minn==0){
19         printf("catch white point!\n");
20         for(int ii=1;ii<CAP.m;ii++)
21         for(int jj=1;jj<CAP.n;jj++){
22             P.r[maxy+jj][maxx+ii]=0; 
23             P.g[maxy+jj][maxx+ii]=255;
24             P.b[maxy+jj][maxx+ii]=0;
25         }
26         TX=maxy+6; TY=maxx+8;
27         P.r[TX][TY]=255; P.g[TX][TY]=P.b[TX][TY]=0;
28     //    P.outfile("test.bmp"); 
29         return 2; 
30     }

 

綠色的位置即爲匹配到的白點,紅點爲預計落點

 

然而,不幸的是,仍是有11%的機率跳不到中心點上,下面咱們就要採用另外一套算法來解決問題:

咱們不妨假設這棋子在屏幕的左半邊,且咱們已知棋子的中心座標。

咱們以棋子爲原點,以正右方向爲X軸正半軸構造笛卡爾座標系。

經過簡單地統計,咱們不難發現目標的位置大概在$f(x)=tan \frac{\pi}{6}x$上

 

 

 

因而咱們構造五條射線$f(x)=tan \frac{\pi}{6}x-10$,$f(x)=tan \frac{\pi}{6}x-5$,$f(x)=tan \frac{\pi}{6}x$(圖中畫出了這一條),$f(x)=tan \frac{\pi}{6}x+5$,$f(x)=tan \frac{\pi}{6}x+10$,將在線上的全部像素取出。

隨後,咱們找出出現次數最多的顏色,對全部該顏色像素求一個平均座標,便可獲得目標點位置。

考慮到該遊戲中存在有花紋較多的方塊(如437天,木紋小板凳),咱們欽定一個常數eps(容許偏差範圍),求出像素數量最多的色域(能夠理解爲$R∈[r-eps,r+eps],G∈[g-eps,g+eps],B∈[b-eps,b+eps]$)求出該色域內全部像素的平均座標,獲得目標點。

如上方右圖所示,被染成綠色的點即爲斷定點,中心紅點即爲預計落點。

爲了提高精度,eps會根據出現的顏色數量而作出相應的調整。

本輔助中,設置了4個閾值5個eps。

對於棋子在屏幕右半邊的狀況同理。

代碼:

  1   memset(X,0,sizeof(X)); memset(Y,0,sizeof(Y));
  2     memset(lineR,0,sizeof(lineR)); memset(lineG,0,sizeof(lineG)); memset(lineB,0,sizeof(lineB)); 
  3     //loop:;
  4     mp.clear(); 
  5     if(chessY<=290 ){
  6         for(int i=chessY+60;i<=P.m;i++){//繪製函數
  7             int j=chessX-(i-chessY)*tan30;
  8             if(P.r[j][i]==0&&P.g[j][i]==0&&P.b[j][i]==0) continue;
  9             cnt++;
 10             lineR[cnt]=P.r[j][i];
 11             lineG[cnt]=P.g[j][i];
 12             lineB[cnt]=P.b[j][i];
 13             X[cnt]=j; Y[cnt]=i;//將函數上的點加入集合中,下文同理
 14             mp[node(P.r[j][i],P.g[j][i],P.b[j][i])]++;
 15             cnt++;
 16             lineR[cnt]=P.r[j-4][i];
 17             lineG[cnt]=P.g[j-4][i];
 18             lineB[cnt]=P.b[j-4][i];
 19             X[cnt]=j-4; Y[cnt]=i;
 20             mp[node(P.r[j-4][i],P.g[j-4][i],P.b[j-4][i])]++;
 21             cnt++;
 22             lineR[cnt]=P.r[j+4][i];
 23             lineG[cnt]=P.g[j+4][i];
 24             lineB[cnt]=P.b[j+4][i];
 25             X[cnt]=j+4; Y[cnt]=i;
 26             mp[node(P.r[j+4][i],P.g[j+4][i],P.b[j+4][i])]++;
 27             cnt++; 
 28             lineR[cnt]=P.r[j+8][i];
 29             lineG[cnt]=P.g[j+8][i];
 30             lineB[cnt]=P.b[j+8][i];
 31             X[cnt]=j+8; Y[cnt]=i;
 32             mp[node(P.r[j+8][i],P.g[j+8][i],P.b[j+8][i])]++;
 33             cnt++; 
 34             lineR[cnt]=P.r[j-8][i];
 35             lineG[cnt]=P.g[j-8][i];
 36             lineB[cnt]=P.b[j-8][i];
 37             X[cnt]=j-8; Y[cnt]=i;
 38             mp[node(P.r[j-8][i],P.g[j-8][i],P.b[j-8][i])]++;
 39             P.r[j+1][i]=P.r[j-1][i]=255;
 40             P.g[j+1][i]=P.g[j-1][i]=255;
 41             P.b[j+1][i]=P.b[j-1][i]=0; 
 42         }
 43     }else{
 44         for(int i=chessY-60;i;i--){
 45             int j=chessX-(chessY-i)*tan30;
 46             if(P.r[j][i]==0&&P.g[j][i]==0&&P.b[j][i]==0) continue;
 47             cnt++;
 48             lineR[cnt]=P.r[j][i];
 49             lineG[cnt]=P.g[j][i];
 50             lineB[cnt]=P.b[j][i];
 51             X[cnt]=j; Y[cnt]=i;
 52             mp[node(P.r[j][i],P.g[j][i],P.b[j][i])]++;
 53             cnt++;
 54             lineR[cnt]=P.r[j-4][i];
 55             lineG[cnt]=P.g[j-4][i];
 56             lineB[cnt]=P.b[j-4][i];
 57             X[cnt]=j-4; Y[cnt]=i;
 58             mp[node(P.r[j-4][i],P.g[j-4][i],P.b[j-4][i])]++;
 59             cnt++;
 60             lineR[cnt]=P.r[j+4][i];
 61             lineG[cnt]=P.g[j+4][i];
 62             lineB[cnt]=P.b[j+4][i];
 63             X[cnt]=j+4; Y[cnt]=i;
 64             cnt++; 
 65             mp[node(P.r[j+4][i],P.g[j+4][i],P.b[j+4][i])]++;
 66             lineR[cnt]=P.r[j+8][i];
 67             lineG[cnt]=P.g[j+8][i];
 68             lineB[cnt]=P.b[j+8][i];
 69             X[cnt]=j+8; Y[cnt]=i;
 70             cnt++; 
 71             mp[node(P.r[j+8][i],P.g[j+8][i],P.b[j+8][i])]++;
 72             lineR[cnt]=P.r[j-8][i];
 73             lineG[cnt]=P.g[j-8][i];
 74             lineB[cnt]=P.b[j-8][i];
 75             X[cnt]=j-8; Y[cnt]=i;
 76             mp[node(P.r[j-8][i],P.g[j-8][i],P.b[j-8][i])]++;
 77             P.r[j+1][i]=P.r[j-1][i]=255;
 78             P.g[j+1][i]=P.g[j-1][i]=255;
 79             P.b[j+1][i]=P.b[j-1][i]=0; 
 80         }
 81     }
 82     //printf("colorsum:%d\n",mp.size()); 
 83     if(mp.size()<40){
 84         JumpepsR=JumpepsG=JumpepsB=1;
 85     }else if(mp.size()<100){
 86         JumpepsR=JumpepsG=JumpepsB=4;
 87     }else if(mp.size()<400){
 88         JumpepsR=JumpepsG=JumpepsB=7;
 89     }else JumpepsR=JumpepsG=JumpepsB=10;
 90     if(cnt==0) 
 91     return 1;
 92     //if(cnt==0) goto loop;
 93         int maxn=0,maxid=0,quan=3;
 94         for(int i=1;i<=cnt;i++){
 95             quan=3; 
 96             int R=lineR[i];
 97             int G=lineG[i];
 98             int B=lineB[i];
 99             int sum=0;
100             for(int j=1;j<=cnt;j++){
101                 int DeltaR=abs(lineR[j]-R);
102                 int DeltaG=abs(lineG[j]-G);
103                 int DeltaB=abs(lineB[j]-B);
104                 if(DeltaR>JumpepsR) continue;
105                 if(DeltaG>JumpepsG) continue;
106                 if(DeltaB>JumpepsB) continue;
107                 sum+=abs(X[j]-chessX)*0.05+4; //求出最大的色域
108             }
109             if(sum>maxn) maxn=sum,maxid=i;
110         }        
111         int sumX=0,sumY=0,sum=0;
112         int R=lineR[maxid];
113         int G=lineG[maxid];
114         int B=lineB[maxid];    
115         for(int j=1;j<=cnt;j++){
116             int DeltaR=abs(lineR[j]-R);
117             int DeltaG=abs(lineG[j]-G);
118             int DeltaB=abs(lineB[j]-B);
119             if(DeltaR>JumpepsR) continue;
120             if(DeltaG>JumpepsG) continue;
121             if(DeltaB>JumpepsB) continue;
122             sum++;
123             P.r[X[j]][Y[j]]=0; 
124             P.g[X[j]][Y[j]]=255; 
125             P.b[X[j]][Y[j]]=0; 
126             sumX+=X[j]; sumY+=Y[j];//求出該色域內點出現的最大次數
127         }
128     if(sum==0) 
129     return 1;
130         sumX/=sum; sumY/=sum;//求出座標
131         //求出目標點座標
132         P.r[sumX][sumY]=255; P.g[sumX][sumY]=P.b[sumX][sumY]=0;
133     TX=sumX; TY=sumY;

 

找到座標後,如何肯定按壓的時長

咱們不妨猜測這個按壓時間與兩點間距呈線性關係。

經過簡單地採樣+散點圖,因而就擬合出了該直線的斜率。

經過該方法,獲得的跳躍時間$T=2.55 \times dist$,其中$dist$表示起點到終點的距離,單位爲像素,T的單位爲毫秒。

後來,我發現該擬合方法偏差較大,只能實現連續36次跳至中心點,中心點率爲85%。

爲了進一步提升精度,我又發現了一個性質:須要跳躍的時間與dist並沒有直接關聯,但與dist在$y=tan \frac {\pi}{6}x$上的投影有關。

所以,優化算法以下:

令向量$\vec a=BEGIN-END$,其中BEGIN表示棋子中心點座標,END表示目標點座標。

設一個單位向量$\vec b=(cos \frac{\pi}{6},sin \frac{\pi}{6})$

則跳躍時間$T=2.53 \times \vec a \cdot \vec b$ ,單位仍爲毫秒。

再簡單地調下參,就能夠實現90%的中心點率,最高連續50次中心點啦~。

 

剛剛跳到4.4W掛掉了....本蒟蒻修復完bug了...

若要看二代輔助的細節,請移步下篇

 

 整個一代輔助代碼以下:

#include<bits/stdc++.h>
#include<cmath>
#include<windows.h>
#define d(x) keybd_event(x,0,0,0)
#define u(x) keybd_event(x,0,2,0)
#define s(x) Sleep(x)
#define me(x) mouse_event(x,0,0,0,0)
#define sc(x,y) SetCursorPos(x,y)
#define gk(x) GetAsyncKeyState(x)

#define M 100000
using namespace std;

int up(int x){while((x*3)%4!=0) x++;return x;}
int lf(int x){return abs(x);}
void printhead(unsigned char c[],int n,int m){
    //該函數用於寫入一個24位bmp頭 
    c[0]=0x42; c[1]=0x4d; //BM
    unsigned siz=54+3*up(n)*up(m);
    for(int i=2;i<=5;i++){
        c[i]=siz&255; siz=siz>>8;
    }//寫入siz
    siz=3*n*m;
    c[10]=0x36;//寫入數據頭位置
    c[0x0e]=0x28;//頭大小 
    for(int i=0x12;i<=0x15;i++) c[i]=m&255,m>>=8;//寫入寬度 
    for(int i=0x16;i<=0x19;i++) c[i]=n&255,n>>=8;//寫入高度
    c[0x1a]=1;//永遠爲1
    c[0x1c]=0x18;//24位位圖 
    //for(int i=0x22;i<=0x25;i++) c[i]=siz&255,siz>>=8;//寫入去頭字節數 
}
#define MFLONG 15000000
#define W 1921
#define H 1081
unsigned char _c[MFLONG]={0};
struct board{//畫布函數 
    int n,m;//寬高 
    unsigned char r[H][W],g[H][W],b[H][W];
    board(){
        n=m=0; memset(b,0,sizeof(b));
        memset(r,0,sizeof(r)); memset(g,0,sizeof(g));
    }
    board(int nn,int mm,int R,int G,int B){
        n=nn; m=mm; memset(b,B,sizeof(b));
        memset(r,R,sizeof(r)); memset(g,G,sizeof(g));
    }
    void clear(){
        n=m=0; memset(b,0,sizeof(b));
        memset(r,0,sizeof(r)); memset(g,0,sizeof(g));
    }
    void outfile(char ad[]){
        FILE *fp; fp=fopen(ad,"wb");
        printhead(_c,n,m); int ns=54;
        for(int i=n;i;i--){
            for(int j=1;j<=m;j++){
                _c[ns++]=b[i][j];
                _c[ns++]=g[i][j];
                _c[ns++]=r[i][j];
            }
            int k=(3*m)%4;
            for(int i=0;i<k;i++)
            _c[ns++]=0;
        }
        fwrite(_c,1,ns,fp);
        fclose(fp);
    }
    void readfile(char ad[]){
        FILE *fp; fp=fopen(ad,"rb");
        fread(_c,1,MFLONG,fp);
        fclose(fp);
        for(int i=0x15;i>=0x12;i--) m=m<<8,m=m+_c[i];
        for(int i=0x19;i>=0x16;i--) n=n<<8,n=n+_c[i];
        int ns=54;
        for(int i=n;i;i--){
            for(int j=1;j<=m;j++){
                b[i][j]=_c[ns++];
                g[i][j]=_c[ns++];
                r[i][j]=_c[ns++];
            }
            int k=(m*3)%4;
            ns+=k;
        }
        fclose(fp);
    }
}; 
board S,P,P2,CAP;

void capture(){
    d(VK_SNAPSHOT); u(VK_SNAPSHOT);
    S.readfile("screenx.bmp");
}
#define epsR 2
#define epsG 2
#define epsB 2
#define conY 1.4356 ///過濾底色和陰影的參數

#define LR 43
#define RR 68
#define LG 49
#define RG 57
#define LB 76
#define RB 102
#define tan30 0.5773

/*#define JumpepsR 7
#define JumpepsG 7
#define JumpepsB 7//用於判斷目標點的東西*/
int JumpepsR,JumpepsG,JumpepsB; 

int wx[]={-1,-1,-1,0,1,1,1,0};
int wy[]={-1,0,1,1,1,0,-1,-1};

struct node{
    int  r,g,b;
    node(){r=g=b=0;}
    node(unsigned char R,unsigned char G,unsigned B){
        r=R; g=G; b=B;
    }
    friend bool operator <(node a,node b){
        if(a.r!=b.r) return a.r<b.r;
        if(a.g!=b.g) return a.g<b.g;
        return a.b<b.b;
    }
    bool cmp(int R,int G,int B){
        int e1=abs(r-R);
        int e2=abs(g-G);
        int e3=abs(b-B); 
        if(e1>epsR) return 0;
        if(e2>epsG) return 0;
        if(e3>epsB) return 0;
        return 1;
    }    
};
int pf(int x){return x*x;}
map<node,int> mp,mmp;
int chessX,chessY;//棋子的x,y座標 
int TX,TY;
int lineR[10000]={0},lineG[10000]={0},lineB[10000]={0},X[10000]={0},Y[10000]={0};
int wave(){//完成對圖像的底色和陰影過濾,以及求出棋子的中心點 
    P.clear();
    int sx=32,ex=1074;
    int sy=682,ey=1265;
    P.m=ey-sy+1; P.n=ex-sx+1;
    for(int i=sx;i<=ex;i++)
    for(int j=sy;j<=ey;j++){
        P.r[i-sx+1][j-sy+1]=S.r[i][j];
        P.g[i-sx+1][j-sy+1]=S.g[i][j];
        P.b[i-sx+1][j-sy+1]=S.b[i][j];
    }
//    P.readfile("st720.bmp"); 
//抓出圖像
        
    P2=P; 
    int sumx=0,sumy=0,cntx=0;
    for(int i=1;i<=P.n;i++)
    for(int j=1;j<=P.m;j++){
        int dR=abs(P.r[i][j]);
        int dG=abs(P.g[i][j]);
        int dB=abs(P.b[i][j]);
        int cnt=0;
        if(LR<=dR&&dR<=RR) cnt++;
        if(LG<=dG&&dG<=RG) cnt++;
        if(LB<=dB&&dB<=RB) cnt++;
        if(cnt==3){
            P.r[i][j]=P.g[i][j]=P.b[i][j]=100;
            sumx+=i; sumy+=j; cntx++;
        }
    }//識別棋子 
    
    for(int i=1;i<=P.n;i++){
        mp.clear();
        for(int j=1;j<=P.m;j++)
        mp[node(P.r[i][j],P.g[i][j],P.b[i][j])]++;
        map<node,int>::iterator it; 
        node maxid,maxid2; int maxn=0;
        for(it=mp.begin();it!=mp.end();it++){
            if(maxn<it->second){
                maxn=it->second;
                maxid=it->first;
            }
        }
        maxid2.r=maxid.r/conY;
        maxid2.g=maxid.g/conY;
        maxid2.b=maxid.b/conY;
        for(int j=1;j<=P.m;j++){
            if(maxid.cmp(P.r[i][j],P.g[i][j],P.b[i][j]))
                P.r[i][j]=P.g[i][j]=P.b[i][j]=0;
            if(maxid2.cmp(P.r[i][j],P.g[i][j],P.b[i][j]))
                P.r[i][j]=P.g[i][j]=P.b[i][j]=0;
        }
    }
    if(cntx==0) 
    return 1;
    sumx/=cntx; sumy/=cntx;
    sumx+=14; 
    P.r[sumx][sumy]=P.g[sumx][sumy]=P.b[sumx][sumy]=255; 
    chessX=sumx+2; chessY=sumy;
    int cnt=0; 
//    P.outfile("ok.bmp"); 
    CAP.readfile("0000white.bmp");//對白點的特殊優化 
    int minn=1234567890,maxx=0,maxy=0;
    for(int j=chessX;j>=chessX-300;j--)
    for(int i=1;i<=P.m-CAP.m;i++){
        int sum=0,pcnt=0; 
        for(int ii=1;ii<CAP.m;ii++)
        for(int jj=1;jj<CAP.n;jj++){
            sum+=pf(P.r[j+jj][i+ii]-CAP.r[jj][ii]);
            sum+=pf(P.g[j+jj][i+ii]-CAP.g[jj][ii]);
            sum+=pf(P.b[j+jj][i+ii]-CAP.b[jj][ii]);
        }
        if(sum==0){
            minn=sum,maxx=i,maxy=j;
            break;
        }
    }
    //cout<<minn<<endl;
    if(minn==0){
        printf("catch white point!\n");
        for(int ii=1;ii<CAP.m;ii++)
        for(int jj=1;jj<CAP.n;jj++){
            P.r[maxy+jj][maxx+ii]=0; 
            P.g[maxy+jj][maxx+ii]=255;
            P.b[maxy+jj][maxx+ii]=0;
        }
        TX=maxy+6; TY=maxx+8;
        P.r[TX][TY]=255; P.g[TX][TY]=P.b[TX][TY]=0;
    //    P.outfile("test.bmp"); 
        return 2; 
    }
    
    CAP.readfile("0000brown.bmp");//對437天的特殊優化 
    minn=1234567890,maxx=0,maxy=0;
    for(int j=chessX;j>=chessX-300;j--)
    for(int i=1;i<=P.m-CAP.m;i++){
        int sum=0,pcnt=0; 
        for(int ii=1;ii<CAP.m;ii++)
        for(int jj=1;jj<CAP.n;jj++){
            sum+=pf(P.r[j+jj][i+ii]-CAP.r[jj][ii]);
            sum+=pf(P.g[j+jj][i+ii]-CAP.g[jj][ii]);
            sum+=pf(P.b[j+jj][i+ii]-CAP.b[jj][ii]);
        }
        if(sum==0){
            minn=sum,maxx=i,maxy=j;
            break;
        }
    }
    //cout<<minn<<endl;
    if(minn==0){
        printf("catch brown point!\n");
        for(int ii=1;ii<CAP.m;ii++)
        for(int jj=1;jj<CAP.n;jj++){
            P.r[maxy+jj][maxx+ii]=0; 
            P.g[maxy+jj][maxx+ii]=255;
            P.b[maxy+jj][maxx+ii]=0;
        }
        TX=maxy+4; TY=maxx+6;
        P.r[TX][TY]=255; P.g[TX][TY]=P.b[TX][TY]=0;
    //    P.outfile("test.bmp"); 
        return 0; 
    }
        
    //printf("%d %d\n",maxx,maxy); 
    
    memset(X,0,sizeof(X)); memset(Y,0,sizeof(Y));
    memset(lineR,0,sizeof(lineR)); memset(lineG,0,sizeof(lineG)); memset(lineB,0,sizeof(lineB)); 
    //loop:;
    mp.clear(); 
    if(chessY<=290 ){
        for(int i=chessY+60;i<=P.m;i++){
            int j=chessX-(i-chessY)*tan30;
            if(P.r[j][i]==0&&P.g[j][i]==0&&P.b[j][i]==0) continue;
            cnt++;
            lineR[cnt]=P.r[j][i];
            lineG[cnt]=P.g[j][i];
            lineB[cnt]=P.b[j][i];
            X[cnt]=j; Y[cnt]=i;
            mp[node(P.r[j][i],P.g[j][i],P.b[j][i])]++;
            cnt++;
            lineR[cnt]=P.r[j-4][i];
            lineG[cnt]=P.g[j-4][i];
            lineB[cnt]=P.b[j-4][i];
            X[cnt]=j-4; Y[cnt]=i;
            mp[node(P.r[j-4][i],P.g[j-4][i],P.b[j-4][i])]++;
            cnt++;
            lineR[cnt]=P.r[j+4][i];
            lineG[cnt]=P.g[j+4][i];
            lineB[cnt]=P.b[j+4][i];
            X[cnt]=j+4; Y[cnt]=i;
            mp[node(P.r[j+4][i],P.g[j+4][i],P.b[j+4][i])]++;
            cnt++; 
            lineR[cnt]=P.r[j+8][i];
            lineG[cnt]=P.g[j+8][i];
            lineB[cnt]=P.b[j+8][i];
            X[cnt]=j+8; Y[cnt]=i;
            mp[node(P.r[j+8][i],P.g[j+8][i],P.b[j+8][i])]++;
            cnt++; 
            lineR[cnt]=P.r[j-8][i];
            lineG[cnt]=P.g[j-8][i];
            lineB[cnt]=P.b[j-8][i];
            X[cnt]=j-8; Y[cnt]=i;
            mp[node(P.r[j-8][i],P.g[j-8][i],P.b[j-8][i])]++;
            P.r[j+1][i]=P.r[j-1][i]=255;
            P.g[j+1][i]=P.g[j-1][i]=255;
            P.b[j+1][i]=P.b[j-1][i]=0; 
        }
    }else{
        for(int i=chessY-60;i;i--){
            int j=chessX-(chessY-i)*tan30;
            if(P.r[j][i]==0&&P.g[j][i]==0&&P.b[j][i]==0) continue;
            cnt++;
            lineR[cnt]=P.r[j][i];
            lineG[cnt]=P.g[j][i];
            lineB[cnt]=P.b[j][i];
            X[cnt]=j; Y[cnt]=i;
            mp[node(P.r[j][i],P.g[j][i],P.b[j][i])]++;
            cnt++;
            lineR[cnt]=P.r[j-4][i];
            lineG[cnt]=P.g[j-4][i];
            lineB[cnt]=P.b[j-4][i];
            X[cnt]=j-4; Y[cnt]=i;
            mp[node(P.r[j-4][i],P.g[j-4][i],P.b[j-4][i])]++;
            cnt++;
            lineR[cnt]=P.r[j+4][i];
            lineG[cnt]=P.g[j+4][i];
            lineB[cnt]=P.b[j+4][i];
            X[cnt]=j+4; Y[cnt]=i;
            cnt++; 
            mp[node(P.r[j+4][i],P.g[j+4][i],P.b[j+4][i])]++;
            lineR[cnt]=P.r[j+8][i];
            lineG[cnt]=P.g[j+8][i];
            lineB[cnt]=P.b[j+8][i];
            X[cnt]=j+8; Y[cnt]=i;
            cnt++; 
            mp[node(P.r[j+8][i],P.g[j+8][i],P.b[j+8][i])]++;
            lineR[cnt]=P.r[j-8][i];
            lineG[cnt]=P.g[j-8][i];
            lineB[cnt]=P.b[j-8][i];
            X[cnt]=j-8; Y[cnt]=i;
            mp[node(P.r[j-8][i],P.g[j-8][i],P.b[j-8][i])]++;
            P.r[j+1][i]=P.r[j-1][i]=255;
            P.g[j+1][i]=P.g[j-1][i]=255;
            P.b[j+1][i]=P.b[j-1][i]=0; 
        }
    }
    //printf("colorsum:%d\n",mp.size()); 
    if(mp.size()<40){
        JumpepsR=JumpepsG=JumpepsB=1;
    }else if(mp.size()<100){
        JumpepsR=JumpepsG=JumpepsB=4;
    }else if(mp.size()<400){
        JumpepsR=JumpepsG=JumpepsB=7;
    }else JumpepsR=JumpepsG=JumpepsB=10;
    if(cnt==0) 
    return 1;
    //if(cnt==0) goto loop;
        int maxn=0,maxid=0,quan=3;
        for(int i=1;i<=cnt;i++){
            quan=3; 
            int R=lineR[i];
            int G=lineG[i];
            int B=lineB[i];
            int sum=0;
            for(int j=1;j<=cnt;j++){
                int DeltaR=abs(lineR[j]-R);
                int DeltaG=abs(lineG[j]-G);
                int DeltaB=abs(lineB[j]-B);
                if(DeltaR>JumpepsR) continue;
                if(DeltaG>JumpepsG) continue;
                if(DeltaB>JumpepsB) continue;
                sum+=abs(X[j]-chessX)*0.05+4; 
            }
            if(sum>maxn) maxn=sum,maxid=i;
        }        
        int sumX=0,sumY=0,sum=0;
        int R=lineR[maxid];
        int G=lineG[maxid];
        int B=lineB[maxid];    
        for(int j=1;j<=cnt;j++){
            int DeltaR=abs(lineR[j]-R);
            int DeltaG=abs(lineG[j]-G);
            int DeltaB=abs(lineB[j]-B);
            if(DeltaR>JumpepsR) continue;
            if(DeltaG>JumpepsG) continue;
            if(DeltaB>JumpepsB) continue;
            sum++;
            P.r[X[j]][Y[j]]=0; 
            P.g[X[j]][Y[j]]=255; 
            P.b[X[j]][Y[j]]=0; 
            sumX+=X[j]; sumY+=Y[j];
        }
    if(sum==0) 
    return 1;
        sumX/=sum; sumY/=sum;
        //求出目標點座標
        P.r[sumX][sumY]=255; P.g[sumX][sumY]=P.b[sumX][sumY]=0;
    TX=sumX; TY=sumY;
    //P.outfile("test.bmp"); 
    return 0; 
    
    //點擊模組 
}
            

int main(){
    while(!gk(VK_F7)) s(10); 
    keybd_event(VK_F7,0,2,0); 
    char c[100];
    int cas=0,x=0,y,sum=0,buchang=0; 
    //Sleep(2000);
    int last=0; 
    while(1){
        cas++; 
        capture();
        Sleep(400); 
        capture();
        Sleep(200);
        int k=wave(); 
        if(gk(VK_F7)) return 0; 
        int X=abs(TX-chessX),Y=abs(TY-chessY); 
        double d=0.866,b=1.732;
        int he=2*X+d*(Y-b*X);
        printf("dist=%d pixel\n",he); 
        me(2); s(he*2.528); me(4); 
        Sleep(1500); 
        
        freopen("log.txt","r",stdin); 
        scanf("%d%d",&x,&y);
        fclose(stdin); 
        sprintf(c,"log%d.bmp",x);
        P.outfile(c);
        sprintf(c,"st%d.bmp",x);
        P2.outfile(c); 
        x++; y+=(k==2); 
        printf("sumjump=%d,centrejump=%d\n\n",x,y);
        freopen("log.txt","w",stdout); 
        printf("%d %d\n",x,y);
        fclose(stdout);    
        freopen("con","w",stdout);  
    }
     
}
相關文章
相關標籤/搜索