数据我们已经获取到了,接下来 没有什么能阻止我们实现外挂了~

我们先在我们的游戏中,定义一个[11][19]的byte类型数组 用以存储数据

byte m_szGameData[11][19];

然后再写一个 ReadGameData() 函数 用以读取数据

bool CKyodaiPluginDlg::ReadGameData()
{
    HWND hGameWnd = GetGameHwnd();
    ZeroMemory(m_szGameData, 11 * 19);
    if (!hGameWnd)
    {
        return false;
    }
    DWORD dwPid = false;
    GetWindowThreadProcessId(hGameWnd, &dwPid);
    HANDLE hGameProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
    if (!hGameProcess)
    {
        MessageBox(L”打开进程失败”);
        return false;
    }

    if (!ReadProcessMemory(hGameProcess, (LPVOID)0x00199F68, m_szGameData, sizeof(m_szGameData), NULL))
    {
        return false;
    }
}

上面这段代码大家都很熟悉了,就不做讲解了

接下来就是要怎么消除的问题了,如下图,是否可以消除无非就是三种情况,两个在同一条线上,这也就一条线可以消除,要要门就是2条线段可以消除,最多只能有3条线

我们要判断x1,y1 x2,y能否消除 我们要先构建2个点x3y3,x4y4 如果 x1y1能到达x3y3(也就是说他们直接的数据都是0) 并且x3y3能到达x4y4 并且 x2y2能到达x4y4则 可以消除

//判断两个点之间是不是连通的
bool CLLK_WGDlg::LineIsNull(int nRow, int nCol, int nRow2, int nCol2)
{
    if (nRow2 == nRow && nCol2 != nCol)
    {
        int nColMax = max(nCol2,nCol);
        int nColMin = min(nCol2,nCol);
        for (int y = nColMin; y <= nColMax;y++)
        {
            if (m_szGameData[nRow][y] != 0)
            {
                return false;
            }
        }
        return true;
    }
    else if (nCol == nCol2 && nRow != nRow2)
    {
        int nRowMin = min(nRow,nRow2);
        int nRowMax = max(nRow,nRow2);
        for (int x = nRowMin; x <= nRowMax;x++)
        {
            if (m_szGameData[x][nCol] != 0)
            {
                return false;
            }
        }
        return true;
    }
    else if (nRow2 == nRow && nCol2 == nCol)  // 2点为同一点的情况
    {
        return true;
    }
    else
    {
        return false;
    }

    return true;
}

bool CLLK_WGDlg::IsClear(int nRow, int nCol, int nRow2, int nCol2)
{
    //先把两个点的数据拿出来
    byte data1 = m_szGameData[nRow][nCol];
    byte data2 = m_szGameData[nRow2][nCol2];
    //把两个点的数据置0 是为了两个贴在一起的能消除
    m_szGameData[nRow][nCol] = 0;
    m_szGameData[nRow2][nCol2] = 0;
    int nTmpRow1 = nRow;
    int nTmpRow2 = nRow2;
    for (int nTmpCol = 0; nTmpCol < 19;nTmpCol++)
    {
        if (LineIsNull(nTmpRow1, nTmpCol, nTmpRow2, nTmpCol) && LineIsNull(nTmpRow1, nTmpCol, nRow, nCol) && LineIsNull(nTmpRow2, nTmpCol, nRow2, nCol2))
        {
            m_szGameData[nRow][nCol] = data1;
            m_szGameData[nRow2][nCol2] = data2;
            return true;
        }
    }
    int nTmpCol1 = nCol;
    int nTmpCol2 = nCol2;
    for (int nTmpRow = 0; nTmpRow < 11;nTmpRow++)
    {
        if (LineIsNull(nTmpRow, nTmpCol1,nTmpRow, nTmpCol2) && LineIsNull(nTmpRow,nTmpCol1,nRow, nCol) && LineIsNull(nTmpRow,nTmpCol2, nRow2, nCol2))
        {
            m_szGameData[nRow][nCol] = data1;
            m_szGameData[nRow2][nCol2] = data2;
            return true;
        }
    }
    m_szGameData[nRow][nCol] = data1;
    m_szGameData[nRow2][nCol2] = data2;
    return false;
}

我们再添加一个函数 ClearOne 用于消除一对

void CKyodaiPluginDlg::ClearOne()
{

    ReadGameData();
    for (int nRow = 0; nRow < 11; nRow++)
    {
        for (int nCol = 0; nCol < 19; nCol++)
        {
            if (m_szGameData[nRow][nCol] == 0)
            {
                continue;
            }
            for (int nRow2 = 0; nRow2 < 11; nRow2++)
            {
                for (int nCol2 = 0; nCol2 < 19; nCol2++)
                {
                    if ((nRow2 != nRow || nCol2 != nCol) && m_szGameData[nRow][nCol] == m_szGameData[nRow2][nCol2] && IsClear(nRow, nCol, nRow2, nCol2))
                    {
                        SelectChess(nRow, nCol);
                        SelectChess(nRow2, nCol2);
                        return;
                    }
                }
            }
        }
    }
}

clearOne中 如果判断可以消除 则调用SelectChess

可以消的算法有了,我们双击单消按钮,然后添加代码如下

void CKyodaiPluginDlg::SelectChess(int nRow, int nCol)
{
    HWND hGameWnd = GetGameHwnd();
    if (hGameWnd)
    {
        int nPosXBase = 5;
        int nPosYBase = 165;

        int xPos = (nCol + 1) * 30 + nPosXBase;
        int yPos = (nRow + 1) * 35 + nPosYBase;
        ::PostMessage(hGameWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(xPos, yPos));
        ::PostMessage(hGameWnd, WM_LBUTTONUP, 0, MAKELPARAM(xPos, yPos));
    }
}

上面代码中5,165是第一个图片的位置,30,35是每一格图片的大小

接着,我们在按钮消除一对的响应函数中 增加如下调用一下 ClearOne

//消除一对
void CKyodaiPluginDlg::OnBnClickedBtnremove()
{
    ClearOne();
}

我们运行游戏 测试一下

代码下载

链接: http://pan.baidu.com/s/1slhf00t 密码: 6brk

打赏