数据我们已经获取到了,接下来没有什么能阻止我们实现外挂了~
我们先在我们的游戏中,定义一个[11][19]的byte类型数组用以存储数据
bytem_szGameData[11][19];
然后再写一个ReadGameData()函数用以读取数据
boolCKyodaiPluginDlg::ReadGameData()
{
HWNDhGameWnd=GetGameHwnd();
ZeroMemory(m_szGameData,11*19);
if(!hGameWnd)
{
returnfalse;
}
DWORDdwPid=false;
GetWindowThreadProcessId(hGameWnd,dwPid);
HANDLEhGameProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPid);
if(!hGameProcess)
{
MessageBox(L”打开进程失败”);
returnfalse;
}
if(!ReadProcessMemory(hGameProcess,(LPVOID)0x00199F68,m_szGameData,sizeof(m_szGameData),NULL))
{
returnfalse;
}
}
接下来就是要怎么消除的问题了,如下图,是否可以消除无非就是三种情况,两个在同一条线上,这也就一条线可以消除,要要门就是2条线段可以消除,最多只能有3条线


我们要判断x1,y1x2,y能否消除我们要先构建2个点x3y3,x4y4如果x1y1能到达x3y3(也就是说他们直接的数据都是0)并且x3y3能到达x4y4并且x2y2能到达x4y4则可以消除

//判断两个点之间是不是连通的
boolCLLK_WGDlg::LineIsNull(intnRow,intnCol,intnRow2,intnCol2)
{
if(nRow2==nRownCol2!=nCol)
{
intnColMax=max(nCol2,nCol);
intnColMin=min(nCol2,nCol);
for(inty=nColMin;y=nColMax;y++)
{
if(m_szGameData[nRow][y]!=0)
{
returnfalse;
}
}
returntrue;
}
elseif(nCol==nCol2nRow!=nRow2)
{
intnRowMin=min(nRow,nRow2);
intnRowMax=max(nRow,nRow2);
for(intx=nRowMin;x=nRowMax;x++)
{
if(m_szGameData[x][nCol]!=0)
{
returnfalse;
}
}
returntrue;
}
elseif(nRow2==nRownCol2==nCol)//2点为同一点的情况
{
returntrue;
}
else
{
returnfalse;
}
returntrue;
}
boolCLLK_WGDlg::IsClear(intnRow,intnCol,intnRow2,intnCol2)
{
//先把两个点的数据拿出来
bytedata1=m_szGameData[nRow][nCol];
bytedata2=m_szGameData[nRow2][nCol2];
//把两个点的数据置0是为了两个贴在一起的能消除
m_szGameData[nRow][nCol]=0;
m_szGameData[nRow2][nCol2]=0;
intnTmpRow1=nRow;
intnTmpRow2=nRow2;
for(intnTmpCol=0;nTmpCol19;nTmpCol++)
{
if(LineIsNull(nTmpRow1,nTmpCol,nTmpRow2,nTmpCol)LineIsNull(nTmpRow1,nTmpCol,nRow,nCol)LineIsNull(nTmpRow2,nTmpCol,nRow2,nCol2))
{
m_szGameData[nRow][nCol]=data1;
m_szGameData[nRow2][nCol2]=data2;
returntrue;
}
}
intnTmpCol1=nCol;
intnTmpCol2=nCol2;
for(intnTmpRow=0;nTmpRow11;nTmpRow++)
{
if(LineIsNull(nTmpRow,nTmpCol1,nTmpRow,nTmpCol2)LineIsNull(nTmpRow,nTmpCol1,nRow,nCol)LineIsNull(nTmpRow,nTmpCol2,nRow2,nCol2))
{
m_szGameData[nRow][nCol]=data1;
m_szGameData[nRow2][nCol2]=data2;
returntrue;
}
}
m_szGameData[nRow][nCol]=data1;
m_szGameData[nRow2][nCol2]=data2;
returnfalse;
}
我们再添加一个函数ClearOne用于消除一对
voidCKyodaiPluginDlg::ClearOne()
{
ReadGameData();
for(intnRow=0;nRow11;nRow++)
{
for(intnCol=0;nCol19;nCol++)
{
if(m_szGameData[nRow][nCol]==0)
{
continue;
}
for(intnRow2=0;nRow211;nRow2++)
{
for(intnCol2=0;nCol219;nCol2++)
{
if((nRow2!=nRow||nCol2!=nCol)m_szGameData[nRow][nCol]==m_szGameData[nRow2][nCol2]IsClear(nRow,nCol,nRow2,nCol2))
{
SelectChess(nRow,nCol);
SelectChess(nRow2,nCol2);
return;
}
}
}
}
}
}
clearOne中如果判断可以消除则调用SelectChess
可以消的算法有了,我们双击单消按钮,然后添加代码如下
voidCKyodaiPluginDlg::SelectChess(intnRow,intnCol)
{
HWNDhGameWnd=GetGameHwnd();
if(hGameWnd)
{
intnPosXBase=5;
intnPosYBase=165;
intxPos=(nCol+1)*30+nPosXBase;
intyPos=(nRow+1)*35+nPosYBase;
::PostMessage(hGameWnd,WM_LBUTTONDOWN,0,MAKELPARAM(xPos,yPos));
::PostMessage(hGameWnd,WM_LBUTTONUP,0,MAKELPARAM(xPos,yPos));
}
}
上面代码中5,165是第一个图片的位置,30,35是每一格图片的大小
接着,我们在按钮消除一对的响应函数中增加如下调用一下ClearOne
//消除一对
voidCKyodaiPluginDlg::OnBnClickedBtnremove()
{
ClearOne();
}
QQ连连看写辅助系列每篇都有源代码,若想获取源代码请私信我。