发一个C#QQ连连看外挂(内存版)源代码
现在游戏的基址已经改变了大家只要重新查找一下基址就直接可以用了
里面用了最经典的寻路算法(比递归算法快100倍+)
Main.csusing 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);
}
}
}
现在游戏的基址已经改变了大家只要重新查找一下基址就直接可以用了
里面用了最经典的寻路算法(比递归算法快100倍+)
Main.csusing 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);
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;namespace llk_wg
{
/// <summary>
/// win32API函数声明
/// </summary>
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; }
}
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;namespace llk_wg
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
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);
}
}
}
look下!~
不过支持下
求段示例性代码的帖子,如何获得游戏发来的数据,又如何发过去
另外,连连看的AI算法感觉好高端,纯搜索估计要超时,会让用户蛋碎本人学C#1年(大二,编程课只开了C语言),算法略通(好吧ACM的水题,擅长搜索题 汗!——)
高级的搜索算法只接触过五子棋的AI,好吧,极大极小搜索,那算不上算法,αβ剪枝,略有点意思,但也不高端
技术方面,接触过socket,asp.net略知一二(好吧,这没关系)
差不多看的陈广->传智播客的视频被英语折磨1年了(估计这次6级挂了,但不想学了)谁能指条明路