发新话题
打印

分析[连连看]游戏外挂

分析[连连看]游戏外挂

本文中的连连看是以QQ游戏中的连连看为例,编写平台为VC++ 6.0
游戏外挂分很多种,我认为最容易编写的就是模拟鼠标键盘的游戏外挂。
由于连连看这个游戏的性质,所以只要外挂能分析出相同的2张图片,然后给游戏发送点击鼠标的消息,就可是实现外挂的功能了。
下面是基本的算法:
游戏窗口中虽然地图形状是随机的,但是地图大小是固定,11行 X 19列,小方块图片大小是31*35
第一步建立一个坐标数组,保存地图的11行19列分割开来的小方形。
在MFC中可以这样写:
CPoint rects[11][19];//只需要保存矩形的中心即可,因为长度和宽度都知道
同时根据地图在窗口中的位置,填充所有小方形的值。(实际上这一步只是为了方便下面的计算。)
分析整个地图,得出哪些图片是背景图片,哪些图片是需要点击的图片,
然后存到一个11*19的 01 矩阵B,假设0表示背景,1表示其他图片。
第二步遍历那些不是背景图片的小方形,找出2个相同图片的方形,再分析这两个方形之间是否有通路,
如果有通路,把这2个方形的位置存入一个容器(我在程序中使用VECTOR),容器中存的内容应该大概如下:

(1,2)-(2,2) 表示第1行第2列的方形和第2行第2列的方形存的图片一样而且有通路
(2,3)-(7-8)
(3,4)-(2,2)
.....

第三步这个时候容器里面应该存了第一次连图之前所有可以连的2个方形的位置,只是可能存在数据冗余,
比如(1,2)-(2,2)之间连过了,那么(2,2)的图片应该就消失了,只是容器里面还有一对(3,4)-(2,2),这一对连图不应该再连了,
因为(2,2)的图片已经不存在。
第四步去除了所有的数据冗余之后,开始给游戏窗口发送鼠标点击的MESSAGE,让窗口自动连图,同时修改01矩阵B,把连过的地方
改成0。
第五步等到容器中所有的元素都进行过连图,重新回到第二步,重新计算所有存在通路的图片。
第六步等到01矩阵B中所有都是0了,说明全部已经连接完毕。
连连看的游戏外挂设计有几个要点:
1.如何取得游戏窗口,用于待会给它发送鼠标点击的消息?
方法有很多个,可以通过枚举当前桌面上的所有窗口的方法,再经过判断来取得窗口的句柄。
这里介绍比较方便的方法,通过当前鼠标位置来取得鼠标下面的窗口。
代码:
POINT point;
  ::GetCursorPos(&point);
  HWND hwnd=::WindowFromPoint(point);

这里用到2个API函数,GetCursorPos是取得当前鼠标在屏幕上的坐标。
WindowFromPoint是根据鼠标坐标取得窗口的句柄。为什么要取得窗口的句柄呢?
WIN32的很多API函数都是以句柄来作为参数的,所以只有取得了窗口的句柄,才可以在这个窗口上面干很多事情。
下面给出这2个API的原型请参考MSDN。
2.如何取得2个相同的图片?
方法可能有很多,我采用的方法是在2个图片上取3对样本点,比较他们的RGB值,3对样本都一样,说明就是一样的图片。
3.如果分辨出背景图片和非背景图片?
由于背景图片是固定的,虽然背景图片并不是单一的颜色,但是我通过截图分析,背景图片主要是由这4种颜色构成:
RGB值=7753015
RGB值=7555636
RGB值=7423794
RGB值=7490100
当然并不完全是这4种颜色,但是背景图片上其他颜色也和这4个颜色的RGB值相差不远。
所以和第二个要点类似,我在图片上取得3个点得RGB值,通过API函数取出他们的RGB分量,
再和上面提到的4种颜色的RGB分量比较,只要容差不超过20,就当作是背景颜色,
如果非背景图片的3个点的颜色都和背景颜色差不多的话,那么这个算法就会出错,但是
根据游戏图片的分析,这种情况是不大可能的,概率是小到可以忽略的。
4.如果知道2个相同图片之间有通道?
还记得上面提到的01矩阵B么?它对计算是否存在通道大有用处。
问题转变到01矩阵B中两个1之间是否有连线,不经过任何一个1而且最多转2次方向。
这个算法我是通过递归来做的。具体就不详细列出。这个算法属于整个程序中的核心算法。
5.如何给窗口发送消息?
知道窗口的句柄hwnd之后,通过API函数SendMessage就可以发送鼠标消息了
原型如下:
LRESULT SendMessage(
  HWND hWnd,      // handle of destination window
  UINT Msg,       // message to send
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
);
Msg填写鼠标左键消息WM_LBUTTONDOWN,
wParam填写MK_LBUTTON,
lParam表示鼠标点击位置

它是一个32位的数,假设我们要鼠标点击(12,10),只需要这样写:
lParam=MAKELONG(12,10);
6.程序中为了方便控制外挂开始和暂停,我是采用注册HOTKEY快捷键来实现,以及子线程发送消息的方式。
妖城欢迎您!

TOP

发新话题