Lazarus中文社区

 找回密码
 立即注册(注册审核可向QQ群索取)

QQ登录

只需一步,快速开始

Lazarus IDE and 组件 下载地址版权申明
查看: 8606|回复: 12

QQ对对碰外挂,以及Lazarus的中文相关

[复制链接]

该用户从未签到

发表于 2010-4-5 17:07:18 | 显示全部楼层 |阅读模式
      昨天晚上,玩了一下QQ对对碰的游戏,居然一盘都没有赢,于是心里很是不爽!于是开始搞这个外挂!让他自动去消行!
      首先,分析一下,QQ的这种休闲游戏,显然不必像大型网络游戏那么麻烦,所以啥都不说,直接上Spy++,查看相关的句柄。可以发现,主要游戏区域的句柄都依附于窗体!应该可以直接通过鼠标模拟点击来实现对对碰的自动消行!这里首先要做的就是用找到这个游戏窗口的句柄,用FindWindow来实现,
这里有点需要注意的,FindWindow在查找窗口的时候,英文是一点问题都没有,但是如果是中文,此时需要做一个编码转换,因为Lazarus默认是UTF8的编码,所以要先用UTF8Decode转换成普通的格式
。所以这里需要的是
FindWindow(nil,PChar(UTF8Decode('中文标题')));这样写,才能返回正确的句柄。找到窗口句柄了之后,其次,我们想要让自动点击,就需要找到动物数组的每个动物对应的数据!这个用CE来查找,可以发现动物数组对应的数据为1到7之间的7个数字,这个找到之后,来进行测试会发现每次进入不同的座位号的时候,数组对应的基地址不同,所以还要找到用户进入的座位号,然后,获得对应的数组地址。这些都完成之后,开始对数组进行逻辑处理,这个游戏的规则是,每换到有三个相同的连成一条直线,就能消掉这三个东西。那么此时就是要根据这个规则来查找,哪两个可以进行交换,我最开始实现的时候,比较左右,上下,先看两个是否相同,如果相同,那么跨过一个子,比较后面的一个与当前相同两个是否相同!如果相同进行交换!但是,貌似效果不咋地!后来在网上看到别人的一个外挂!他是先将相邻两个数据交换,交换了之后再比较是否有三个相同的,相同的就能交换!于是我也采用了这种算法!先内建了一个数组!将数据都弄到这个数组中去,然后再做比对!
下面给出代码哈!
  1. unit DxGameDDPHook;
  2. interface
  3. uses Windows,Messages,Classes,ExtCtrls;
  4. type
  5.   TDxDDPGameHook = class
  6.   private
  7.     RunTimer: TIdleTimer;
  8.     GameClose: Boolean;
  9.     FDDPGameWnd: THandle;
  10.     AnimalArray: Array[1..8,1..25] of byte;//动物数组
  11.     ProcId: THandle;
  12.     ThreadHandle: THandle;
  13.     UserSiteNum: Integer;//用户的座位号
  14.     GameBeginPoint: TPoint;
  15.     FOnStart: TNotifyEvent;
  16.     FOnEnd: TNotifyEvent;
  17.     procedure RunGame;
  18.     function GetAnimalArrayData: Boolean;//获取动物数组数据
  19.     procedure DoRunTimer(Sender: TObject);
  20.     procedure ClearMemory;
  21.   public
  22.     constructor Create;
  23.     property SitNum: integer read UserSiteNum;
  24.     property OnStart: TNotifyEvent read FOnStart write FOnStart;
  25.     property OnEnd: TNotifyEvent read FOnEnd write FOnEnd;
  26.     property DDPGameWnd: THandle read FDDPGameWnd;
  27.     destructor Destroy;override;
  28.     procedure  SetInterver(Interval: Integer);
  29.     procedure StartGame(Info: Integer);
  30.     procedure EndGame;
  31.   end;
  32. const
  33.    UserSitNumBase=  $00480B1C;
  34.    //每个座位号对应的动物数组的开始基地址
  35.    AnimalArrayBase:array[0..3] of ^Dword=(
  36.                                 Pointer($47D560),
  37.                                 Pointer($47E144),
  38.                                 Pointer($47ED28),
  39.                                 Pointer($47F90C)
  40.                                 );
  41. implementation
  42. { TDxDDPGameHook }
  43. procedure TDxDDPGameHook.ClearMemory;
  44. begin
  45.   FillChar(AnimalArray,200,0);
  46. end;
  47. constructor TDxDDPGameHook.Create;
  48. begin
  49.   ClearMemory;
  50.   GameBeginPoint := Point(272,99);//游戏区域相对于窗体的开始位置
  51.   GameClose := True;
  52.   UserSiteNum := -1;
  53.   ProcId := 0;
  54.   RunTimer := TIdleTimer.Create(nil);
  55.   RunTimer.OnTimer:= @DoRunTimer;
  56.   RunTimer.Enabled := False;
  57. end;
  58. destructor TDxDDPGameHook.Destroy;
  59. begin
  60.   ClearMemory;
  61.   EndGame;
  62.   RunTimer.Free;
  63.   inherited;
  64. end;
  65. procedure TDxDDPGameHook.DoRunTimer(Sender: TObject);
  66. begin
  67.   RunGame;
  68. end;
  69. procedure TDxDDPGameHook.EndGame;
  70. begin
  71.   GameClose := True;
  72.   FDDPGameWnd := 0;
  73.   RunTimer.Enabled := False;
  74.   if Assigned(FOnEnd) then
  75.     FOnEnd(Self);
  76. end;
  77. function TDxDDPGameHook.GetAnimalArrayData: Boolean;
  78. var
  79.   ReadC: DWORD;
  80. begin
  81.   if not GameClose then
  82.   begin
  83.     ClearMemory;
  84.     if ProcId = 0 then
  85.     begin
  86.       GetWindowThreadProcessId(FDDPGameWnd,ProcId);//获得当前线程ID
  87.       ThreadHandle := OpenProcess(PROCESS_VM_READ or PROCESS_VM_WRITE,false,ProcId);
  88.     end;                       
  89.     if UserSiteNum = -1 then //用户座位号没有
  90.       ReadProcessMemory(ThreadHandle,Pointer(UserSitNumBase),@UserSiteNum,4,ReadC);
  91.     //开始读取座位号与动物数组数据
  92.     if UserSiteNum in [0..3] then //只有4个座位,有效的座位
  93.     begin
  94.       ReadProcessMemory(ThreadHandle,AnimalArrayBase[UserSiteNum],@AnimalArray,200,ReadC);
  95.     end;
  96.     Result := (AnimalArray[1,1] <> 0) or (AnimalArray[1,2] <> 0) or (AnimalArray[2,1] <> 0);
  97.   end
  98.   else Result := False;
  99. end;
  100. procedure TDxDDPGameHook.RunGame;
  101. var
  102.   i,j: Integer;
  103.   tmpArray: Array[1..8,1..25] of byte;
  104.   procedure ChangePoint(a,b: TPoint);
  105.   var
  106.     MPs: DWORD;
  107.   begin
  108.     a.x := GameBeginPoint.X + 48*a.X - 30;
  109.     a.y := GameBeginPoint.Y + 48*a.y - 30;
  110.     b.x := GameBeginPoint.X + 48*b.X - 30;
  111.     b.y := GameBeginPoint.Y + 48*b.y - 30;
  112.     //开始交换数据
  113.     MPs := a.X+ a.Y shl 16;
  114.     SendMessage(FDDPGameWnd,WM_LBUTTONDOWN,0,MPs);
  115.     sendMessage(FDDPGameWnd,WM_LBUTTONUP, 0,MPs);
  116.     MPs := b.X+ b.Y shl 16;
  117.     SendMessage(FDDPGameWnd,WM_LBUTTONDOWN,0,MPs);
  118.     sendMessage(FDDPGameWnd,WM_LBUTTONUP, 0,MPs);
  119.   end;
  120.   function testCanClear: Boolean;
  121.   var
  122.     r1,x,y:byte;
  123.   begin
  124.     Result:=false;
  125.     for y := 1 to 8 do //1-8行坐标
  126.     begin
  127.       r1:=1;
  128.       for x := 1 to 7 do  //Y列坐标
  129.       begin
  130.         if tmpArray[x][y] = tmpArray[x+1][y] then
  131.         begin
  132.           Inc(r1);  //累计相同棋子数
  133.           if r1>=3 then
  134.           begin
  135.             Result:=true;
  136.             exit;
  137.           end;
  138.         end
  139.         else r1 := 1;//初始化累计 1
  140.       end;
  141.     end;
  142.     //遍历 1-8 列 看是否有 3子 相连的
  143.     for x := 1 to 8 do
  144.     begin
  145.       r1:=1;
  146.       for y := 1 to 7 do  //列坐标
  147.       begin
  148.         if tmpArray[x][y]=tmpArray[x][y+1] then
  149.         begin
  150.           Inc(r1);  //累计相同棋子数
  151.           if r1>=3 then
  152.           begin
  153.             Result:=true;
  154.             exit;
  155.           end;
  156.         end
  157.         else r1 := 1;//初始化累计 1
  158.       end;
  159.     end;
  160.   end;
  161. var
  162.   tmp: Byte;
  163. begin
  164.   //开始执行游戏
  165.   if not GameClose then
  166.   begin
  167.      if not GetAnimalArrayData then
  168.      begin
  169.        StartGame(RunTimer.Interval);
  170.        exit;
  171.      end;
  172.      //先纵向比较
  173.      for I := 1 to 8 do
  174.      begin
  175.        for j := 1 to 7 do
  176.        begin //有两个相似
  177.          CopyMemory(@tmpArray,@AnimalArray,200);
  178.          tmp:=tmpArray[I][J];
  179.          tmpArray[i][j]:=tmpArray[i][j+1];
  180.          tmpArray[i][j+1]:=tmp;//交换相临棋子
  181.          if testCanClear then
  182.          begin
  183.            ChangePoint(Point(I,j),Point(i,j+1));
  184.            exit;          
  185.          end;
  186.        end;
  187.      end;
  188.      {if not GetAnimalArrayData then
  189.      begin
  190.        StartGame(RunTimer.Interval);
  191.        exit;
  192.      end; }
  193.      //横向比较
  194.      for j := 1 to 8 do
  195.      begin
  196.        for i := 1 to 7 do
  197.        begin //有两个相似
  198.          CopyMemory(@tmpArray,@AnimalArray,200);
  199.          tmp:=tmpArray[i][j];
  200.          tmpArray[i][j]:=tmpArray[i+1][j];
  201.          tmpArray[i+1][j]:=tmp; //交换相临的2点
  202.          if testCanClear then
  203.          begin
  204.            ChangePoint(Point(I,j),Point(i+1,j));
  205.            exit;          
  206.          end; 
  207.        end;
  208.      end;
  209.   end;
  210. end;
  211. procedure TDxDDPGameHook.SetInterver(Interval: Integer);
  212. begin
  213.   RunTimer.Interval := Interval;
  214. end;
  215. procedure TDxDDPGameHook.StartGame(Info: Integer);
  216. var
  217.   str: string;
  218. begin
  219.   FDDPGameWnd := Windows.FindWindowW(nil,PWchar(UTF8Decode('对对碰角色版')));
  220.   GameClose := FDDPGameWnd = 0;
  221.   ProcId := 0;
  222.   if not GameClose  then
  223.   begin   
  224.    //模拟鼠标单击
  225.     SendMessage(FDDPGameWnd,WM_LBUTTONDOWN,0,$0180017A);//按下
  226.     SendMessage(FDDPGameWnd,WM_LBUTTONUP, 0, $0180017A);//弹起
  227.     RunTimer.Interval := Info;
  228.     RunTimer.Enabled := True;
  229.     if Assigned(FOnStart) then
  230.       FOnStart(Self);
  231.   end;
  232. end;
  233. end.
