首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 6.0 實作 QQ 連連看自動消除外掛

     編輯:VC 教學

前言

連連看類遊戲核心在於「尋找可由不超過三條直線連接的相同圖案對」。本文示範如何在 VC++ 6.0 中,透過視窗截圖、色彩特徵碼識別棋盤格狀、實作尋路演算法、模擬滑鼠點擊,完成一個半自動外掛程式。文中涵蓋畫面辨識、資料結構設計、BFS 尋路與輸入模擬關鍵技術。

一、整體架構流程

  1. 取得遊戲視窗 DC:`FindWindow` → `GetDC` 擷取螢幕像素。
  2. 棋盤格定位與採樣:固定偏移量(如左上角 (10,180)),每格 31×35 像素,每格取 4 個特徵點編碼建立色彩指紋庫。
  3. 建立邏輯地圖:`map[19][11]` 記錄各格對應的色彩索引(0 表空格)。
  4. 尋路演算法:BFS 搜尋兩格之間是否存在 ≤ 3 線段的正交路徑。
  5. 模擬滑鼠點擊:`mouse_event` 發送左鍵下/上,座標換算為螢幕絕對位置。

二、關鍵程式碼解析

1. 色彩特徵擷取與建立索引表

struct MYCOLOR { COLORREF c[4]; }; // 每格 4 採樣點
MYCOLOR tc[230];                 // 色彩指紋庫
int map[19][11];                 // 邏輯棋盤
int tcnum = 1;                   // 索引計數,0 保留給空格

void CZg1Dlg::OnButton3() // 「編碼/辨識」按鈕
{
    int tX[4] = {15,11,15,21}; // 相對 X 偏移
    int tY[4] = {17,17,21,17}; // 相對 Y 偏移
    CPoint base(10, 180);       // 棋盤左上角
    CDC* pDC = m_gameWnd->GetDC();

    for (int row = 0; row < 11; ++row)
    {
        for (int col = 0; col < 19; ++col)
        {
            MYCOLOR tmp;
            for (int k = 0; k < 4; ++k)
                tmp.c[k] = pDC->GetPixel(base.x + col*31 + tX[k], base.y + row*35 + tY[k]);

            // 簡易背景色過濾(依實際遊戲調整 RGB 範圍)
            bool isBg = true;
            for (int k = 0; k < 4; ++k) {
                int r = GetRValue(tmp.c[k]), g = GetGValue(tmp.c[k]), b = GetBValue(tmp.c[k]);
                if (!((r>45&&r<73) && (g>50&&g<90) && (b>103&&b<129))) { isBg = false; break; }
            }
            if (isBg) { map[col][row] = 0; continue; }

            // 查找或新增指紋
            int idx = -1;
            for (int i = 1; i < tcnum; ++i)
                if (memcmp(&tc[i], &tmp, sizeof(MYCOLOR)) == 0) { idx = i; break; }
            if (idx == -1) { tc[tcnum] = tmp; idx = tcnum++; }
            map[col][row] = idx;
        }
    }
    m_gameWnd->ReleaseDC(pDC);
}

2. BFS 尋路判斷可消除

struct Node { int x, y, dir, turns; };
bool CanLink(int x1, int y1, int x2, int y2)
{
    if (map[x1][y1] == 0 || map[x1][y1] != map[x2][y2]) return false;
    const int dx[4] = {0,0,1,-1}, dy[4] = {1,-1,0,0};
    bool vis[21][13][4][4] = {}; // x,y,dir,turns
    queue q;
    // 從起點四個方向展開
    for (int d = 0; d < 4; ++d) {
        int nx = x1 + dx[d], ny = y1 + dy[d];
        if (nx>=0 && nx<19 && ny>=0 && ny<11 && (map[nx][ny]==0 || (nx==x2&&ny==y2)))
            q.push({nx,ny,d,0}), vis[nx][ny][d][0]=true;
    }
    while (!q.empty()) {
        Node cur = q.front(); q.pop();
        if (cur.x == x2 && cur.y == y2) return true;
        for (int d = 0; d < 4; ++d) {
            int nx = cur.x + dx[d], ny = cur.y + dy[d];
            int nt = cur.turns + (d != cur.dir);
            if (nt > 3) continue; // 最多 3 線段 = 2 轉彎
            if (nx<0||nx>=19||ny<0||ny>=11) continue;
            if (map[nx][ny]!=0 && !(nx==x2&&ny==y2)) continue;
            if (vis[nx][ny][d][nt]) continue;
            vis[nx][ny][d][nt] = true;
            q.push({nx,ny,d,nt});
        }
    }
    return false;
}

3. 主迴圈:掃描全盤尋找可消除配對並模擬點擊

void CZg1Dlg::OnAutoPlay()
{
    for (int y1 = 0; y1 < 11; ++y1)
        for (int x1 = 0; x1 < 19; ++x1)
            if (map[x1][y1])
                for (int y2 = 0; y2 < 11; ++y2)
                    for (int x2 = 0; x2 < 19; ++x2)
                        if (map[x2][y2] && CanLink(x1,y1,x2,y2))
                        {
                            ClickCell(x1, y1);
                            ClickCell(x2, y2);
                            map[x1][y1] = map[x2][y2] = 0; // 更新邏輯地圖
                            goto NEXT_ROUND; // 重新掃描
                        }
    return;
NEXT_ROUND:
    OnAutoPlay(); // 遞迴或改用 while 迴圈
}

void ClickCell(int cx, int cy)
{
    // 格子中心螢幕座標
    int sx = gameRect.left + 10 + cx*31 + 15;
    int sy = gameRect.top  + 180 + cy*35 + 17;
    SetCursorPos(sx, sy);
    mouse_event(MOUSEEVENTF_LEFTDOWN, 0,0,0,0);
    Sleep(30);
    mouse_event(MOUSEEVENTF_LEFTUP, 0,0,0,0);
    Sleep(50);
}

三、已知限制與改進方向

  • 雙擊延遲:遊戲需真實滑鼠點擊觸發選取狀態,`mouse_event` 合成訊息可能被攔截,需改用 `SendInput` 或鍵盤鉤子注入。
  • 畫面遮擋/解析度變動:採用相對座標與特徵點比對,若視窗移動需即時校準。
  • 演算法效能:19×11 棋盤 BFS 極快,若擴大棋盤可加入啟發式剪枝。
  • 反外掛:現代遊戲多有保護機制,僅供教學研究使用。

四、結語

本文從像素級色彩辨識、邏輯建模、圖論尋路到輸入模擬,完整展示了遊戲外掛的核心技術棧。雖然針對特定版本 QQ 連連看,但方法論可移植至任意同類型連連看遊戲。開發過程中深入體會了影像處理、演算法設計與系統程式設計的交叉應用,極具教學價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved