本帖最后由 YiZheng 于 2020-2-19 20:46 编辑
今天来讲讲怎么用程序算法找出相同的棋子,首先咱们今天的目标就是读取内存数据,然后分析内存,利用算法找出相同的棋子
简单说如果想消除一对棋子,咱们得先找出相同的棋子;
昨天的那张棋盘的内存截图可能会有人看不懂,我先解读解读;
先上两张图片;
第二天界面截图.PNG (97.55 KB, 下载次数: 2)
2020-2-18 19:03 上传
第二天内存截图.PNG (26.72 KB, 下载次数: 3)
2020-2-18 18:51 上传
可以发现整个棋盘的布局是有点反人类的;
我为了方便你们看,做了手脚;
观察游戏界面第一排和最后一排,再观察内存区域红线部分;
发现游戏中的一排在内存中是以一列存储的,也就是【游戏】一排==【内存】一列,【游戏】一列==【内存】一排;
;
第一步:读取数据到数组
//棋盘数据
char chessData[9][14];
void GetChessData()
{
///棋盘基地址
DWORD baseAddress = 0x0019FA04;
//取得窗口句柄
HWND gameHWND = FindWindowA(NULL, "连连看");
//通过窗口句柄-》取得窗口进程ID
DWORD processID; ::GetWindowThreadProcessId(gameHWND, &processID);
//通过进程ID-》获得进程句柄
HANDLE processOpen = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
//临时变量,存放棋子
char tmp[1];
//定义缓冲区
LPVOID pBuffer = (LPVOID)&tmp;
for (int i = 1; i < 13; i++)//读取列
{
for (int j = 1; j < 8; j++)//读取行
{
//定义棋盘基地址指针
LPCVOID pBase = (LPCVOID)baseAddress;
//读取棋盘数据
ReadProcessMemory(processOpen, pBase, pBuffer, 1, NULL);
//写入数据到数组
chessData[j][i] = *tmp;
//绕过两个数据之间的3个00
baseAddress += 0x4;
}
//绕过一行数据后的00和FF
baseAddress += 0x1C;
}
}
最后读取出来的数据是这个样子;
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 8 8 8 8 8 8 8 8 8 8 8 8 0
0 8 b 13 a c 11 b d 13 d e 11 0
0 f 10 9 14 e 2 15 12 12 4 3 3 0
0 7 a 6 8 15 4 b 9 9 1 11 c 0
0 e 3 7 f 6 a 10 7 13 f 2 2 0
0 12 d 4 15 e f 1 10 1 5 14 11 0
0 11 11 11 11 11 11 11 11 11 11 11 11 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
完美!一个一个空格敲的我眼睛酸,后面没敲了,所以比较乱,别介意;
为什么我写数据到数组的时候要从一开始,就是为了周围有一圈零,这个后面会用到;
还有就是每次写入一个数据,地址都要加上一个4,以正确的读取后面的数据,每读取一行也要加一个1C,十进制就是28,如果你不这样做,你就等着叫爸爸:
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 8 8 8 8 8 8 8 8 8 8 8 8 0
0 8 8 8 8 8 8 8 8 8 8 8 8 0
0 8 8 8 8 8 8 8 8 8 8 8 8 0
0 8 8 8 8 8 8 8 8 8 8 8 8 0
0 8 8 8 8 8 8 8 8 8 8 8 8 0
0 8 8 8 8 8 8 8 8 8 8 8 8 0
0 8 8 8 8 8 8 8 8 8 8 8 8 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
不加就是读出一群8来
第二步:实现找出相同一对的算法;
bool FindPair()
{
int firstPiece_x; int firstPiece_y;//第一颗棋子
int cecondPiece_x; int cecondPiece_y;//第二颗棋子
for (firstPiece_x = 1; firstPiece_x < 13; firstPiece_x++)
{
for (firstPiece_y = 1; firstPiece_y < 8; firstPiece_y++)//外面两层,是第一颗棋子的XY坐标
{
for (cecondPiece_x = firstPiece_x; cecondPiece_x < 13; cecondPiece_x++)
{
for (cecondPiece_y = firstPiece_y; cecondPiece_y < 8; cecondPiece_y++)//里面两层,是第二颗棋子的XY坐标
{
//如果两个棋子的值相等,并且两个棋子值不等于零(未被消除),并且第一颗棋子与第二颗棋子不在同一个位置(自己不等于自己)
if ((chessData[firstPiece_y][firstPiece_x] == chessData[cecondPiece_y][cecondPiece_x])
&& (chessData[firstPiece_y][firstPiece_x] != 0 || chessData[cecondPiece_y][cecondPiece_x] != 0)
&& !(firstPiece_x == cecondPiece_x && firstPiece_y == cecondPiece_y))
{
//找到了返回真,这里会写一个算法判断两个棋子是否能消除。。。。。
return true;
}
}
}
}
}
}
找棋子的话也是从数组的1下标开始,周围的零没必要也去找一遍;
好了结束!大家有建议欢迎提出来;
第一篇传送门 :分析游戏
第三篇传送门:算法设计