复制代码
所有代码,一会回来了之后提供

评分

参与人数 1威望 +16 收起 理由
猫工 + 16 优秀文章

查看全部评分

回复

使用道具 举报

该用户从未签到

发表于 2010-4-5 18:05:34 | 显示全部楼层
非常喜欢。
是从delphi移值过来的吧?
谢谢分享
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2010-4-5 20:18:05 | 显示全部楼层
最开始,我是用delphi写的,然后移动到这个上来地!呵呵!基本上没啥很大的改动!就是那个
FindWindow的API函数,对中文的处理,搞了半天!
现在传上所有代码哈!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册(注册审核可向QQ群索取)

x
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2010-4-6 00:08:24 | 显示全部楼层
谢谢分享,这是使用 WIN AIP的.我一直都没有用 LAZ去试, DELPHI就搞過
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2010-4-17 20:34:00 | 显示全部楼层
   这个真的好!得顶、得顶!!!谢谢楼主!!!
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2010-4-22 14:06:28 | 显示全部楼层
这个真的好!得顶、得顶!!!谢谢楼主!!!
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2010-10-23 20:13:35 | 显示全部楼层
顶~~~~
学习了~~~~~~~~~~~~~~~~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2010-11-22 11:29:27 | 显示全部楼层
顶~~~~
学习了~~~~~~~~~~~~~~~~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2010-11-22 11:37:10 | 显示全部楼层
强!喜欢原创!谢谢!
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2010-11-24 20:08:13 | 显示全部楼层
找了好多都没有找到关于中文处理的问题
回复 支持 反对

使用道具 举报

*滑块验证:

本版积分规则

QQ|手机版|小黑屋|Lazarus中国|Lazarus中文社区 ( 鄂ICP备16006501号-1 )

GMT+8, 2025-5-2 18:19 , Processed in 0.048274 second(s), 10 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表