大概的思路是这样的:首先1.找到游戏窗口->
                                                2.解析方块的位置、图案->
                                                3.遍历方块,找到可以消去的方块->
                                                4.计算方块在窗口中的位置,模拟鼠标点击



大家都知道连连看的规则是:如果两个方块的连线小于等于两个直角时,这对方块就可以消去。所以除了两个方块之间用直线连接外,还有另外这两种情况。

1.一个直角

2.两个直角

根据上述情况,就可以归纳出一种统一的算法。即:首先找出图案相同的两个方块,分别向他们的四个方向引出四条线段,线段的另一端终止于边缘,或者其它的方块处。分别判断水平与水平、竖直与竖直方向的线段的横坐标、纵坐标是否有交集。如果没有两个方向都没有交集,则这两个方块不能消去。如果有,再在任一条线段有交集的位置向另一条线段连线,如果连线成功(中间无无方块阻碍或者两线段相连),则两方块可以消去。

至于方块图案的判断,是因为背景的图案颜色非常靠近(现在“角色版”索性为单色背景),分别取最亮处,与最暗处的RGB值。找出R,G,B值的最大、最小值。判断的时候是在方块上取出任意几个点的(程序中为4个点)RGB值,如果这四个点的R,G,B值都在背景色R,G,B的最大、最小值的范围内,则断定这个方格上没有方块。

其中比较重要的两个技巧就是这样。我把主要的代码贴出来:

class CLLKer  
...{
public:
    CLLKer();
    virtual ~CLLKer();

    // 设置窗口标题
    void SetWndCaption(CString strCaption)...{ m_strWndCaption = strCaption; }

    // 设置方块个数
    void SetCellCount(UINT nHorCount, UINT nVerCount) ...{ 
        m_nHorCellCount = nHorCount;
        m_nVerCellCount = nVerCount;
    }

    // 设置单元格大小
    void SetCellSize(UINT nWidth, UINT nHeight) ...{
        m_nCellWidth = nWidth;
        m_nCellHeight = nHeight;
    }
    
    // 设置边界
    void SetMagin(UINT nLeft, UINT nTop) ...{
        m_nMargin_X = nLeft;
        m_nMargin_Y = nTop;
    }    

    /**/

    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_pMap;            // 单元格布局
    CWnd *m_pWnd;            // 游戏窗口
    vector<CELL> m_vCells;    // 单元格信息

    /**///
    // 参数
    CString m_strWndCaption;
    UINT m_nHorCellCount;
    UINT m_nVerCellCount;
    UINT m_nCellWidth;
    UINT m_nCellHeight;
    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

// Implementation
protected:
    //{{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_MAP
END_MESSAGE_MAP()

/**//////
// CLLKDlg dialog

CLLKDlg::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_MAP
END_MESSAGE_MAP()

/**//////
// CLLKDlg message handlers

BOOL 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 strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);
        if (!strAboutMenu.IsEmpty())
        ...{
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    // TODO: Add extra initialization here
    /**/////
    // 取得配置文件路径
    char szModulPath[_MAX_PATH] = ...{0};
    GetModuleFileName(NULL, szModulPath, _MAX_PATH);
    CString strPath = szModulPath;
    int iPos = strPath.ReverseFind('/');
    m_strInitPath = strPath.Left(iPos+1);
    m_strInitPath += "CONFIG.INI";
    /**/////

    CRect rcWnd;
    GetWindowRect(rcWnd);

    int iPos_X = GetPrivateProfileInt("OPTION", "POS_X", 500, m_strInitPath);
    int iPos_Y = GetPrivateProfileInt("OPTION", "POS_Y", 700, m_strInitPath);
    
    rcWnd.OffsetRect(iPos_X, iPos_Y);

    MoveWindow(rcWnd, FALSE);

    BOOL m_bIsTopMost = GetPrivateProfileInt("OPTION", "TOPMOST", 0, m_strInitPath);
    CheckDlgButton(IDC_CHK_TOPMOST, m_bIsTopMost);
    HWND hWnd = this->GetSafeHwnd();
    
    if ( m_bIsTopMost )
        ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
    else
        ::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);

    SetTimer(1, 100, NULL);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

