|
      昨天晚上,玩了一下QQ对对碰的游戏,居然一盘都没有赢,于是心里很是不爽!于是开始搞这个外挂!让他自动去消行!
      首先,分析一下,QQ的这种休闲游戏,显然不必像大型网络游戏那么麻烦,所以啥都不说,直接上Spy++,查看相关的句柄。可以发现,主要游戏区域的句柄都依附于窗体!应该可以直接通过鼠标模拟点击来实现对对碰的自动消行!这里首先要做的就是用找到这个游戏窗口的句柄,用FindWindow来实现,这里有点需要注意的,FindWindow在查找窗口的时候,英文是一点问题都没有,但是如果是中文,此时需要做一个编码转换,因为Lazarus默认是UTF8的编码,所以要先用UTF8Decode转换成普通的格式 | 。所以这里需要的是
FindWindow(nil,PChar(UTF8Decode('中文标题')));这样写,才能返回正确的句柄。找到窗口句柄了之后,其次,我们想要让自动点击,就需要找到动物数组的每个动物对应的数据!这个用CE来查找,可以发现动物数组对应的数据为1到7之间的7个数字,这个找到之后,来进行测试会发现每次进入不同的座位号的时候,数组对应的基地址不同,所以还要找到用户进入的座位号,然后,获得对应的数组地址。这些都完成之后,开始对数组进行逻辑处理,这个游戏的规则是,每换到有三个相同的连成一条直线,就能消掉这三个东西。那么此时就是要根据这个规则来查找,哪两个可以进行交换,我最开始实现的时候,比较左右,上下,先看两个是否相同,如果相同,那么跨过一个子,比较后面的一个与当前相同两个是否相同!如果相同进行交换!但是,貌似效果不咋地!后来在网上看到别人的一个外挂!他是先将相邻两个数据交换,交换了之后再比较是否有三个相同的,相同的就能交换!于是我也采用了这种算法!先内建了一个数组!将数据都弄到这个数组中去,然后再做比对!
下面给出代码哈!- unit DxGameDDPHook;
- interface
- uses Windows,Messages,Classes,ExtCtrls;
- type
-   TDxDDPGameHook = class
-   private
-     RunTimer: TIdleTimer;
-     GameClose: Boolean;
-     FDDPGameWnd: THandle;
-     AnimalArray: Array[1..8,1..25] of byte;//动物数组
-     ProcId: THandle;
-     ThreadHandle: THandle;
-     UserSiteNum: Integer;//用户的座位号
-     GameBeginPoint: TPoint;
-     FOnStart: TNotifyEvent;
-     FOnEnd: TNotifyEvent;
-     procedure RunGame;
-     function GetAnimalArrayData: Boolean;//获取动物数组数据
-     procedure DoRunTimer(Sender: TObject);
-     procedure ClearMemory;
-   public
-     constructor Create;
-     property SitNum: integer read UserSiteNum;
-     property OnStart: TNotifyEvent read FOnStart write FOnStart;
-     property OnEnd: TNotifyEvent read FOnEnd write FOnEnd;
-     property DDPGameWnd: THandle read FDDPGameWnd;
-     destructor Destroy;override;
-     procedure  SetInterver(Interval: Integer);
-     procedure StartGame(Info: Integer);
-     procedure EndGame;
-   end;
- const
-    UserSitNumBase=  $00480B1C;
-    //每个座位号对应的动物数组的开始基地址
-    AnimalArrayBase:array[0..3] of ^Dword=(
-                                 Pointer($47D560),
-                                 Pointer($47E144),
-                                 Pointer($47ED28),
-                                 Pointer($47F90C)
-                                 );
- implementation
- { TDxDDPGameHook }
- procedure TDxDDPGameHook.ClearMemory;
- begin
-   FillChar(AnimalArray,200,0);
- end;
- constructor TDxDDPGameHook.Create;
- begin
-   ClearMemory;
-   GameBeginPoint := Point(272,99);//游戏区域相对于窗体的开始位置
-   GameClose := True;
-   UserSiteNum := -1;
-   ProcId := 0;
-   RunTimer := TIdleTimer.Create(nil);
-   RunTimer.OnTimer:= @DoRunTimer;
-   RunTimer.Enabled := False;
- end;
- destructor TDxDDPGameHook.Destroy;
- begin
-   ClearMemory;
-   EndGame;
-   RunTimer.Free;
-   inherited;
- end;
- procedure TDxDDPGameHook.DoRunTimer(Sender: TObject);
- begin
-   RunGame;
- end;
- procedure TDxDDPGameHook.EndGame;
- begin
-   GameClose := True;
-   FDDPGameWnd := 0;
-   RunTimer.Enabled := False;
-   if Assigned(FOnEnd) then
-     FOnEnd(Self);
- end;
- function TDxDDPGameHook.GetAnimalArrayData: Boolean;
- var
-   ReadC: DWORD;
- begin
-   if not GameClose then
-   begin
-     ClearMemory;
-     if ProcId = 0 then
-     begin
-       GetWindowThreadProcessId(FDDPGameWnd,ProcId);//获得当前线程ID
-       ThreadHandle := OpenProcess(PROCESS_VM_READ or PROCESS_VM_WRITE,false,ProcId);
-     end;                       
-     if UserSiteNum = -1 then //用户座位号没有
-       ReadProcessMemory(ThreadHandle,Pointer(UserSitNumBase),@UserSiteNum,4,ReadC);
-     //开始读取座位号与动物数组数据
-     if UserSiteNum in [0..3] then //只有4个座位,有效的座位
-     begin
-       ReadProcessMemory(ThreadHandle,AnimalArrayBase[UserSiteNum],@AnimalArray,200,ReadC);
-     end;
-     Result := (AnimalArray[1,1] <> 0) or (AnimalArray[1,2] <> 0) or (AnimalArray[2,1] <> 0);
-   end
-   else Result := False;
- end;
- procedure TDxDDPGameHook.RunGame;
- var
-   i,j: Integer;
-   tmpArray: Array[1..8,1..25] of byte;
-   procedure ChangePoint(a,b: TPoint);
-   var
-     MPs: DWORD;
-   begin
-     a.x := GameBeginPoint.X + 48*a.X - 30;
-     a.y := GameBeginPoint.Y + 48*a.y - 30;
-     b.x := GameBeginPoint.X + 48*b.X - 30;
-     b.y := GameBeginPoint.Y + 48*b.y - 30;
-     //开始交换数据
-     MPs := a.X+ a.Y shl 16;
-     SendMessage(FDDPGameWnd,WM_LBUTTONDOWN,0,MPs);
-     sendMessage(FDDPGameWnd,WM_LBUTTONUP, 0,MPs);
-     MPs := b.X+ b.Y shl 16;
-     SendMessage(FDDPGameWnd,WM_LBUTTONDOWN,0,MPs);
-     sendMessage(FDDPGameWnd,WM_LBUTTONUP, 0,MPs);
-   end;
-   function testCanClear: Boolean;
-   var
-     r1,x,y:byte;
-   begin
-     Result:=false;
-     for y := 1 to 8 do //1-8行坐标
-     begin
-       r1:=1;
-       for x := 1 to 7 do  //Y列坐标
-       begin
-         if tmpArray[x][y] = tmpArray[x+1][y] then
-         begin
-           Inc(r1);  //累计相同棋子数
-           if r1>=3 then
-           begin
-             Result:=true;
-             exit;
-           end;
-         end
-         else r1 := 1;//初始化累计 1
-       end;
-     end;
-     //遍历 1-8 列 看是否有 3子 相连的
-     for x := 1 to 8 do
-     begin
-       r1:=1;
-       for y := 1 to 7 do  //列坐标
-       begin
-         if tmpArray[x][y]=tmpArray[x][y+1] then
-         begin
-           Inc(r1);  //累计相同棋子数
-           if r1>=3 then
-           begin
-             Result:=true;
-             exit;
-           end;
-         end
-         else r1 := 1;//初始化累计 1
-       end;
-     end;
-   end;
- var
-   tmp: Byte;
- begin
-   //开始执行游戏
-   if not GameClose then
-   begin
-      if not GetAnimalArrayData then
-      begin
-        StartGame(RunTimer.Interval);
-        exit;
-      end;
-      //先纵向比较
-      for I := 1 to 8 do
-      begin
-        for j := 1 to 7 do
-        begin //有两个相似
-          CopyMemory(@tmpArray,@AnimalArray,200);
-          tmp:=tmpArray[I][J];
-          tmpArray[i][j]:=tmpArray[i][j+1];
-          tmpArray[i][j+1]:=tmp;//交换相临棋子
-          if testCanClear then
-          begin
-            ChangePoint(Point(I,j),Point(i,j+1));
-            exit;          
-          end;
-        end;
-      end;
-      {if not GetAnimalArrayData then
-      begin
-        StartGame(RunTimer.Interval);
-        exit;
-      end; }
-      //横向比较
-      for j := 1 to 8 do
-      begin
-        for i := 1 to 7 do
-        begin //有两个相似
-          CopyMemory(@tmpArray,@AnimalArray,200);
-          tmp:=tmpArray[i][j];
-          tmpArray[i][j]:=tmpArray[i+1][j];
-          tmpArray[i+1][j]:=tmp; //交换相临的2点
-          if testCanClear then
-          begin
-            ChangePoint(Point(I,j),Point(i+1,j));
-            exit;          
-          end; 
-        end;
-      end;
-   end;
- end;
- procedure TDxDDPGameHook.SetInterver(Interval: Integer);
- begin
-   RunTimer.Interval := Interval;
- end;
- procedure TDxDDPGameHook.StartGame(Info: Integer);
- var
-   str: string;
- begin
-   FDDPGameWnd := Windows.FindWindowW(nil,PWchar(UTF8Decode('对对碰角色版')));
-   GameClose := FDDPGameWnd = 0;
-   ProcId := 0;
-   if not GameClose  then
-   begin   
-    //模拟鼠标单击
-     SendMessage(FDDPGameWnd,WM_LBUTTONDOWN,0,$0180017A);//按下
-     SendMessage(FDDPGameWnd,WM_LBUTTONUP, 0, $0180017A);//弹起
-     RunTimer.Interval := Info;
-     RunTimer.Enabled := True;
-     if Assigned(FOnStart) then
-       FOnStart(Self);
-   end;
- end;
- end.
复制代码 所有代码,一会回来了之后提供 |
评分
-
查看全部评分
|