发一个C#QQ连连看外挂(内存版)源代码现在游戏的基址已经改变了大家只要重新查找一下基址就直接可以用了里面用了最经典的寻路算法(比递归算法快100倍+)Main.csC# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace llk_wg {
class Main {
//游戏窗口标题
const string GAME_CAPTION = "QQ游戏 - 连连看角色版";
//棋盘基址
static IntPtr GAME_BASE = (IntPtr)0x0012A47C;
//声明一个棋盘数组
static byte[,] boxs = new byte[11, 19];
//游戏窗口句柄
static IntPtr hwnd;
//初始化棋盘数组
static void InitBox() {
//获取游戏句柄
hwnd = Win32.FindWindow(null, GAME_CAPTION);
//获取棋盘数组的内存基址
IntPtr lpBufferbase = Marshal.UnsafeAddrOfPinnedArrayElement(boxs, 0);
//获取pid
int ProcessId;
Win32.GetWindowThreadProcessId(hwnd, out ProcessId);
//打开游戏线程
IntPtr hObject = Win32.OpenProcess(Win32.STANDARD_RIGHTS_REQUIRED | Win32.SYNCHRONIZE | 4095, false, ProcessId);
//读取棋盘数据
Win32.ReadProcessMemory(hObject, GAME_BASE, lpBufferbase, boxs.Length, IntPtr.Zero);
//关闭线程
Win32.CloseHandle(hObject);
}
//发送鼠标消息(顺便把图片的高度宽度也算进去)
static void SendMouseclick(int x, int y) {
//获取游戏句柄
hwnd = Win32.FindWindow(null, GAME_CAPTION);
//lparam的高位就是y坐标低位就是x坐标y左移16就到高位去了
int lparam = (y << 16) + x;
Win32.PostMessage(hwnd, Win32.WM_LBUTTONDOWN, 0, lparam);
Win32.PostMessage(hwnd, Win32.WM_LBUTTONUP, 0, lparam);
}
//消除1对图片(模拟2次鼠标单击)
static void ClickTwo(int x1, int y1, int x2, int y2) {
SendMouseclick(22 + x1 * 31, 194 + y1 * 35);
SendMouseclick(22 + x2 * 31, 194 + y2 * 35);
}
//游戏开局
public static void Start(int type) {
int x = type == 1 ? 660 : 760;
SendMouseclick(x, 570);
}
//找相同的图片(本工具的核心)
static bool Select(int x1, int y1, int x2, int y2) {
if (x1 == x2 && y1 + 1 == y2) return true;
if (y1 == y2 && x1 + 1 == x2) return true;
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
List<int> list3 = new List<int>();
bool flag;
list1.Add(x1);
for (int i = x1 - 1; i >= 0; i--) if (boxs[i, y1] == 0) list1.Add(i); else break;
for (int i = x1 + 1; i < 11; i++) if (boxs[i, y1] == 0) list1.Add(i); else break;
list2.Add(x2);
for (int i = x2 - 1; i >= 0; i--) if (boxs[i, y2] == 0) list2.Add(i); else break;
for (int i = x2 + 1; i < 11; i++) if (boxs[i, y2] == 0) list2.Add(i); else break;
list3 = list1.Intersect(list2).ToList();
for (int i = 0; i < list3.Count(); i++) {
flag = true;
for (int j = Math.Min(y1, y2) + 1; j < Math.Max(y1, y2); j++) { if (boxs[list3[i], j] != 0) { flag = false; break; } }
if (flag) return true;
}
list1.Clear(); list2.Clear(); list3.Clear();
list1.Add(y1);
for (int i = y1 - 1; i >= 0; i--) if (boxs[x1, i] == 0) list1.Add(i); else break;
for (int i = y1 + 1; i < 19; i++) if (boxs[x1, i] == 0) list1.Add(i); else break;
list2.Add(y2);
for (int i = y2 - 1; i >= 0; i--) if (boxs[x2, i] == 0) list2.Add(i); else break;
for (int i = y2 + 1; i < 19; i++) if (boxs[x2, i] == 0) list2.Add(i); else break;
list3 = list1.Intersect(list2).ToList();
for (int i = 0; i < list3.Count(); i++) {
flag = true;
for (int j = Math.Min(x1, x2) + 1; j < Math.Max(x1, x2); j++) { if (boxs[j, list3[i]] != 0) { flag = false; break; } }
if (flag) return true;
}
return false;
}
//消除一对
public static void RemoveSingle() {
InitBox();
for (int x1 = 0; x1 < 11; x1++) {
for (int y1 = 0; y1 < 19; y1++) {
for (int x2 = 0; x2 < 11; x2++) {
for (int y2 = 0; y2 < 19; y2++) {
if (boxs[x1, y1] != 0 && boxs[x1, y1] == boxs[x2, y2] && !(x1 == x2 && y1 == y2)) {
if (Select(x1, y1, x2, y2)) {
ClickTwo(y1, x1, y2, x2);
return;
}
}
}
}
}
}
}
//消除所有
public static void RemoveAll() {
InitBox();
Target:
for (int x1 = 0; x1 < 11; x1++) {
for (int y1 = 0; y1 < 19; y1++) {
for (int x2 = 0; x2 < 11; x2++) {
for (int y2 = 0; y2 < 19; y2++) {
if (boxs[x1, y1] != 0 && boxs[x1, y1] == boxs[x2, y2] && !(x1 == x2 && y1 == y2)) {
if (Select(x1, y1, x2, y2)) {
ClickTwo(y1, x1, y2, x2);
boxs[x1, y1] = 0;
boxs[x2, y2] = 0;
goto Target;
}
}
}
}
}
}
}
//获取其他玩家最小box数量值
public static byte GetOtherUserMinNum() {
byte value = 0;
byte[] buffer = new byte[20];
int lpBase = 0x0012E04C;// 0x00115CDC;//0012E04C
//获取游戏句柄
hwnd = Win32.FindWindow(null, GAME_CAPTION);
//获取棋盘数组的内存基址
IntPtr lpBufferbase = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
//获取pid
int ProcessId;
Win32.GetWindowThreadProcessId(hwnd, out ProcessId);
//打开游戏线程
IntPtr hObject = Win32.OpenProcess(Win32.STANDARD_RIGHTS_REQUIRED | Win32.SYNCHRONIZE | 4095, false, ProcessId);
//读取棋盘数据
Win32.ReadProcessMemory(hObject, (IntPtr)lpBase, lpBufferbase, buffer.Length, IntPtr.Zero);
//关闭线程
Win32.CloseHandle(hObject);
try { value = buffer.Where(o => o != 0).Min(); } catch { }
return value;
}
//获取自己的图片数量
public static byte GetShengyuNum() {
byte[] buffer = new byte[4];
//0012E048,00115CD8
int lpBase = 0x0012E048;// 0x00115CDC;//0012E04C
//获取游戏句柄
hwnd = Win32.FindWindow(null, GAME_CAPTION);
//获取棋盘数组的内存基址
IntPtr lpBufferbase = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
//获取pid
int ProcessId;
Win32.GetWindowThreadProcessId(hwnd, out ProcessId);
//打开游戏线程
IntPtr hObject = Win32.OpenProcess(Win32.STANDARD_RIGHTS_REQUIRED | Win32.SYNCHRONIZE | 4095, false, ProcessId);
//读取棋盘数据
Win32.ReadProcessMemory(hObject, (IntPtr)lpBase, lpBufferbase, buffer.Length, IntPtr.Zero);
//关闭线程
Win32.CloseHandle(hObject);
return Marshal.ReadByte(lpBufferbase);
}
}
}
Win32.csC# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace llk_wg
{
///
/// win32API函数声明
///
class Win32
{
[DllImport("user32.dll", EntryPoint = "FindWindowA")]
public static extern IntPtr FindWindow( string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "PostMessageA")]
public static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
public static extern int GetWindowThreadProcessId( IntPtr hWnd, out int lpdwProcessId);
[DllImport("kernel32.dll", EntryPoint = "OpenProcess")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", EntryPoint = "CloseHandle")]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, IntPtr lpNumberOfBytesRead);
public const int WM_LBUTTONDOWN = 513;
public const int WM_LBUTTONUP = 514;
public const int STANDARD_RIGHTS_REQUIRED = 983040;
public const int SYNCHRONIZE = 1048576;
}
}
Program.csC# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace llk_wg
{
static class Program
{
///
/// 应用程序的主入口点。
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form1.csC# code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace llk_wg
{
public partial class Form1 : Form
{
bool flag = false;
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
Main.Start(1);
}
private void btnLianxi_Click(object sender, EventArgs e)
{
Main.Start(2);
}
private void btnSingle_Click(object sender, EventArgs e)
{
Main.RemoveSingle();
}
private void btnAll_Click(object sender, EventArgs e)
{
Main.RemoveAll();
}
private void btnAuto_Click(object sender, EventArgs e)
{
flag = !flag;
if (flag)
{
this.btnAuto.Text = "停止挂机";
this.timer1.Start();
}
else
{
this.btnAuto.Text = "挂机";
this.timer1.Stop();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
this.timer1.Interval = 100;
int otherMin = Main.GetOtherUserMinNum();
int selfMin = Main.GetShengyuNum();
if (otherMin - 2 <= selfMin) Main.RemoveSingle();
if (selfMin == 0) Main.Start(1);
}
}
}