"扫雷外挂" 之C++ 程序篇
来源:互联网 发布:微信html5制作软件 编辑:程序博客网 时间:2024/06/05 20:18
上篇《 “扫雷外挂” 之 理论篇》只讲了理论,我这次来看下C++的实现。
0.扫雷外挂效果图
1.分析扫雷图像
下面的代码可以得到一个点的颜色,核心代码是GetPixel。
typedef struct _Color3B{BYTE r;BYTE g;BYTE b;} Color3B;static Color3B getColorByPosition( int x, int y,HWND hWnd){HDC windowDC;RECT winRECT; // 游戏窗口的RECTPOINT po; // 位置// 获取游戏场景windowDC = GetDC(hWnd);assert( windowDC );// 获得游戏窗口的RECTGetClientRect( hWnd, &winRECT );po.x = winRECT.left + x;po.y = winRECT.top + y;COLORREF retColor = GetPixel( windowDC, po.x, po.y );BYTE red = GetRValue(retColor);//get red;BYTE green = GetGValue(retColor);//get greenBYTE blue = GetBValue(retColor);//get blue// 释放场景ReleaseDC( hWnd, windowDC );Color3B resultColor={red, green, blue};return resultColor;}
2.模拟鼠标操作
其实鼠标操作我知道的有两种,一种是下面写的这种
void CMineHelperDlg::AILClick(vector<Cell*>& vecCells){int kX, kY;::SetFocus(g_WindowHWnd);for(int i = 0; i < vecCells.size(); ++i){kX = vecCells[i]->getX() * CELL_WIDTH + GAME_LEFT + CELL_WIDTH / 2;kY = vecCells[i]->getY() * CELL_HEIGHT + GAME_TOP + CELL_HEIGHT / 2;::PostMessage( g_WindowHWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(kX, kY) );::PostMessage( g_WindowHWnd, WM_LBUTTONUP, 0, MAKELPARAM(kX, kY) );}}
还有种是:
SetCursorPos( 47,729);mouse_event( MOUSEEVENTF_LEFTDOWN, 0,0,0,NULL);//鼠标down事件mouse_event( MOUSEEVENTF_LEFTUP, 0,0,0,NULL);//鼠标up事件
3.扫雷外挂流程分析
看起来比较复杂的流程,我本来用while的,比较难搞,最后用了Goto,流程就变得非常清晰。还弄了一个struct做为标志传进去分析,看分析是什么结果,决定goto到哪个步骤。
typedef struct _ChangeFlag{bool MineChangeFlag ;bool HaveClickResultFlag ;bool HaveNewCombinationFlag ;_ChangeFlag():MineChangeFlag(false),HaveClickResultFlag(false),HaveNewCombinationFlag(false){}void Clear(){MineChangeFlag = HaveClickResultFlag = HaveNewCombinationFlag = false;}}ChangeFlag;
4.分析扫雷游戏
来讲下最难的部分:就是上图中的进行组合分析。
a + b = 1
a + b + c = 1
要得出c = 0我用一个类叫CellCombination来表示一个子项,它有N多个格子的坐标组成。还有一个Int来存总的雷数。我还记录了是哪个格子产生的子项。
class CellCombination{public:CellCombination(int mineCount,pair<int,int> pCell):totalMineCount(mineCount),parentCell(pCell){}CellCombination(){}void addCell(int x, int y);int getSize()const;int getTotalMineCount()const;void setTotalMineCount(int mineCount);pair<int,int> getParentCell()const;bool isNearMe(CellCombination& other);vector<pair<int,int> >& getVecCells();private:vector<pair<int,int> > vecCells;int totalMineCount;pair<int,int> parentCell;};
当我们分析一个格子周围8个格子的情况时候,如果发现有多解的情况下,就产生一个子项。然后通过两两子项相减,来确定一些格子的状态。
a + b = 1
a + b + c = 1
c + d + e = 2
f + g + h = 1
如何通过两两相减呢?比如一共产生了上面4个子项。就是4个里面选2个进行操作。就是一个组合算法。可以用我上次写的算法组合算法 C++高效实现 (二进制辅助法)。如果一共有10个子项,一共有10 * 9 / 2 即45次比较。如果一共有20个子项,一共有20 * 19 / 2 即190次比较。算法效率也不是特别高。
经过实战分析后,我发现扫雷中会有很多格子数量是2的子项,比如a + b = 1,但是两个这样的子项是不会产生结果的。 所以我先对所有子项进行排序,从尾部开始往前移动,移到数量是2的就退出了。另外一个来指向当前前一个,直到第一个。
vector<Cell*> MainAnalysis::analysisCombinations(ChangeFlag& changeFlag){vector<Cell*> resultClickCells;sort(totalCombination.begin(), totalCombination.end(), compareCombo);for(int i = totalCombination.size() - 1; i >=1; --i){if(totalCombination[i].getSize() > 2){for(int j = i - 1; j >= 0; --j){resultClickCells = doSubThing(i,j, changeFlag);if(resultClickCells.size() > 0){return resultClickCells;}}}else{break;}}return resultClickCells;}
如何进行两个子项相减呢?先把教长的子项拷贝一份,然后循环短的子项中的每一个点,每找到一个结果就从长的子项的vector中删除一个。进行两个子项相减的程序就不列出来了,也做了很多优化,如果两个子项的长度是一样的,就直接退出,不会有结果的,还有如果两个子项的ParentCell距离比较远,可肯定不会有结果。如果有一个找不到就退出,也是不会有结果的。
扫雷外挂代码下载:vs2010 + MFC
http://www.waitingfy.com/archives/1077/minehelper-3
参考:
扫雷外挂
http://www.cnblogs.com/xiangism/archive/2012/10/27/2665130.html
如果你觉得还不错,请顶下我的文章,谢谢!
- "扫雷外挂" 之C++ 程序篇
- C/C++之win98扫雷外挂基础篇
- 扫雷外挂程序开发
- "扫雷外挂" 原理篇
- QT| C/C++之win98扫雷外挂增强版
- Delphi外挂辅助技术入门篇、Windows扫雷程序示例
- 扫雷外挂
- 扫雷外挂
- C语言扫雷程序
- c语言扫雷程序
- 【我的程序】Minekiller——扫雷外挂
- c语言小程序之扫雷简单实现
- C语言扫雷控制台程序
- C语言实现扫雷程序
- 扫雷山寨外挂
- 扫雷外挂制作
- C语言外挂小程序
- 【扫雷】C语言编写的小程序扫雷
- android 编译之后的文件系统和内核
- JavaScript基础篇--Undefined与Null
- 猜年龄 - 蓝桥杯
- <%@ include file=""%>,<jsp:include page=""/>
- 一切成功源于积累——20140405 美国非农5分钟k线直至收盘 各货币对表现
- "扫雷外挂" 之C++ 程序篇
- 哈密尔顿回路 C++
- 切面条 - 蓝桥杯
- CImage实现图片缩放
- block的概念及简单用法,通俗易懂
- POJ - 1990 MooFest
- AOV网络与拓扑(一)
- 冒泡排序的三种实现
- Python学习笔记