下次自动登录
现在的位置:
& 综合 & 正文
QQ游戏连连看外挂(VC)
大概的思路是这样的:首先1.找到游戏窗口-&
2.解析方块的位置、图案-&
3.遍历方块,找到可以消去的方块-&
4.计算方块在窗口中的位置,模拟鼠标点击。
大家都知道连连看的规则是:如果两个方块的连线小于等于两个直角时,这对方块就可以消去。所以除了两个方块之间用直线连接外,还有另外这两种情况。
1.一个直角
2.两个直角
根据上述情况,就可以归纳出一种统一的。即:首先找出图案相同的两个方块,分别向他们的四个方向引出四条线段,线段的另一端终止于边缘,或者其它的方块处。分别判断水平与水平、竖直与竖直方向的线段的横坐标、纵坐标是否有交集。如果没有两个方向都没有交集,则这两个方块不能消去。如果有,再在任一条线段有交集的位置向另一条线段连线,如果连线成功(中间无无方块阻碍或者两线段相连),则两方块可以消去。
至于方块图案的判断,是因为背景的图案颜色非常靠近(现在“角色版”索性为单色背景),分别取最亮处,与最暗处的RGB值。找出R,G,B值的最大、最小值。判断的时候是在方块上取出任意几个点的(中为4个点)RGB值,如果这四个点的R,G,B值都在背景色R,G,B的最大、最小值的范围内,则断定这个方格上没有方块。
其中比较重要的两个技巧就是这样。我把主要的贴出来:
class CLLKer
...{public:
virtual ~CLLKer();
// 设置窗口标题
void SetWndCaption(CString strCaption)...{ m_strWndCaption = strC }
// 设置方块个数
void SetCellCount(UINT nHorCount, UINT nVerCount) ...{
m_nHorCellCount = nHorC
m_nVerCellCount = nVerC
// 设置单元格大小
void SetCellSize(UINT nWidth, UINT nHeight) ...{
m_nCellWidth = nW
m_nCellHeight = nH
// 设置边界
void SetMagin(UINT nLeft, UINT nTop) ...{
m_nMargin_X = nL
m_nMargin_Y = nT
/**/////////////////////////////////////////////////////////////////////////////////////
BOOL LockWnd();
// 锁定窗口
UINT Encode();
// 扫描窗口记录布局信息
BOOL EliminateOnePair();
void EliminateAll();
BOOL CheckWnd();
void Reset();private:
/**///////////////////////
// 功能函数
int CompareTowColor(COLORREF cColor1, COLORREF cColor2);
// 返回两颜色的RGB的差值和
int SearchColor(COLORS color);
// 取得颜色相同的Cell索引值
void FindXLine(const POS& pos, int& iLeft, int& iRight);
// 取得水平方向的路径
void FindYLine(const POS& pos, int& iTop, int& iLow);
// 取得竖直方向的路径
BOOL IsXPath(const POS& pos1, const POS& pos2);
// 水平方向的路径是否相通
BOOL IsYPath(const POS& pos1, const POS& pos2);
// 竖直方向的路径是否相通
BOOL IsPath(const POS& pos1, const POS& pos2);
// 判断两单元格是否存在连通路径
BOOL FindMatchingCell(const POS& pos, POS& posMathed);
// 找到指定方块的匹配方块
BOOL FindPair(POS& posOri, POS& posMathed);
// 找到一对可消除的方块
void ReleaseData();
/**///////////////////////
// 中间变量
int **m_pM
// 单元格布局
CWnd *m_pW
// 游戏窗口
vector&CELL& m_vC
// 单元格信息
/**///////////////////////
CString m_strWndC
UINT m_nHorCellC
UINT m_nVerCellC
UINT m_nCellW
UINT m_nCellH
UINT m_nMargin_X;
UINT m_nMargin_Y;
UINT m_nMax_R;
UINT m_nMax_G;
UINT m_nMax_B;
UINT m_nMin_R;
UINT m_nMin_G;
UINT m_nMin_B;};
class CAboutDlg : public CDialog...{public:
CAboutDlg();// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum ...{ IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
// DDX/DDV support
//}}AFX_VIRTUAL// Implementationprotected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)...{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX)...{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAPEND_MESSAGE_MAP()/**//////////////////////////////////////////////////////////////////////////////// CLLKDlg dialogCLLKDlg::CLLKDlg(CWnd* pParent /**//*=NULL*/)
: CDialog(CLLKDlg::IDD, pParent)...{
//{{AFX_DATA_INIT(CLLKDlg)
m_bAutoElmit = FALSE;
m_bIsTopMost = FALSE;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()-&LoadIcon(IDR_MAINFRAME);
m_bStarted = FALSE;}void CLLKDlg::DoDataExchange(CDataExchange* pDX)...{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CLLKDlg)
DDX_Check(pDX, IDC_CHK_AUTO, m_bAutoElmit);
DDX_Check(pDX, IDC_CHK_TOPMOST, m_bIsTopMost);
//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CLLKDlg, CDialog)
//{{AFX_MSG_MAP(CLLKDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_LOCK, OnLock)
ON_BN_CLICKED(IDC_ENCODE, OnEncode)
ON_BN_CLICKED(IDC_DELETE, OnDelete)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_CHK_TOPMOST, OnChkTopmost)
//}}AFX_MSG_MAPEND_MESSAGE_MAP()/**//////////////////////////////////////////////////////////////////////////////// CLLKDlg message handlersBOOL CLLKDlg::OnInitDialog()...{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX & 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
CString strAboutM
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
pSysMenu-&AppendMenu(MF_SEPARATOR);
pSysMenu
&&&&推荐文章:
【上篇】【下篇】后使用快捷导航没有帐号?
查看: 1763|回复: 1
最后登录QQ注册时间阅读权限10精华积分0帖子
QQ小野人, 积分 0, 距离下一级还需 50 积分
为什么我在连连看1V1房间,不能坐下,每点一下就会出现“这个座位不能使用”
最后登录QQ注册时间阅读权限100精华0积分80984帖子
QQ骑士, 积分 80984, 距离下一级还需 39016 积分
可能是还有其他玩家在游戏
LZ网速慢了稍等下试试看
再不行的话重新***下游戏大厅
孤独的最终产物就是过分的自信和自我满足 ●
Powered by这几天期末考,完全没有考试的心情,又无聊到玩起连连看,可惜输得太多,非常不爽,于是自己做个连连看外挂玩一下。网上有很多连连看的外挂可以下载,不过自己做一个来用,感觉自然不一样,毕竟还是学计算机的嘛~~这里简要记下做的过程,有兴趣自己写的朋友可以参考参考~~~ 我是用MFC做的~开发环境:Xp sp2 、Visual Studio.NET 2003
&&& 一、QQ游戏连连看玩法。 & 玩法非常简单,用鼠标点击两个相同的格子,如果两个格子可以用一条“线”连起来,则这两个格子可以消去。关键是这条“线”最多只能有两个拐点!~
二、外挂的功能需求。 功能简单:一个按键,让游戏自动消去一对格子········
三、外挂原理。 1.获得游戏数据: & 首先,需要获得游戏的格子数据,才能进一步用算出哪两个格子可以消去。对于QQ游戏连连看,可以采用网上比较普遍的做法,读取屏幕像素点,根据像素点判断是什么格子(红球or蓝球or黑桃or······)。 & 为了获得游戏的像素数据,必须先获得游戏窗口的指针,在程序中我注册了几个全局热键,我的机制是用户激活游戏窗口,按下外挂注册的全局热键(例如我的是F1键)。这个时候利用一个API获得窗口指针。 // CWnd*&&&&&&& m_pGameW //游戏窗口 m_pGameWindow = GetForegroundWindow();//取出最“顶”的窗口 && 接着就可以读取游戏窗口的像素值了,基本思想就是写一个循环 for(int i=0;i&11;i++)// 11行 { &&& for(int j=0;j&19;j++)//19列& 全世界都知道QQ的连连看方格是11行19列 &&&&&&& //具体读取像素操作 } 具体代码就不贴了~太多了。。最终的结果是将屏幕的格子数据保存到一个11X19的二维数组中,数组的坐标(i,j)就代表在游戏中第几行,几列。array[i][j]的值如果为0就代表该处为空没有格子,1、2、3····就代表不同的格子。像上面那张图片编码后应该就为: 1 0 0 2 3 0 0 4 5 0 0 6 7 0 0 8 3 0 0 第一行编码的结果 。。其它行的就不再贴了。 2.计算可消去的一对格子: && 我已经将游戏数据保存到了一个二维数组了。接下来就是如何计算一个哪两个格子可以消去.我的做法是将这个二维数组看成一个图,利用我针对连连看改进的宽度图搜索算法。 3.模拟鼠标点击消去格子: 当算法算出两个可消去的格子的数组坐标后,需要将其转换到实际的屏幕坐标,再进行鼠标模拟点击。 void CLLKCheatDlg::Imitate(int beginX,int beginY,int endX,int endY) { &&& //相对于游戏窗口的两个坐标 &&& CPoint begin = getPoint(beginX,beginY); &&& CPoint end = getPoint(endX,endY); &&& //转换到屏幕坐标 &&& m_pGameWindow-&ClientToScreen(&begin); &&& m_pGameWindow-&ClientToScreen(&end);
&&& //移动鼠标到第一个点 &&& ::SetCursorPos(begin.x,begin.y);
&&& mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0); &&& mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
&&& ::SetCursorPos(end.x,end.y); &&& mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0); &&& mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0); } //getPoint是我自己写的,用来计算逻辑坐标到游戏窗口坐标的转换。
四、测试 看看我使用该工具秒杀的截图吧。提供了一个按键,全部消去的功能。 &
阅读(...) 评论()