void CLLKDlg::OnSysCommand(UINT nID, LPARAM lParam)
...{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    ...{
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    ...{
        CDialog::OnSysCommand(nID, lParam);
    }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CLLKDlg::OnPaint() 
...{
    if (IsIconic())
    ...{
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    ...{
        CDialog::OnPaint();
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CLLKDlg::OnQueryDragIcon()
...{
    return (HCURSOR) m_hIcon;
}

void CLLKDlg::OnLock() 
...{
    // TODO: Add your control notification handler code here
    if ( m_LLKer.LockWnd() ) 
    ...{
        AfxMessageBox("锁定成功", MB_ICONINFORMATION);

        m_bStarted = TRUE;
        return;
    }
    AfxMessageBox("未找到游戏窗口,请确认窗口名称是否正确", MB_ICONERROR);
}

void CLLKDlg::OnEncode() 
...{
    // TODO: Add your control notification handler code here
    UINT nBlock = m_LLKer.Encode();
    if ( nBlock > 0 )
    ...{
        AfxMessageBox("解析成功!", MB_ICONINFORMATION);
    }
}

void CLLKDlg::OnDelete() 
...{
    // TODO: Add your control notification handler code here
    UpdateData(TRUE);

    POINT ptCursor;
    
    int iRes = ::GetCursorPos(&ptCursor);

    if ( m_bAutoElmit )
    ...{
        m_LLKer.EliminateAll();
        ::SetCursorPos(ptCursor.x, ptCursor.y);
    }
    else
    ...{
        if ( m_LLKer.EliminateOnePair() )
            ::SetCursorPos(ptCursor.x, ptCursor.y);
    }
}

void CLLKDlg::OnTimer(UINT nIDEvent) 
...{
    // TODO: Add your message handler code here and/or call default
    if ( !m_LLKer.CheckWnd() && m_bStarted )
    ...{
        m_LLKer.Reset();
    }
    CDialog::OnTimer(nIDEvent);
}

void CLLKDlg::OnChkTopmost() 
...{
    // TODO: Add your control notification handler code here
    UpdateData(TRUE);
    
    HWND hWnd = this->GetSafeHwnd();

    if ( m_bIsTopMost )
        ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
    else
        ::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);

    CString strBuf;
    strBuf.Format("%d", m_bIsTopMost);
    WritePrivateProfileString("OPTION", "TOPMOST", strBuf, m_strInitPath);
}

BOOL CLLKDlg::DestroyWindow() 
...{
    // TODO: Add your specialized code here and/or call the base class

    CRect rcWnd;
    GetWindowRect(rcWnd);
    
    CString strBuf;

    strBuf.Format("%d", rcWnd.left);
    WritePrivateProfileString("OPTION", "POS_X", strBuf, m_strInitPath);
    strBuf.Format("%d", rcWnd.top);
    WritePrivateProfileString("OPTION", "POS_Y", strBuf, m_strInitPath);

    return CDialog::DestroyWindow();
}

QQ游戏连连看外挂(VC)相关推荐

  1. 自制 QQ游戏 连连看 外挂 ~~

    这几天期末考,完全没有考试的心情,又无聊到玩起连连看,可惜输得太多,非常不爽,于是自己做个连连看外挂玩一下.网上有很多连连看的外挂可以下载,不过自己做一个来用,感觉自然不一样,毕竟还是学计算机的嘛~~ ...

  2. 连连看外挂消去算法分析

    很久之前发布了一个小外挂,是我自己捣鼓出来的QQ游戏连连看外挂. 见:http://www.cnblogs.com/G_Weber/archive/2009/06/02/1494871.html 在做 ...

  3. 【Python游戏外挂】满级小孩进新手村,实现连连看外挂秒杀

    前言: 哈喽~在连连看中满级大佬进新手村是一个什么样的体验? 连连看小游戏,新手必看之正确打开方式[高燃慎入]全是技巧 没有感情 [Python制作游戏外挂]满级大佬进新手村,连连看你看清楚了没? 需 ...

  4. [转载]关于QQ游戏外挂mouse_event不起作用的原因,及我的对对碰外挂程序.

    资源名称 关于QQ游戏外挂mouse_event不起作用的原因,及我的对对碰外挂程序. 作者: dongfa 适用语言: .NET 文件大小 2161 运行平台: Windows XP 上传者: sh ...

  5. 200行Python实现效果逆天的连连看外挂

    本文内容转自我本人的知乎回答:你看过/写过哪些有意思的代码? - 三级狗的回答 - 知乎 https://www.zhihu.com/question/275611095/answer/4079841 ...

  6. QQ游戏外挂制作教程 (对对碰)

    这些日子,QQ游戏外挂是风光了一阵.俄罗斯方块,连连看,对对碰这些游戏的外挂层出不穷.其实这一类外挂的原理大体都是一样的.下面我就以QQ游戏对对碰外挂作为例子阐述一下QQ外挂的制作原理.       ...

  7. 美味连连-QQ游戏辅助-简单实用的QQ游戏美味连连辅助(非外挂)

    这是2013年最好玩的悠闲游戏"美味连连"的辅助软件, 个人认为是目前最好用的QQ游戏"美味连连"辅助软件! 本程序由我原来写的"QQ连连看辅助&qu ...

  8. QQ游戏美女找茬外挂

    前段时间看到别人玩QQ游戏,美女来找茬,突然之间想到自己可以做个小外挂,自动比较两幅图,把不同之处标出来.软件自动化测试和开发简单的游戏外挂很相似.都是控制UI,然后模拟键盘和鼠标操作 思路: 1. ...

  9. 《QQ游戏外挂制作教程》一文的补遗

    前段时间发的这篇文章<QQ游戏外挂制作教程(对对碰)>主要阐述了目前QQ游戏外挂一般的工作原理. 近日收到一些网友的邮件,询问如何其中的一些细节.主要是关于对对游戏中的一些点的坐标,颜色的 ...

  10. 教你用VC6做QQ对对碰外挂程序

    前段时间跟以前的同事玩QQ游戏对对碰,结果输的好惨,后来在网上看到了有对对碰的外挂,但还需要注册,就考虑既然别人可以写出来,我为什么就不能写出来呢?于是花了一个下午的时间仔细研究了一下,把外挂写了出来 ...

最新文章

  1. [文档].Altera - 可选择的Nios II的Boot方法
  2. python调用c++动态库 linux_linux中使用boost.python调用c++动态库的方法
  3. FFT IP核调用与仿真之SCALE压缩因子设置
  4. Call to undefined function mysqli_connect()
  5. python3 for循环怎么用_Python3入门系列之-----循环语句(for/while)
  6. halcon 旋转_HALCON高级篇:3D相机标定(3/3)
  7. 重磅!ICDAR 2019-LSVT街景文字识别国际竞赛!奖金丰厚
  8. 51CTO‘s Bug?
  9. 试用officescan 10.5
  10. 【软件测试】:测试通过标准
  11. 四轴飞行器基本组成及其飞行原理详解
  12. linux中PATH环境变量的作用和使用方法
  13. 数据库附加失败解决方法
  14. shell 小米system锁adb_忘记锁屏密码不用怕?支招小米手机解锁四种简单常用的方法...
  15. MATLAB泰勒级数展开
  16. 收藏:不错的数据中台建设方法论
  17. 面向对象三大特征---继承
  18. Social LSTM: Human Trajectory Prediction in Crowded Spaces
  19. 谷歌浏览器F12断点调试按钮说明
  20. JavaScript踩坑(5)比值函数 function(a, b)

热门文章

  1. 怎么解决redis雪崩和穿透
  2. editormd html 转义,Markdown(editormd)语法解析成HTML
  3. hilbert方程组matlab,数值分析(Hilbert矩阵)病态线性方程组的求解Matlab程序
  4. 突然间的一个阿里电话面试
  5. 根据省份id查询当前的省会/简称/省会城市
  6. PLC 有哪几种常用编程语言
  7. 基于 软件体系结构(第3版)考试重点和复习指南
  8. h264html实时播放,H5播放H264之websocket
  9. 学习C语言未来的发展方向
  10. 丹尼斯·里奇的自述简历