QQ连连看外挂制作
这几天做了个外挂,主要是想学习下相关技术,
参考的是郁金香老师的视频
核心算法是我自己实现的
?
我在判断3条线路连通性时,用了4个辅助点,纵向pa和pb,横向pc和pd
让其中2个点与我们棋盘上的棋子形成一个矩形,
然后遍历它们组成这个矩形的所有行和所有列
把所有的情况都考虑成3条路径,因为它们都在一个矩形上
其中有的点重合的话那就是2条或1条路径
只要保证2个参考点p1和p2不重叠就行了
纵向时的pa与pb 可以和参考点p1或p2重叠?
横向时的pc与pd 可以和参考点p1或p2重叠

?
?
?
xp_sp2
vc6的MFC程序
在框架代码中调用下面的方法就可以了
?
//llk_wg.hconst PCHAR gameCaption="QQ游戏 - 连连看角色版"; //程序窗口标题const LPARAM lpStartMenu= (568<<16)+655;//开始按钮坐标HWND hGame=::FindWindow(NULL,gameCaption);//获取游戏窗口句柄DWORD dwProcessId;//进程的pidHANDLE hProcess;//进程句柄LPCVOID lpBaseAddress;//基地址byte arrChessData[11][19];//棋盘数据存放DWORD rDwLen;//实际读取的字节数LPDWORD lpNumberOfBytesRead=&rDwLen;//实际读取的字节数指针BOOL readFlag=false;//读取数据标志失败BOOL ReadData(LPCVOID lpBaseAddress,LPVOID lpRead,DWORD nsize);//读数据void LeftClick(POINT pp);//模拟鼠标单击BOOL ReadChessData();//读棋盘数组数据BOOL CheckChess(POINT p1,POINT p2);//检测棋子是否可清除BOOL CheckLine2p(POINT pi,POINT pj);//检测2点是否直通(无障碍)BOOL Click2p(POINT p1,POINT p2);//模拟点击消息void ClearPairOfChess(BOOL b);//消除棋子主过程void KillAll();//秒杀void AutoStart();//自动开局BOOL CheckLine2p(POINT pi,POINT pj)//检测同行或同列的2点是否连通(无障碍){//关键算法之一POINT pUp;POINT pDown;POINT pLeft;POINT pRight;if ((pi.x==pj.x)&&(pi.y==pj.y)) //棋子重叠可连通{return true;}if (pi.x==pj.x)//同列时(x相等,y不等){if (pi.y<pj.y){pUp=pi;pDown=pj;}else{pUp=pj;pDown=pi;}if ( 1==(pDown.y-pUp.y) )//相邻棋子可连通{return true;}else//不相邻时{for (int lineNum=pUp.y+1; lineNum<pDown.y; lineNum++) {if (arrChessData[lineNum][pUp.x]!=0){return false;//有障碍}}}}//if (pi.y==pj.y)//同行时(x不等,y相等){if (pi.x<pj.x){pLeft=pi;pRight=pj;}else{pLeft=pj;pRight=pi;}if ( 1==(pRight.x-pLeft.x) )//相邻棋子可连通{return true;}else{for (int columnNum=pLeft.x+1; columnNum<pRight.x; columnNum++){if (arrChessData[pLeft.y][columnNum]!=0){return false;//有障碍}}}}//return true;}BOOL CheckChess(POINT p1,POINT p2) //检测棋子可否消除{//关键算法之一bool checkFlag=false;POINT pa,pb;//pa的x坐标与p1相等,pb的x坐标与p2相等pa.x=p1.x;pb.x=p2.x;POINT pc,pd;//pc的y坐标与p1相等,pd的y坐标与p2相等pc.y=p1.y;pd.y=p2.y;for (int lineNum=0;lineNum<11;lineNum++){pa.y=lineNum;pb.y=lineNum;if( CheckLine2p(p1,pa)&&CheckLine2p(pa,pb)&&CheckLine2p(pb,p2) ){//Click2p(p1,p2); //执行消除checkFlag=true;}}for (int columnNum=0;columnNum<19;columnNum++){pc.x=columnNum;pd.x=columnNum;if ( CheckLine2p(p1,pc)&&CheckLine2p(pc,pd)&&CheckLine2p(pd,p2) ){//Click2p(p1,p2); //执行消除checkFlag=true;}}return checkFlag;}BOOL Click2p(POINT p1,POINT p2) //模拟单击事件{//棋子宽度31,高度35 //int x=25,y=195;//第一个棋子坐标LeftClick(p1);LeftClick(p2);ReadChessData();if (arrChessData[p1.y][p1.x]==0){return true;//成功消除一对棋子}return false;}void KillAll()//秒杀{for (int a=0;a<10;a++){ClearPairOfChess(true); //一般5次循环内就完成秒杀}}void ClearPairOfChess(BOOL b)//清除一对棋子的主过程{ReadChessData();//更新一下棋盘数据//遍历棋盘,找出成对的棋子POINT p1,p2;int x1,y1;int x2,y2;for (y1=0;y1<11;y1++)//遍历行数y{for (x1=0;x1<19;x1++) //遍历列数x{if (arrChessData[y1][x1]!=0) //不为空子时,此子设为p1{for (y2=y1;y2<11;y2++){for (x2=0;x2<19;x2++){if ((arrChessData[y1][x1]==arrChessData[y2][x2])&&(!((x1==x2)&&(y1==y2))) ){ //存在p2时p1.x=x1;p1.y=y1;p2.x=x2;p2.y=y2;if (CheckChess(p1,p2)) //检测是否可清除{if (Click2p(p1,p2))//消除{if (!b) //不秒杀{return;}}}}}}}}}}void LeftClick(POINT pp)//模拟鼠标单击{if (hGame){LPARAM lParam = ((195+pp.y*35)<<16)+(25+pp.x*31);SendMessage(hGame,WM_LBUTTONDOWN,0,lParam);SendMessage(hGame,WM_LBUTTONUP,0,lParam);}}void AutoStart() //自动开始按钮{hGame=::FindWindow(NULL,gameCaption);//获取游戏窗口句柄if (hGame){LPARAM lParam = lpStartMenu;//(568<<16)+655PostMessage(hGame,WM_LBUTTONDOWN,MK_LBUTTON,lParam);PostMessage(hGame,WM_LBUTTONUP,0,lParam);}}BOOL ReadData(LPCVOID lpBaseAddress,LPVOID lpRead,DWORD nsize) //读数据{//3个参数分别是,基址,读取数据存放的缓冲区指针,要读取的数据大小hGame=::FindWindow(NULL,gameCaption);//获取游戏窗口句柄if (hGame==NULL){//AfxMessageBox(gameErr); return readFlag;}::GetWindowThreadProcessId(hGame,&dwProcessId);//获取进程idhProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,dwProcessId); //打开readFlag=::ReadProcessMemory(hProcess,lpBaseAddress,lpRead,nsize,lpNumberOfBytesRead);//读一个字节return readFlag;}BOOL ReadChessData()//读棋盘数组数据{lpBaseAddress= (LPCVOID)0x0012A480;//棋盘数组基址ReadData(lpBaseAddress,arrChessData,sizeof(byte)*11*19);return readFlag;}?
1 楼 genime 2012-04-07 请教一下,为什么我读的棋盘数据都是00呢 2 楼 genime 2012-04-07 请教一下,为什么我查找的基址是一样的,读出来的都是00 呢? 座位号读的倒是对的 3 楼 genime 2012-04-07 已经搞定了- - 4 楼 xouou_53320 2012-04-08 genime 写道已经搞定了- -哦 5 楼 xouou_53320 2012-05-02 //支持xp和win7
void CheckOsVersion()
{
OSVERSIONINFO ovi;
ovi.dwOSVersionInfoSize=sizeof(ovi);
GetVersionEx(&ovi);
if (ovi.dwMajorVersion == 5 && ovi.dwMinorVersion == 1) //WinXP
{
//MessageBox(NULL,"xp系统","提示",MB_OK);
lpBaseAddress = (LPCVOID)0x0012A480;//基址
}
else if (ovi.dwMajorVersion == 6 && ovi.dwMinorVersion == 1) //Win7
{
lpBaseAddress = (LPCVOID)0x0012A444;
}else
{
MessageBox(NULL,"版本不支持!","提示",MB_OK);
ExitProcess(0);
}
}