# QQLineBlock **Repository Path**: SnailcatMall/QQLineBlock ## Basic Information - **Project Name**: QQLineBlock - **Description**: QQ连连看自动消除块算法练习 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2023-06-16 - **Last Updated**: 2026-10-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: 自动消块, QQ连连看, QQ连连看自动消块 ## README # TXQQGame — QQ连连看自动消除 针对 QQ游戏「连连看」(角色版 / 翻新版)的自动消除工具:自动识别棋盘、算出可连通的对子并按序点击消除。 项目包含两套互不相干的实现,按游戏版本二选一使用: | 实现 | 入口类 | 目标进程 | 棋盘来源 | 适用版本 | |---|---|---|---|---| | **内存版** | `org.example.App` | `kyodaiRPG.exe` | 直接读进程内存 | QQ连连看 角色版 | | **截图识别版** | `org.example.newApp` | `LLKNew.exe` | 屏幕截图 + 图像识别 | QQ连连看 翻新版(Unity) | --- ## 功能特性 - **自动识别棋盘**:截图识别版通过「粗筛 + 精判」两级匹配区分牌型(同种牌聚为一类),并自动定位棋子实时位置。 - **按牌型求解**:先把棋子按牌型归类,再对同种牌两两判连通——而不是拿每个格子对全盘暴扫。 - **完整连通判定**:支持 0 / 1 / 2 拐角,并允许连线**绕行到棋盘外**(棋盘外扩一圈空白边距)。 - **整盘一次算准**:内存模拟消除,消一对就清空两格,让后续棋子利用新空出的路径;边消边算得到严格可依次执行的消除顺序。 - **后台自动循环**:始终基于「最新棋盘」工作,点击后棋盘变化即重新识别,实时跟上棋子位置。 - **点击确认 + 空转保护**:每次点击都截图确认真正选中/消除,未确认则重试;连续多轮一对都没消掉时自动暂停,等待棋盘变化(新局/洗牌)再恢复。 - **热键控制**:`F6` 启动/终止,`F7` 终止。 --- ## 环境要求 - **Windows**(依赖 Win32 窗口消息与 GDI 截图) - **JDK 1.8**(`pom.xml` 的 `maven.compiler.source/target` 为 1.8) - **JSCM 原生库**(`com.scm.all.export.*`):负责窗口操作、热键监听、进程读写、发送点击消息 > 项目通过 IntelliJ IDEA 的库依赖(`.idea/libraries/Jscm_Core.xml`)引入 JSCM;`pom.xml` 只声明了 JUnit。建议直接在 IDEA 中运行。 ### JSCM 原生库路径 `App` / `newApp` 的静态初始化会把原生库目录注册给 JSCM,默认指向本机路径,可用系统属性覆盖: ``` -Djscm.sdk.x86=C:\path\to\x86\ -Djscm.sdk.x64=C:\path\to\x64\ ``` 初始化时会先 `System.loadLibrary("jawt")` 预加载当前 JRE 自带的 `jawt.dll`,避免 `Jscm.dll` 命中厂商附带的旧版 `jawt.dll` 而报 `UnsatisfiedLinkError`。 --- ## 快速开始 ### 截图识别版(翻新版,推荐) 1. 打开「连连看翻新版」(进程 `LLKNew.exe`)。 2. 在 IDEA 中运行主类 `org.example.newApp`。 3. 按 **`F6`** 开始自动消除(再按一次 `F6` 或按 `F7` 停止)。 启动时会把游戏窗口置顶归位一次并固定在屏幕坐标,之后每帧靠截图识别,不再抢焦点。 > 注意:识别区域是固定屏幕坐标,游戏窗口位置/分辨率改变后需重新校准 `RobotImageUtils` 中的棋盘参数。 ### 内存版(角色版) 1. 打开「QQ连连看-角色版」(进程 `kyodaiRPG.exe`,同时需 `QQGame.exe` 在运行)。 2. 运行主类 `org.example.App`。 3. 按 **`F6`** 执行一次自动消除(内部最多复核 5 遍以兜住偶发丢点击)。 该版本要求窗口位于屏幕左上角(代码会把窗口移动到 `(0,0)` 并置顶)。 --- ## 热键 | 按键 | 说明 | |---|---| | `F6` | 截图版:启动 / 终止后台自动消除(切换);内存版:执行一次消除 | | `F7` | 截图版:终止后台自动消除 | --- ## 关键参数 ### 内存版 `App.java` | 参数 | 默认值 | 说明 | |---|---|---| | `block_x` / `block_y` | 31 / 35 | 方块列间距 / 行间距 | | `left_x` / `left_y` | 9 / 180 | 棋盘相对窗口左上角偏移 | | `block_offset` | 13 | 点击到方块中心的偏移 | | `clickDelay` | 3 | 每次点击后的间隔(ms),点击走同步消息,顺序有保证 | | 棋盘基址 | `1A9F58` | 棋盘数据在进程内存中的地址(19×11 字节) | ### 截图版 `RobotImageUtils.java` | 参数 | 默认值 | 说明 | |---|---|---| | `boardX` / `boardY` | 202 / 132 | 棋盘截取区域左上角屏幕坐标 | | `blockStep` | 44 | 每格步长(行/列间距相同) | | `iconWidth` / `iconHeight` | 38 / 37 | 方块图标尺寸 | | `rows` / `cols` | 11 / 19 | 棋盘行列数 | | `sameTileMad` | 15 | 精判同类阈值(逐像素平均绝对差) | | `matchBlurRadius` | 1 | 精判用的均值模糊半径(1 表示 3×3) | | `matchShift` | 1 | 精判允许的 ±像素位移 | | `coarsePool` / `coarseMad` | 6 / 22 | 粗筛池化边长 / 阈值(只提速,不改变识别结果) | | `tileMinWhitePercent` | 5 | 判定「有牌」的最小白底占比(%) | | `selectMad` | 3 | 点击前后状态变化的判定阈值 | | `clickCheckDelay` / `clickRetryDelay` | 25 / 60 | 点击确认 / 重试等待(ms) | | `clickMaxAttempts` | 4 | 单次点击最多尝试次数 | | `checkMargin` | true | 识别余量自检开关(只读,会打印同种/异种牌距离与分离比) | --- ## 算法原理 ### 1. 图像识别(截图版) - **空格判定**:有牌的格子是白底,空格是整片蓝色背景,用白底像素占比区分。 - **两级匹配**: - **粗筛**:把每格池化成 `coarsePool × coarsePool` 的 RGB 均值特征,距离 ≥ `coarseMad` 直接判为不同种牌(毫秒级)。阈值取得比「异种牌最小距离」还大,保证真同类对不会被挡在精判之外 —— **粗筛只提速,不改变识别结果**。 - **精判**:只对粗筛留下的候选对做「均值模糊 + ±位移取最小逐像素平均绝对差(MAD)」,距离 < `sameTileMad` 判为同类。 - 实测真实切片:同种牌精判距离 ≤ 8.2、异种牌 ≥ 21.5(分离比 2.62),阈值取 15,两侧余量均 > 6。 - **点击确认**:点击前后截取同一格区域做 MAD 比对,超过 `selectMad` 才认为选中/消除;未变化则延长等待并重试。 ### 2. 连通判定(`canRemove`) - 支持 **0 拐**(直线)、**1 拐**(两个候选拐点各判一次)、**2 拐**(中间段竖直 / 水平两个方向各扫一遍,O(行+列))。 - 棋盘外扩一圈空白边距,允许连线绕行到棋盘外。 - 两拐扫描用「A / B 各自沿行(列)的连续空格可达区间」做裁剪,只扫两个区间的交集 —— 结果与全量扫描**严格等价**,但更快。 ### 3. 整盘求解(`solveBoard`) - 先把棋子按**牌型归类**,只对同种牌两两判连通。 - 每找到一对就**就地消除**(清空两格)并继续,直到再无可消。 - 贪心本身即为最优:消除只会把格子由「有牌」变「空」,永远不会堵死别的对子,只会打通新路,因此最终可消对子数与消除顺序无关。 --- ## 目录结构 ``` src/main/java/org/example/ ├── App.java # 内存版:读进程内存识别棋盘 + 连通求解 + 发送点击消息 ├── newApp.java # 截图版:后台自动循环 + 按牌型归类的连通求解 ├── RobotImageUtils.java # 截图版:截图 / 图像识别(两级匹配) / 点击并确认选中 └── AtoB.java # 一对可消除棋子的坐标与点击位置 ``` - **内存版核心**:`App.java`(`lineBlock` / `solveBoard` / `horizon` / `vertical` / `turn_once` / `turn_twice` / `can_remove`)。 - **截图版核心**:`newApp.java`(`autoLoop` / `solveBoard` / `canRemove`)+ `RobotImageUtils.java`(`getData` / `boardSignature` / `clickTile`)。 --- ## 注意事项 - 截图版所有坐标均为**固定屏幕坐标**,游戏窗口位置或分辨率变化后需重新校准。 - 内存版的棋盘基址(`1A9F58`)与偏移随游戏版本可能变化,失效时需重新定位。 - 使用前请确认已获得相关授权,本工具仅供学习与研究使用。