今年最后一天上班,闲的无聊,研究了下扫雷,瞬间把我手动记录181秒提高到1秒
// Winmine.h: interface for the CWinmine class.
//
//
#if !defined(AFX_WINMINE_H__A4A77AE4_C744_4838_B6F9_BB4B52188135__INCLUDED_)
#define AFX_WINMINE_H__A4A77AE4_C744_4838_B6F9_BB4B52188135__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CWinmine
{
public:
CWinmine();
virtual ~CWinmine();
public:
BOOL FindWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName
);
void SetSleepTime(DWORD dwMilSeconds);
void IsWithMouseMove(BOOL bWith);
void AutoDetect();
BOOL Init();
private:
LONG m_lWidthAddress; //雷区宽度数据保存地址
LONG m_lHeightAddress; //雷区高度数据保存地址
LONG m_lMinesAddress; //雷的数目数据保存地址
LONG m_lCellBaseAddress; //雷的布局数据起始地址
SHORT m_Width;
SHORT m_height;
SHORT m_Mines;
LONG m_CellBase;
POINTS m_basePoint; //首个单位雷区中心坐标
HWND m_hwndMine; //扫雷窗体句柄
HANDLE m_hProcessMine;
DWORD m_dwMilSeconds;
BOOL m_WithMouseMove; //是否需要鼠标跟随
};
#endif // !defined(AFX_WINMINE_H__A4A77AE4_C744_4838_B6F9_BB4B52188135__INCLUDED_)
// Winmine.cpp: implementation of the CWinmine class.
//
//
#include "stdafx.h"
#include "AutoMineDetect.h"
#include "Winmine.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
CWinmine::CWinmine()
{
m_lWidthAddress = 0x1005334; //雷区宽度数据地址
m_lHeightAddress = 0x1005338;
m_lMinesAddress = 0x1005330;
m_lCellBaseAddress = 0x1005340;
m_basePoint.x = 11 + 8;
m_basePoint.y = 54 + 8;
m_dwMilSeconds = 0;
m_WithMouseMove = FALSE;
}
CWinmine::~CWinmine()
{
CloseHandle(m_hwndMine);
m_hwndMine = NULL;
}
BOOL CWinmine::FindWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName )
{
BOOL bRet = FALSE;
m_hwndMine = ::FindWindow(lpClassName, lpWindowName);
if (m_hwndMine)
{
DWORD dwPID;
DWORD dwRet = ::GetWindowThreadProcessId(m_hwndMine,&dwPID);
m_hProcessMine = ::OpenProcess(PROCESS_ALL_ACCESS
|PROCESS_VM_OPERATION
|PROCESS_VM_READ
|PROCESS_VM_WRITE,
0,
dwPID);
bRet = TRUE;
}
return bRet;
}
void CWinmine::AutoDetect()
{
if ((NULL !=m_hwndMine) && SetForegroundWindow(m_hwndMine))
{
Init();
POINTS stpnt;
LONG lCellAddress = m_lCellBaseAddress;
DWORD nCellBase=0;
//点击初始化按钮(未完成)
stpnt.x = m_basePoint.x;
stpnt.y = m_basePoint.y;
for (int ny = 0; ny < m_height; ny++)
{
for (int nx = 0; nx < m_Width; nx++)
{
lCellAddress =m_lCellBaseAddress + 32*(ny+1) + (nx+1); //初级,中级,高级内存存储数据块位置一样,每行均占32字节
DWORD dwBytesRead;
BOOL bRet = ::ReadProcessMemory(m_hProcessMine,
(LPVOID)lCellAddress,
&nCellBase,
1,
&dwBytesRead
);
if (nCellBase != 0x8f)
{
if (m_WithMouseMove)
{
POINT stpntTemp;
stpntTemp.x = stpnt.x;
stpntTemp.y = stpnt.y;
ClientToScreen(m_hwndMine,&stpntTemp);
SetCursorPos(stpntTemp.x,stpntTemp.y);
printf("%d, (%d,%d) ",nCellBase,stpnt.x,stpnt.y);
}
SendMessage(m_hwndMine,WM_LBUTTONDOWN,MK_LBUTTON, *((DWORD *)&stpnt));
SendMessage(m_hwndMine,WM_LBUTTONUP,MK_LBUTTON, *((DWORD *)&stpnt));
Sleep(m_dwMilSeconds);
}
stpnt.x += 16;
}
stpnt.x = m_basePoint.x;
stpnt.y += 16;
printf("/n");
}
stpnt.y = m_basePoint.y;
}
}
BOOL CWinmine::Init()
{
BOOL bRet = FALSE;
DWORD dwBytesRead;
//读取雷区宽度数据
bRet = ::ReadProcessMemory(m_hProcessMine,
(LPVOID)m_lWidthAddress,
&m_Width,
4,
&dwBytesRead
);
//读取雷区高度数据
bRet = ::ReadProcessMemory(m_hProcessMine,
(LPVOID)m_lHeightAddress,
&m_height,
4,
&dwBytesRead
);
//读取总雷数
bRet = ::ReadProcessMemory(m_hProcessMine,
(LPVOID)m_lMinesAddress,
&m_Mines,
4,
&dwBytesRead
);
bRet = ::ReadProcessMemory(m_hProcessMine,
(LPVOID)m_lCellBaseAddress,
&m_CellBase,
4,
&dwBytesRead
);
return bRet;
}
void CWinmine::SetSleepTime( DWORD dwMilSeconds )
{
m_dwMilSeconds = dwMilSeconds;
}
void CWinmine::IsWithMouseMove( BOOL bWith )
{
m_WithMouseMove = bWith;
}
简单测试程序:
void CAutoMineDetectDlg::OnOK()
{
// TODO: Add extra validation here
CWinmine objMine;
DWORD dwSeconds=0;
CString strTitle = _T("扫雷");
dwSeconds = GetDlgItemInt(IDC_SECONDS);
m_btnCheck.GetCheck();
if (objMine.FindWindow((LPCTSTR)strTitle, NULL))
{
if (0!=m_btnCheck.GetCheck())
{
objMine.IsWithMouseMove(TRUE);
}
objMine.SetSleepTime(dwSeconds);
objMine.AutoDetect();
}
else
{
MessageBox(_T("请先打开扫雷程序"));
}
// CDialog::OnOK();
}