需要全局出击官网WG的,找我

《全民突击》外挂
扫描二维码下载手游视界
扫描二维码下载录屏大师
第三方登录
当前位置: > 视频播放
《全民突击》外挂
使用微信扫一扫
分享给微信好友或朋友圈
X 手游链接
《全民突击》是腾讯首款FPS枪战手游。全3D绚丽画面,打造电影级视觉盛宴;经典名枪、炫酷战车,构建军迷博物馆;最强佣兵团养成系统,晋升全能指挥官;闯关模式、无尽模式,再现真实战场;真人实时对战,酣畅淋漓,不再一个人寂寞打枪!快加入《全民突击》与6亿玩家共同开启枪战梦想,激爽战斗吧!
共条评论 &第页
大神玩家视频秀
热门视频排行榜
作者:迷你世界
作者:囚我终老卍
作者:玩家8930684
作者:AGN.若林
作者:刘红梅
作者:迷你世界
作者:囚我终老卍
作者:玩家8930684
作者:AGN.若林
作者:刘红梅
作者:迷你世界
作者:囚我终老卍
作者:玩家8930684
作者:AGN.若林
作者:刘红梅爆笑《绝地求生》真人版:全局出击_腾讯视频
三倍流畅播放
1080P蓝光画质
新剧提前看
1080P蓝光画质
纯净式无框播放器
三倍流畅播放
扫一扫 手机继续看
下载需先安装客户端
{clientText}
客户端特权:
3倍流畅播放
当前播放至 {time}
扫一扫 手机继续看
爆笑《绝地求生》真人版:全局出击
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要
副标题要不要visual_c++外挂教程(较详细)
&&课程分四个大章节&&
&&&&&&&&&初级篇,中级篇,进阶篇,高级篇
&&&&&&&&&初级篇内容:编写一个完整的,简单的外挂
&&&&&&&&&&&C++的数据类型:Byte,Word,DWORD,int,float
&&&&&&&&&&&API函数的调mouse_event,GetWindowRect,SetCursorPos,FindWindow,SendMessage)
&&&&&&&&&&&CE5.4工具的使用方法
&&&&&&&&&中级篇内容:调试工具的使用技巧,功能CALL的概念
&&&&&&&&&&&调试工具OD1.1的使用技巧(如硬件断点,条件断点,内存断点。
&&&&&&&&&&&常用汇编指令与对应高级语言的转换。
&&&&&&&&&&&游戏功能CALL概念
&&&&&&&&&&&找第一个功能CALL
&&&&&&&&&&外挂框架的构建(通用)
&&&&&进阶篇内容:分析游戏内部数据,分析常用功能CALL
&&&&&&&&&&游戏数据实践找各种功能CALL(如打怪,选怪,物品使用,技能栏之类)及相应的代码编写
&&&&&高级篇内容:编写完整外挂
&&&&&&&&&&&完成一个相对完整的外挂,实现&自动挂机,打怪,存放物品之类的功能
&&&&&&&&&&
&&1&入门篇.
&&&&&1.1、一个最简单的外挂
&&&&&&&&&1.1.1、游戏窗口数据分析(SPY++)&--------------------10
&&&&&&&&&&&&&&a、取得窗口相对坐标
&&&&&&&&&&&&&&b、读出游戏窗口信息GetWindowRect
&&&&&&&&&&&&&&c、移动鼠标指针SetCursorPos
&&&&&&&&&1.1.2&用VC++写个最简单的外挂(实现游戏开局)---&12&&&&&&&&&&&
&&&&&&&&&&&&&&a、鼠拟鼠标单击mouse_event
&&&&&&&&&&&&&&b、鼠标指针移动还原
&&&&&&&&&&&&&&c、集成到startgame函数里
&&&&&1.2、用CE查找棋盘数据&&&&&&------------------------14
&&&&&&&&&1.2.1、CE中的数据类型
&&&&&&&&&&&&&&a、数据类型:Bit,Byte,Word,Dword,float,double
&&&&&&&&&&&&&&b、用CE查找出坐位号;
&&&&&&&&&&&&&&c、保存分析数据
&&&&&&&&&1.2.2、编程读出坐位号;&---------------------------&15
&&&&&&&&&&&&&&a、远程读取进程数据
&&&&&&&&&&&&&&b、打开远程进程
&&&&&&&&&&&&&&c、读取远程进程数据
&&&&&&&&&1.2.3、用CE查出棋盘基址;---------------------------16
&&&&&&&&&&&&&&a、找棋盘数据基址
&&&&&&&&&&&&&&b、分析棋盘数据结构
&&&&&&&&&1.2.4、读出当前棋盘数据&--------------------------17
&&&&&&&&&&&&&&a、编程读出棋盘数据
&&&&&&&&&&&&&&b、棋盘数据显示出来&&&&&&&&
&&&&&1.3、用模拟技术编制外挂&&-------------------------------18
&&&&&&&&&&&&&&&&&&&&&1.3.1&分析棋子与棋盘坐标关系
&&&&&&&&&&&&&&&a、鼠标软件模拟,函数SendMessage
&&&&&&&&&&&&&&&b、分析窗口内棋子相对坐标X,Y&
&&&&&&&&&&&&&&&c、软件模拟点击棋盘坐标x,y处的棋子
&&&&&&&&&1.3.2&消掉一对棋子的算法框架&--------------------&20
&&&&&&&&&&&&&&&a、遍历棋盘同类型棋子配对
&&&&&&&&&&&&&&&b、构建算法框架
&&&&&&&&&1.3.3&(Check2p)大致框架(算法核心)---------------21
&&&&&&&&&&&&&&&a、在这一对棋子间找相通路径的原理
&&&&&&&&&&&&&&&b、(Check2p函数)框架代码
&&&&&&&&&&&&&&&c、(CheckLine函数)检测2点是否有连通.
&&&&&&&&&1.3.4&CheckLine实现&&23
&&&&&&&&&&&&&&&a、CheckLine函数实现
&&&&&&&&&&&&&&&b、Check2p核心代码架构
&&&&&&&&&1.3.5&Check2p完整代码实现&&&----------------------25
&&&&&&&&&&&&&&&a、完整的Ceheck2p代码解析
&&&&&&&&&&&&&&&b、完善CheckLine函数&&&&&&&&&&&&&&
&&&&&&&&&1.3.6&Click2p函数实现,单消棋子功能实现&&--------33
&&&&&&&&&&&&&&&a、完成Click2p函数
&&&&&&&&&&&&&&&b、单消一对棋子的实现
&&&&&&&&&&&&&&&c、修改ClearPair函数
&&&&&&&&&1.3.7&挂机/秒杀/----------------------------------35
&&&&&&&&&&&&&a、自动开局
&&&&&&&&&&&&&b、挂机下棋&&&&&&&&&&&&&
&&&&&&&&&1.3.8&&游戏外挂界面美化---------------------------38
&&&&&&&&&&&&&a、添加进度条
&&&&&&&&&&&&&b、界面调整
&&&&&&&&&&&&&c、Slider控件属性设置
&&&&&&&&&1.3.9&倒计时与棋子数(基址查找)--------------------40
&&&&&&&&&&&&&a、查找棋子数
&&&&&&&&&&&&&b、查找倒计时
&&&&&&&&&&&&&c、开局标志
&&&&&&&&&1.4&&编写完整外挂&--------------------------------40
&&&&&&&&&&&1.4.1&优化自动开局函数StartGame&
&&&&&&&&&&&&&a、让游戏窗口高高在上
&&&&&&&&&&&&&b、优化开局函数
&&&&&&&&&&&1.4.2&去掉游戏倒计时限制&----------------------&42
&&&&&&&&&&&&&a、找到计时代码
&&&&&&&&&&&&&b、动态修改游戏代码(OD使用初探)
&&&&&&&&&&&&&c、去掉计时限制&&&&&&&&&
&&&&&&&&&&&1.4.3&编写完整外挂&--------------------------------44
&&&&&&&&&&&&a、功能测试
&&&&&&&&&&&&b、修改完善外挂
&&&&&&&&&&&&c、读出当前棋子数
&&&&&&&&&&&&d、秒杀实现
&&&&&&&&&&&1.4.4&初级篇小结&----------------------------------46
&&&&&&&&&&&&a、游戏分析小结
&&&&&&&&&&&&b、编程小结
&&&&&&&&&&&&&&&&&&&&&&
&&2&中级篇&以XX3D游戏为例&&&
&&&&&2.1、分析前的准备..CALL简介:---------------------------49
&&&&&&&&&2.1.1、CALL的概念(远程调用CALL)
&&&&&&&&&&&&&&&&a、写个调用示例(假想游戏客户端)
&&&&&&&&&&&&&&&&b、用OD找CALL,初探(用OD找出我们自己写的CALL)
&&&&&&&&&&&&&&&&c、代码注入器,远程CALL调用
&&&&&&&&&2.1.2、远程CALL调用代码实现-------------------------51
&&&&&&&&&&&&&&&&a、CreateRemoteThread&API函数
&&&&&&&&&&&&&&&&b、无参数的远程CALL调用(代码实现)&
&&&&&&&&&2.1.3、调试工具OD简介(人物角色)血值,魔力值,坐标偏移;53
&&&&&&&&&&&&&&&&a、CE找出当前血值偏移
&&&&&&&&&&&&&&&&b、OD&分析出魔力值,坐标偏移
&&&&&&&&&&&&&&&&c、导出游戏关键代码&
&&&&&&&&&2.1.4、游戏基址概念;---------------------------------54
&&&&&&&&&&&&&&&&a、基址+偏移&概念
&&&&&&&&&&&&&&&&b、读写内存函数&参数简介
&&&&&&&&&&&&&&&&c、编程实现读出(血值,魔力值)
&&&&&&&&&2.1.5、常用汇编指令详解-------------------------56
&&&&&&&&&&&&&&&&a、Mov指令的几种形式
&&&&&&&&&&&&&&&&b、汇编指与高级语言的转换
&&&&&&&&&&&&&&&&c、push指令
&&&&&&&&&2.1.6、内联汇编编程实例-------------------------58
&&&&&&&&&&&&&&&&a、加法add
&&&&&&&&&&&&&&&&b、减法sub
&&&&&&&&&&&&&&&&c、纯汇编调用函数CALL(参数的传递)
&&&&&&&&&&&&&&&&d、堆栈平衡
&&&&&2.2、技能栏使用-游戏分析利器OD(OllyDbg)
&&&&&&&&&2.2.1、吃金创药CALL---------------------------59
&&&&&&&&&&&&&&&a、CE工具使用技巧
&&&&&&&&&&&&&&&b、OD断点F2
&&&&&&&&&&&&&&&c、分析CALL的参数
&&&&&&&&&&&&&&&d、代码注入器测试CALL
&&&&&&&&&2.2.2、编写自己的CALL测试代码61
&&&&&&&&&&&&&&&a、远程分配内存空间VirtualAllocEx
&&&&&&&&&&&&&&&b、向游戏进程注入自己代码
&&&&&&&&&&&&&&&c、远程调用《吃金创药》&&&
&&&&2.3、DLL外挂框架构建
&&&&&&&2.3.1、DLL动态链接库构建,与调用&&----------------62
&&&&&&&&&&&&a、建立MFC动态链接库dll
&&&&&&&&&&&&b、EXE程序中调用DLL函数&&&&&&&&&&&&&&
&&&&&&&2.3.2、API与回调函数64
&&&&&&&&&&&&a、键盘勾子回调函数keyProc
&&&&&&&&&&&&b、安装函数SetupFun
&&&&&&&&&&&&c、注入DLL至游戏进程空间
&&&&&&&2.3.3、DLL中构建窗口&------------------------------66
&&&&&&&&&&&&a、DLL中插入窗口资源
&&&&&&&&&&&&b、在游戏内创建DLL窗口
&&&&&&&&&&&&c、DLL内CALL代码书写(以吃红药为例)&
&&&&2.4、选怪功能实现
&&&&&&2.4.1、找怪物列表基址---------------------------------68
&&&&&&&&&&&a、选定怪ID
&&&&&&&&&&&b、怪物数组基址
&&&&&&&&&&&c、怪物数组大小
&&&&&&2.4.2、分析怪对象属性---------------------------------70
&&&&&&&&&&&a、怪对象ID
&&&&&&&&&&&b、怪与玩家距离
&&&&&&&&&&&c、怪物死亡状态
&&&&&&2.4.3、遍历怪物列表&&&&&&-----------------------------71&
&&&&&&&&&&&&&a、选怪关键代码
&&&&&&&&&&&&&b、定位一个怪对象
&&&&&&&&&&&&&c、选怪功能实现
&&&&&&&2.4.4、选怪功能优化----------------------------------73
&&&&&&&&&&&&&a、OD分析选怪功能对应代码
&&&&&&&&&&&&&b、写测试代码让选定怪物血条正确显示
&&&&&&&&&&&&&c、集成选怪函数到SelMon()
&&&&&2.5、用OD分析游戏功能CALL.《XXXXXX》为例:主要是找CALL
&&&&&&&2.5.1、普通攻击CALL关键代码分析75
&&&&&&&&&&&&&a、更新游戏选怪基址
&&&&&&&&&&&&&b、分析攻击CALL关键代码
&&&&&&&&&&&&&c、汇编指令与应高级语言对照翻译
&&&&&&&&&&&&&d、编程测试
&&&&&&&2.5.2、挂机打怪功能------------------------------------75
&&&&&&&&&&&&&1、更新选怪CALL地址
&&&&&&&&&&&&&2、优化代码结构
&&&&&&&&&&&&&3、自动选怪代码编写
&&&&&&&&&&&&&4、自动打怪代码编写
&&&&&&&&&&&&&5、代码测试
&&&&&&&2.5.3、物品背包数组基址+偏移分析(CE+OD)--------------79
&&&&&&&&&&&&&a、确定突破口
&&&&&&&&&&&&&b、回溯基址
&&&&&&&&&&&&&c、用OD验证
&&&&&&&&&&&&&d、推导出基址+偏移公式
&&&&&&2.5.4&、使用指定物品&UseGoods(int&index=0);-------------80
&&&&&&&&&&&&&&a、算法原理
&&&&&&&&&&&&&&b、返回物品在背包中的下标&int&GetGoodsIndex(char*&name);
&&&&&&&&&&&&&&c、useGoods(GetGoodsIndex(&金创药(小)&);
&&&&&2.5.5、TabCtrl控件的使用(VC++基础好的可跳过)-----------------84
a、m_tab.InsertItem
b、m_tab.GetCurSel()
c、Create(IDD_PAG1,GetDlgItem(IDC_TAB))
&&&&&2.5.6、TabCtrl控件BUG修证(VC++基础好的可跳过)---------------85
&&&&&&&&&&&a、修证乱码
&&&&&&&&&&&b、修证对齐
&&&&&&&&&&&c、局部美化(位置大小调整)
&&&&&2.5.7、捡物功能分析实现---------------------------------86
&&&&&&&&&a、捡物功能CALL分析
&&&&&&&&&b、捡物CALL参数分析
&&&&&&&&&c、找出所有动作CALL(打坐/普攻/捡物/交易/组队/走跑切换....)
&&&&&&&&&d、测试及封装到pickgoods()函数&
&&&&&2.5.8:&F1-F10技能数组分析-------------------------------88
&&&&&&&&&a、F1-F10技能栏数组(基址+偏移)
&&&&&&&&&b、F1-F10功能调用核心代码分析
&&&&&2.5.9、F1-F10功能CALL---------------------------------90
&&&&&&&&&a、找出真的功能CALL
&&&&&&&&&b、F1-F10功能CALL参数分析
&&&&&&&&&c、F1-F10功能CALL测试(集成功能至GameProc.h)&&&&&&&&&&&&&&&&&&&
&3、进阶篇&&
&&&&主要讲功能CALL的参数分析
&&&&&汇编浮点指令/浮点运行/浮点数整数转换/汇编里的指针
&3.1.1、喊话功能CALL地址&&&&-------------------------------93
&&&&&&a、找喊话内容地址
&&&&&&b、分析出关键CALL
&&&&&&c、测试关键CALL&&
&3.1.2、喊话功能VC++实现------------------------------------94
&&&&&&a、分析喊话CALL参数基址+偏移&
&&&&&&b、汇编指令lea
&&&&&&c、字串操作REPNZ/REPNE与SCAS
&&&&&&d、V++代码实现
&3.2.1、走路相关数据分析(为分析走路/寻路CALL做准备)----------97
&&&&&a、查找当前角色坐标(xhy)
&&&&&b、查找目的地坐标(xhy)偏移+基址
&&&&&c、找出相关CALL&&&&&
&3.2.2、走路功能CALL及相关分析-------------------------------98
&&&&&&a、隐藏的push指令
&&&&&&b、测试走路CALL
&&&&&&c、确定功能CALL及参数
&3.2.3、对找到的几个疑是CALL进行测试---------------------------100
&&&&&&a、分析出疑是CALL相关参数
&&&&&&b、对找到的CALL进行逐一测试
&&&&&&c、确定真正的走路CALL
&3.2.4、人物走跑站状态开关分析---------------------------------102
&&&&&&a、走路CALL&状态开关分析
&&&&&&b、分析状态开关&基址+偏移
&&&&&&c、分析走路目的地址相关基址+偏移
&3.2.5、利用分析数据&实现走路/寻路---------------------------104
&&&&&&a、走路功能代码实现
&&&&&&b、测试
&&&&&&c、封装到walk(x,y)
&&&&&&d、瞬移(穿墙)
&3.3、&怪物过滤
&&&&&&3.3.1、怪物列表关键代码分析&-------------------------&105
&&&&&&&&&&&&&a、怪物列表(分析原理)
&&&&&&&&&&&&&b、回溯怪物列表基址+偏移
&&&&&&&&&&&&&c、取得怪物对象的公式
&&&&&&3.3.2、怪物属性分析&-----------------------------------107
&&&&&&&&&&&&&a、怪物名
&&&&&&&&&&&&&b、怪物血量
&&&&&&&&&&&&&c、怪物ID
&&&&&&&&&&&&&d、怪物与玩家距离&&
&&&&&&&&&&&&&e、提取特征码&&&&&&&&&&&
&&&&&&3.3.3、怪物过滤的编写代码&&&&&&&&&------------------------108&&
&&&&&&&&&&&&a、读出怪物列表
&&&&&&&&&&&&b、过滤掉指定怪物&
&&&&&&&&&&&&c、选定特定怪物&
&&&&&&&&&&&&d、过滤打怪测试&
&&&&&&&&&&&&e、选中最近怪物&&&&&&&&&&&&&&&&&&&&&
&3.4、&物品过滤
&&&&&&3.4.1、物品属性分析&&&---------------------------------111
&&&&&&&&&&&&&a、物品ID
&&&&&&&&&&&&&b、物品对象
&&&&&&&&&&&&&c、物品属性分析
&&&&&&3.4.2、物品过滤(编程读出物品列表数据)------------------112
&&&&&&&&&&&&&a、读出物品列表
&&&&&&&&&&&&&b、条件判断是否捡物(距离,物品名)
&&&&&&&&&&&&&c、显示出提示信息&&
&&&&&&3.4.3、捡物过滤&&--------------------------------------113
&&&&&&&&&&&&&a、分析捡物深层CALL
&&&&&&&&&&&&&b、PickID(物品ID);
&&&&&&&&&&&&&c、捡物过滤
&&&&&&&&&&&&&d、捡物范围控制
&&&&&3.4.4、游戏多开实现------------------------------------116
&&&&&&&&&&&&&a、游戏防止多开的原理
&&&&&&&&&&&&&b、找出本游戏多开的方法
&&&&&&&&&&&&&c、测试验证&&
&3.5、&组队相关
&&&&&&3.5.1、&选定指定角色------------------------------118
&&&&&&&&&&&&a、多开BUG修证
&&&&&&&&&&&&b、分析玩家属性
&&&&&&&&&&&&c、遍历玩家列表
&&&&&&&&&&&&d、选定指定玩家角色原理
&&&&&&&&&&&&e、int&SelPlayEr(pchar&玩家名);
&&&&&&3.5.2、计算玩家间的距离(已知坐标)----------------120
&&&&&&&&&&&&a、坐标系内的点1与点2
&&&&&&&&&&&&b、2点间的距离计算公式
&&&&&&&&&&&&c、准备知识
&&&&&&&&&&&&d、planRange(int&p1,int&p2)函数构建
&&&&&&3.5.3、&组队功能123
&&&&&&&&&&&a、更新组队动作CALL
&&&&&&&&&&&b、选定指定玩家
&&&&&&&&&&&c、邀请指定玩家加入队伍int&Invite(char*&playName);
&&&&&&3.5.4、&离队功能&&------------------------------124
&&&&&&&&&&&a、分析离队动作
&&&&&&&&&&&b、逆向分析离队代码
&&&&&&&&&&&c、初识封包
&&&&&&&&&&&d、Rep&stos&[edi]
&&&&&&&&&&&e、内存中的数据与&byte,int的对应关系
&&&&&&&&&&&f、封装离队函数void&exitTeam();
&3.6、售物/购物(封包的世界)&&&&
&&&&&&3.6.1、售物功能封包分析---------------------------126
&&&&&&&&&&1、封包回溯,找未加密的封包
&&&&&&&&&&2、确家关键CALL
&&&&&&&&&&3、分析封包(物品数量,类型,位置)
&&&&&&&&&&4、功能测试SellGoods函数构建
&&&&&3.6.2&售物封包参数来源分析----------------------128
&&&&&&&&&&1、数量分析
&&&&&&&&&&2、出售物品类型分析
&&&&&&&&&&3、出售物品在背包里的格数
&&&&&&&&&&4、各种数据的来源
&&&&&3.6.3、编程实现出售背包指定物品-----------------132
&&&&&&&&&&1、遍历背包指定物品
&&&&&&&&&&2、出售背包第一格物品
&&&&&&&&&&3、出售背包第N格物品
&&&&&3.6.4、完善售物功能----------------------------134
&&&&&&&&&&1、构建函数int&FindIndex(char*&name);
&&&&&&&&&&&&&FindIndex//用来查询指定物品名name在背包中的位置
&&&&&&&&&&2、垃圾物品清单
&&&&&&&&&&3、遍历出售所有垃圾物品SellGoods
&&&&&&&&&&4、移植函数到Gameproc.h&&&&&&&&&&
&&&&&3.6.5、打开NPC购物/售物对话框-------------------137
&&&&&&&&&&1、打开NPC对话
&&&&&&&&&&2、打开NPC(买进/卖出)窗口&
&&&&&&&&&&3、封装到int&OpenNpc_buysell();测试&&&
&&&&&3.6.6、购物功能封包分析------------------------140
&&&&&&&&&&1、封包回溯,找未加密的封包
&&&&&&&&&&2、确家关键CALL
&&&&&&&&&&3、分析封包&&&&&&&&&
&&&&&&&&&&4、数量分析
&&&&&&&&&&5、出售物品类型分析&&
&&&&&&&&&&6、功能测试&&&&&&&&&&&
&3.7、&摆摊.开店
&&&&&3.7.1&开店封包分析------------------------------142
&&&&&&&a、店名分析
&&&&&&&b、封包参数分析
&&&&&&&c、为TAB选项卡2&添加内容
&&&&&&&d、不同CPP之间共享函数及变量的方法
&&&&&&&d、写申请开店代码测试&
&&&&&3.7.2&开店封包(挂店物品分析)------------------145
&&&&&&&a、分析封包
&&&&&&&b、封包出售物品的格式分析
&&&&&&&c、写代码测试
&4、高级篇&&&
&&&&4.0、编写相对完整的外挂&&------------------------149
&&&&&&4.0.1、窗口界面整理
&&&&&&&&&&&a、常规选项卡
&&&&&&&&&&&b、保护选项卡
&&&&&&&&&&&c、捡物选项卡
&&&&&&&&&&&d、喊话选项卡&&&&&&&&&&
&&&&&&4.0.2、常规选项卡-自动打怪函数构建-------------154
&&&&&&&&&&&a、关联变量
&&&&&&&&&&&b、选怪函数优化
&&&&&&&&&&&c、共享变量&extern
&&&&&&&&&&&d、算法设计
&&&&&&&&&&&e、功能测试
&&&&&&4.0.3、保护选项卡-自动补红补蓝函数构建----------159
&&&&&&&&&&&a、402中的BUG修整
&&&&&&&&&&&b、算法设计
&&&&&&&&&&&c、编写代码
&&&&&&&&&&&d、功能测试
&&&&&&4.0.4、捡物选项卡-自动捡物函数构建--------------164
&&&&&&&&&&&a、过滤垃圾物品-不捡垃圾列表里的物品
&&&&&&&&&&&b、算法设计
&&&&&&&&&&&c、编写代码
&&&&&&&&&&&d、功能测试
&&&&&&4.0.5、喊话选项卡-自动喊话设置------------------168
&&&&&&&&&&&a、关联变量
&&&&&&&&&&&b、喊话功能算法设计
&&&&&&&&&&&c、编写代码
&&&&&&&&&&&d、功能测试
&&&&4.1、游戏更新后的外挂更新&------------------------174
&&&&4.2、脚本功能-------------------------------------175
&&&&4.3、盗号的实现&&&--------------------------------180
初级篇1.1.1教学目标:模拟鼠标操作
&&&&&1.1.1、游戏数据分析(SPY++)
&&&&&&&&&&&&&&&&a、取得窗口相对坐标
&&&&&&&&&&&&&&&&b、读出游戏窗口信息GetWindowRect
&&&&&&&&&&&&&&&&c、移动鼠标指针SetCursorPos
&&&&&&&&&&&&&&&
HWND&FindWindow(
&&LPCTSTR&lpClassName,&&//窗口类名
&&LPCTSTR&lpWindowName&&//窗口标题
教学过程:
&取游戏标题:QQ游戏&-&连连看角色版
&取开局所在坐标:x=655;y=577&//lparam&0x0241028f
&&&拦截消息:WM_LBUTTONDOWN,WM_LBUTTONUP
API-FindWindow(NULL,&QQ游戏&-&连连看角色版&);
FindWindow,GetWindowRect,SetCursorPos
////////////////////////////////////
首先还是要用SPY查找游戏窗口,这里用到的是中文版,用”查找窗口”找到游戏标题:&QQ游戏&-&连连看角色版”,再次用查找窗口功能,这次选择”消息”,用来查找鼠标指向开始按钮的消息位置.先让消息停下来,这次选择消息的类型WM_LBUTTONDOWN和WM_LBUTTONUP,找到鼠标点击位置取开局所在坐标:x=655;y=577&//lparam&0x0241028f
下面打开VC,新建-工程-MFC&EXE-工程名是LLKWG,然后选择基本对话框,完成即可
还要在编辑框中关联变量,建立类向导
在游戏开局按钮输入代码
//&The&system&calls&this&to&obtain&the&cursor&to&display&while&the&user&drags
//&&the&minimized&window.
HCURSOR&CLlk_wgDlg::OnQueryDragIcon()
return&(HCURSOR)&m_hI
&HWND&//游戏窗口句柄
&RECT&r1;&&&//&RECT结构表示一个矩形区域
void&CLlk_wgDlg::OnStartGame()&
//&TODO:&Add&your&control&notification&handler&code&here
gameh=::FindWindow(NULL,&QQ游戏&-&连连看角色版&);//获取游戏窗口句柄
::GetWindowRect(gameh,&r1);&&&&&&&&//这里取坐标,&双冒号是全局的意思
this-&m_x=r1.this-&m_y=r1.//读出窗口左上角坐标,&this是关联变量
UpdateData(false);&&&&&&&&&&&&&&&&&//显示到编辑框
//设置鼠标指针位置&&取开局所在坐标:x=655;y=577&//lparam&0x0241028f
SetCursorPos(655+r1.left,577+r1.top);//当前窗口坐标+开局按钮坐标
&&1.1.2&用VC++写个最简单的外挂(实现游戏开局)&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&a、鼠拟鼠标单击mouse_event
&&&&&&&&&&&&&&&&b、鼠标指针移动还原
&&&&&&&&&&&&&&&&c、集成到startgame函数里
教学过程:
&//模拟鼠标的&单击(鼠标按下/鼠标抬起)
//MOUSEEVENTF_LEFTDOWN&Specifies&that&the&left&button&is&down.&
&&&&//MOUSEEVENTF_LEFTUP&
//鼠标在当前位置按下
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
//鼠标在当前位置抬起
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
&&&&mouse_event,Sleep,SetCursorPos
///////////////
这次用到了鼠标点击的函数mouse_event鼠标硬件模拟,如果调用不成功则延时一下Sleep&(200),然后再将鼠标移回原位SetCursorPos这个是位置设置函数
调用成功后,将函数放在一个.h头文件里,方便以后调用.新建&c/c++&Header&File,文件名GameProc
#include&&stdafx.h&&
//游戏&功能函数
&POINT&p;//x,y
void&startGame()
//&TODO:&Add&your&control&notification&handler&code&here
//获取游戏窗口句柄
gameh=::FindWindow(NULL,&QQ游戏&-&连连看角色版&);
::GetWindowRect(gameh,&r1);&
//保存当前鼠标指针
&&&//取得当前鼠标位置
GetCursorPos(&p);
//设置鼠标指针位置&&取开局所在坐标:x=655;y=577&//lparam&0x0241028f
SetCursorPos(655+r1.left,577+r1.top);
//模拟鼠标的&单击(鼠标按下/鼠标抬起)
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);&//鼠标在当前位置按下
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);&//鼠标在当前位置抬起
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
Sleep(200);//过一段时间&再执行后边的代码
&&&&&&SetCursorPos(p.x,p.y);&//还原鼠标位置
当然还要将这个.h文件包涵进主函数里
#include&&stdafx.h&
#include&&llk_wg.h&
#include&&llk_wgDlg.h&
#include&&GameProc.h&
然后这样调用
void&CLlk_wgDlg::OnStartGame()&
&&startGame();
今天我们要一起学习的是1.2.1
&&教学目标:&
&&1.2.1、CE中的数据类型
&&&&&&&&&&&&&&a、数据类型:Bit,Byte,Word,Dword,float,double
&&&&&&&&&&&&&&b、用CE查找出坐位号;
&&&&&&&&&&&&&&c、保存分析数据
教学过程:
&a、数据类型:Bit,Byte,Word,Dword,float,double
&C++数据类型
&bit/位&1位&&取值范围:0..1
&byte(字节)=0..进制)=0..255(10进制)=0..FF&&&(16进制)
&WORD(单字)=2Byte=0..65535(10进制)&&&&=0..FFFF&(16进制)
&DWORD(双字)=2WORD=4Byte=0..&=0..FFFFFFFF
&float(浮点数)&double(双浮点数)
&int(4字节),long(4字节),WORD,DWORD(4字节),float(4字节),double(8字节)
&&b、用CE查找出坐位号;
&&&打开&QQ游戏&连连看
&&&猜测&0..5,1..6,顺时针
&坐位号地址:0x00B8D8E0&&&&&&
///////////////////////////////////
首先讲了关于十六进制/十进制/八进制/二进制/字节/双字节等基础知识
因为游戏当中不同的座位号数据不一样,所以首先要找到座位号.
用CE搜索游戏是字节型来查找游戏的座位号,一桌是6个位置,猜测是从0到5,上面是0,顺时针方向加1.所以我们更换座位号后再继续用CE搜索相应的位置号,注意附加的进程可不要出错哦.QQ连连看的进程名是KYODAI~1.EXE,可以用任务管理器找出.
找到后将CE的数据保存一下,方便下次调用.
这节课主要讲了字节的基础知识和CE的基本用法
&今天我们要一起学习的是1.2.2
&&教学目标:&
&1.2.2、编程读出坐位号;
&&&&&&&&&&&&&&a、远程读取进程数据
&&&&&&&&&&&&&&b、打开远程进程
&&&&&&&&&&&&&&c、读取远程进程数据
教学过程:
API函数介绍
&&1、FindWindow&&&&&&&&&&&&&&&//获取窗口句柄
&&2、GetWindowThreadProcessId&//获取窗口进程ID
&&3、OpenProcess&&&&&&&&&&&&&&//打开指定进程
&&4、ReadProcessMemory&&&&&&&&//读指定进程&内存数据
&游戏进程名:KYODAI~1.EXE
&游戏窗口标题:&QQ游戏&-&连连看角色版&
&HWND&FindWindow(
&&LPCTSTR&lpClassName,&&//&NULL&忽略
&&LPCTSTR&lpWindowName&&//&窗口标题
BOOL&ReadProcessMemory(
&&HANDLE&hProcess,&&//&进程句柄&
&&LPCVOID&lpBaseAddress,
&&&&&&&&&&&&&&&&&&&&//&基址0x00B8D8E0
&&LPVOID&lpBuffer,&&//&存放数据缓冲区
&&DWORD&nSize,&&&&&&//&要读取数据的字节数
&&LPDWORD&lpNumberOfBytesRead&
&&&&&&&&&&&&&&&&&&&&//&实际读取的字节数
//////////////////////
这次需要几个函数来取得窗口/句柄/进程/内存等信息
几个函数要联合运用,前一个函数的返回值就是后一个函数的参数
在VC代码里添加座位号的变量m_Num&类型是UINT,新增一个按钮,添加如下代码
const&PCHAR&gameCaption=&QQ游戏&-&连连看角色版&;
void&CLlk_wgDlg::OnButton2()&
&&//&游戏窗口标题:&QQ游戏&-&连连看角色版&
&&//&1、FindWindow&&&&&&&&&&&&&&&//获取窗口句柄
&&//2、GetWindowThreadProcessId&//获取窗口进程ID
&&//3、OpenProcess&&&&&&&&&&&&&&//打开指定进程
&&//4、ReadProcessMemory&&&&&&&&//读指定进程&内存数据
//获取窗口句柄
HWND&gameh=::FindWindow(NULL,gameCaption);
//获取窗口进程ID
::GetWindowThreadProcessId(gameh,&processid);
//打开指定进程
HANDLE&processH=::OpenProcess(PROCESS_ALL_ACCESS,false,processid);
//读指定进程&内存数据
&&&&DWORD&
LPCVOID&pbase=(LPCVOID)0x00B8D8E0;//读取当前的指针,强制转换为LPCVOID指针
LPVOID&&nbuffer=(LPVOID)&m_&&&//保存当前的指针,强制转换为LPVOID指针
::ReadProcessMemory(processH,pbase,nbuffer,4,&byread);
UpdateData(false);&//更新变量的值到&编辑框
今天我们要一起学习的是1.2.3
&&教学目标:&
&&1.2.3、用CE查出棋盘基址;
&&&&&&&&&&&&&&a、找棋盘数据基址
&&&&&&&&&&&&&&b、分析棋盘数据结构
&19宽*11高&:数组&byte&a[19][11]
&byte&0..255&//&00..FF
&0x&&&&//棋盘数组基址
&db&地址&&&&&//&以字节方式&显示指定地址内存里的数据
////////////////////////
前面座位号的基址已经找出了,所以这次要找出棋盘的数据,
要先查一下棋盘的2维排列,是19宽*11高,用QQ截图查找一下长和宽,然后计算出每一格的大小.猜测棋盘的棋子也是字节的,我们查找左上角第一棋子的数据.
用CE查找,如果有棋子就是大于0,变化了就再搜索更改的数值,没有棋子就是0,多次查找就找到第一棋子的地址了.&自己找个座位坐下来,加个密码不让别人进,多按几次&练习&按钮,这样棋盘变化就方便找棋子数据了.老师也查找出错了,再来一次吧.
找到后用OD加载一下看看,这样的数据排序看的比较清楚
这节课讲解了CE查找的方法
今天我们要一起学习的是1.2.4
&&教学目标:&
&&1.2.4、读出当前棋盘数据
&&&&&&&&&&&&&&a、编程读出棋盘数据
&&&&&&&&&&&&&&b、棋盘数据显示出来&&&&&&&&
&参考章节:1.2.3,1.2.2
&19宽*11高&:数组&byte&a[11][19]&//&a[y][x]
&byte&0..255&//&00..FF
&0x&&&&//棋盘数组基址
&db&地址&&&&&//&以字节方式&显示指定地址内存里的数据
itoa(要转换的整数,存放字符数组,要转换的字符进制)
for&(int&y=0;y&=10;y++)&//y++&y:=Y+1;
////////////////////////////////////
添加了一个编辑框用来显示棋盘数据,再关联一个变量m_Chessdata&&Cstring类型
增加”更新棋盘数据”按钮,添加代码如下:
byte&chessdata[11][19];//a[y][x]
void&CLlk_wgDlg::OnBtnReadchess()&
//&TODO:&Add&your&control&notification&handler&code&here
//获取窗口句柄
HWND&gameh=::FindWindow(NULL,gameCaption);
//获取窗口进程ID
::GetWindowThreadProcessId(gameh,&processid);
//打开指定进程
HANDLE&processH=::OpenProcess(PROCESS_ALL_ACCESS,false,processid);
//读指定进程&内存数据
&&&&DWORD&
LPCVOID&pbase=(LPCVOID)0x;&//棋盘数据基址
LPVOID&&nbuffer=(LPVOID)&&//存放棋盘数据
::ReadProcessMemory(processH,pbase,nbuffer,11*19,&byread);
char&buf[11];&///显示棋盘数据
m_chessdata=&&;&//先清空编辑
&for&(int&y=0;y&=10;y++)//一列一列的读,FOR循环:Y=0是循环的起始值,Y&=10是终止值,Y++是每次Y+1
&for&(int&x=0;x&=18;x++)&//一行一行的读
&&itoa(chessdata[y][x],buf,16);&//itoa整型转换成字串
&&m_chessdata+=
&&m_chessdata+=&&&;
&&&&m_chessdata+=&\r\n&;&//换行
UpdateData(false);&//更新数据
今天我们要一起学习的是1.3.1
&&教学目标:&
&&&1.3.1&分析棋子与棋盘坐标关系
&&&&&&&&&&&&&&&a、鼠标软件模拟,函数SendMessage
&&&&&&&&&&&&&&&b、分析窗口内棋子相对坐标X,Y&
&&&&&&&&&&&&&&&c、软件模拟点击棋盘坐标x,y处的棋子
SendMessage(hwnd,WM_LBUTTOMDOWN,0,YX);//hwnd=FindWindow(NULL,游戏标题);
SendMessage(hwnd,WM_LBUTTOMUP,0,YX);&&//PostMessage/mouse_event
2、获取棋盘左上角棋盘第一格坐标.
&棋盘第一格&坐标&x=21,y=192
int&&&x=22,y=187;
hwnd=FindWindow(NULL,游戏标题);
SendMessage(hwnd,WM_LBUTTONDOWN,0,(y&&16)+x);//
SendMessage(hwnd,WM_LBUTTONUP,0,(y&&16)+x);&&//&
3、计算棋盘的&宽度*高度
棋盘第一格&
坐标&x=21,y=192
31*35&棋子宽度,高度
SendMessage(hwnd,WM_LBUTTONDOWN,0,(y&&16)+x+31*2);//
SendMessage(hwnd,WM_LBUTTONUP,0,(y&&16)+x);&&//&
//SendMessage&鼠标模拟,//WM_LBUTTONDOWN&鼠标左键按下&//WM_LBUTTONUP&鼠标左键抬起
//&&&左移指令
&//////////////////////////
前面都是直接移动了鼠标,这次要改发送鼠标消息了,这样鼠标不移动也会点击游戏的开始按钮.SendMessage的参数是相对坐标,&mouse_event的参数是绝对坐标
再次打开SPY++,找到棋盘第一格的位置,X=21,Y=187
新增一个按钮”点击棋盘第一格”方便测试,添加代码如下:
void&CLlk_wgDlg::OnButton3()&&&&&&&&&&&&&&&&&&&&&&&//按钮函数
int&&&x=22,y=187;&&&&&&&&&&&&&&&&&&&&&&&&&&&//定义座标点
HWND&hwnd=::FindWindow(NULL,gameCaption);&&&//查找窗口
int&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//定义座标点变量
lparam=(y&&16)+x+31*2;&&&&&&&&&&&&&&&&&&&&&&//表示指定格,Y&&16是左移16位,发消息用的Y座标点
::SendMessage(hwnd,WM_LBUTTONDOWN,0,lparam);//鼠标按下消息
::SendMessage(hwnd,WM_LBUTTONUP,0,lparam);&&//鼠标抬起消息
用QQ抓图,查找棋子格子数大小,31*35的大小,以便计算出所有格子的座标点.
今天我们要一起学习的是1.3.2
&&教学目标:&&
&&&1.3.2&消掉一对棋子的算法框架
&&&&&&&&&&&&&&&a、遍历棋盘同类型棋子配对
&&&&&&&&&&&&&&&b、构建算法框架
&//遍历整个&棋盘&找相同一对棋子
&//检测这一对棋子是否&可以消除
&//如果&可以消除&,则模拟鼠标点击这2点
最多一条&三条&连线&能够形式一条&路线&就表示可消除
&////////////////////////////
更改”点击棋盘第一格”代码如下:
void&ClearPiar()&//消除一对棋子
//读出棋盘数据至chessdata&11,19
&&&&&updatdChess();
//遍历整个棋盘&找出相同类型&一对棋子
&POINT&p1,p2;//定义两个点,座标型
&int&x1,y1,x2,y2;//定义座标点
&&for&(y1=0;y1&11;y1++)//点1循环,从Y列开始
&&for&(x1=0;x1&19;x1++)//点2循环,从X行开始
&&{&&&for&(y2=y1;y2&11;y2++)//这是点2的Y循环,由Y1开始
&&for&(x2=x1;x2&19;x2++)//这是点2的X循环,由X1开始
//&棋子1与棋子2&类型是否相同,&要求点1与点2&相等则假,就是座标不能相同.
&&if&((chessdata[y1][x1]==chessdata[y2][x2])&&&(!((x1==x2)&&(y1==y2)))&& &&)
&&p1.x=x1;p1.y=y1;
&&p2.x=x2;p2.y=y2;
&&//检测&相同的2个棋子是否可消掉
&if&(&check2p(p1,p2))//如果可消除&则返回真
&//click2p&鼠标模拟&点击&p1,p2
&click2p(p1,p2);
这节课讲的是VC编程,需要对逻辑运算有一定的理解,&要检测两点是否相同,同时要避免在同一点,还要检测两点是否可消除,检测的函数check2p先定义了一个空的,下节课再添加代码.模拟鼠标点击的函数click2p本节课也没有添加代码.
今天我们要一起学习的是1.3.2
&&教学目标:&&
&&1.3.3&(Check2p)大致框架(算法核心)
&&&&&&&&&&&&&&&a、在这一对棋子间找相通路径的原理
&&&&&&&&&&&&&&&b、(Check2p函数)框架代码
&&&&&&&&&&&&&&&c、(CheckLine函数)检测2点是否有连通
LineNull(p1,p2);&//是否在棋盘上&的2个点之前是否有一条全为0的直线,如有true,否则false
1、剪贴游戏图;
Y坐标相同的情况下&p1,p2&
lineNull(p1.right,p2.left)&//可消除
X坐标相同的情况下&p1,p2
LineNull(p1.down,p2.up)&&&&//可消除
X与Y坐标都不相情况下&p1,p2
lineNll(p1.down,pa),LineNull(p2.down,pb),LineNull(pa,pb)
&////////////////////////////////////
现在就要来分析游戏了,连连看大家都知道,是需要判断两点间是否可以连接的,比如有直连,有一折后的连接,最多是二折后的连接.
如果是直连的话,就要判断中间是否所有的数据都为0,判断的思路很主要,一定要搞清楚.而有折的连接则需要多条直线,最多是三条直线,这个需要遍历,不断的向下判断.
将VC代码打开,插入一个类Generic&Class,名称为CChessPoint
添加代码如下:
class&CChessPoint&&
POINT&p;//临时点
POINT&//上点
POINT&//下点
POINT&//左点
POINT&//右点
CChessPoint(POINT&pxy);&&//构造函数
virtual&~CChessPoint();
还要在Cchesspoint.cpp实现部分修改代码
CChessPoint::CChessPoint(POINT&pxy)&
{&&&&up=down=left=right=//将座标初始化
//向上下左右扩展
&&&&&up.y=pxy.y-1;
&down.y=pxy.y+1;
&left.x=pxy.x-1;
&right.x=pxy.x+1;
&//这样处理完之后每个棋子就包涵了上下左右中五个点的属性
CChessPoint::~CChessPoint()
在按钮部分增加代码如下:
bool&lineNull(POINT&p1,POINT&p2)
return&//先写个空的,下节课继续.
bool&check2p(POINT&p1,POINT&p2)
{&//检测&p1,p2&2个棋子&是否可以消除
//&Y坐标相同的情况下&p1,p2&
//lineNull(p1.right,p2.left)&//可消除
if&(p1.y==p2.y)&//如果列相同则执行
{&&&&CChessPoint&pa(p1),pb(p2);//先建立类,初始化两点
&if&(lineNull(pa.down,pb.up))&return&//先将两个点类化,&可消除返回真
//X坐标相同的情况下&p1,p2
//LineNull(p1.down,p2.up)&&&&//可消除
if&(p1.x==p2.x)&//如果行相同则执行此句
{&&&&CChessPoint&pa(p1),pb(p2);
&if&(lineNull(pa.down,pb.up))&return&
//X与Y坐标都不相情况下&p1,p2
//lineNull(p1.down,pa),LineNull(p2.down,pb),LineNull(pa,pb)
这节讲VC,比较难理解,很多地方与DELPHI不同,老师写了很多代码,我不太懂,是不是代码写的太啰嗦了?还是我水平太差.我再继续学学看,如果不懂的太多,就要参考别的VC教程一起学习了.这节课代码还没有写完,时间已经到了,下节继续.
&今天我们要一起学习的是1.3.4
&&教学目标:&&
&&1.3.4&CheckLine实现
&&&&&&&&&&&&&&&a、CheckLine函数实现
&&&&&&&&&&&&&&&b、Check2p核心代码架构
&bool&CheckLine(POINT&p1;POINT&p2)
&&//x坐标相同
//&p1.y&to&p2.y
&&//Y坐标相同
&//p1.x&to&p2.x
&///////////////////////////////
首先还是要添加修改两点间是直线的判断函数
bool&CheckLine(POINT&p1,POINT&p2)&//检测2点间&是否连通(存在一条全为0的直线路径)
if&(p1.x==p2.x)//两点X坐标相同
for&(y=p1.y;y&=p2.y;y++)
&&&&&&&&&//假如ChessData[y][p1.x]&&Y的某一个点大于0则说明有棋子,就返回&false;
if&(chessdata[y][p1.x]&0)&return&
else&if&(p1.y==p2.y)
&&&&&&&&&for&(x=p1.x;x&=p2.x;x++)
&{//假如ChessData[p1.y][x]&X某一点有棋子则大于0返回&
& if&(chessdata[p1.y][x]&0)&return&
再添加除了直线的两点函数检测的代码
bool&check2p(POINT&p1,POINT&p2)
&CChessPoint&pa(p1),pb(p2);//初始化棋子类
&POINT&p11,p22;//新建两个变量指针,方便调用
&int&x,y;//新建两个整型变量,方便调用
//检测&p1,p2&2个棋子&是否可以消除
if&(p1.y==p2.y)&//&Y坐标相同的情况下&p1,p2&
&if&(CheckLine(pa.down,pb.up))&return&//找到相同路线
&//pa,pb&;&pa,p_1;pb,p_2;
&p11=p1;p22=p2;
&for&(y=0;y&11;y++)
&&&p11.y=p22.y=y;
//找到转折的路线
&&&&&&&&&&if&heckLine(p11,p22)&&CheckLine(pa.up,p11)&&CheckLine(pb.up,p22))
本节全是在编写VC代码,思考如何判断几条连线,代码也没写完,也没测试,不知道对不对,时间到了,下节课继续写.
今天我们要一起学习的是1.3.5
&&教学目标:&&
&&&&1.3.5&Check2p完整代码实现
&&&&&&&&&&&&&&&a、完整的Ceheck2p代码解析
&&&&&&&&&&&&&&&b、完善CheckLine函数&&&&&&&&&&&&&&
&&&Check2P实现原理;
Y坐标相同:pa=p1.left,pb=p2.right//&pa,pb之间是否连通&则消除
X坐标相同:&pa=p1.down,pb=p2.up&//pa,pb之间是否连通&则消除
X,Y坐标都不相同
&&pa,pb//&p1,pa//&pb,p2&这三线路&都连通&则可消除
&&p1,pa,//pa,pb//p2,pb&这三线路&都连通&则可消除
&/////////////////////
本节课老师讲课用了FLASH工具,比起之前用画图要强的多,使我一下子就理解了这几个点之间的关系.
比如在两点可以直连的情况下,第一个棋子是P1,第二个棋子是P2,第一个棋子与第二个棋子之间的点是PA到PB,这两个点要不断的循环,查找其中是否为空,如果为空则可以消除.当然这是横向的连接,同时还有竖向的连接
Y坐标相同:pa=p1.left,pb=p2.right//&pa,pb之间是否连通&则消除
当然更多的是折线的连接
X,Y坐标都不相同
&&pa,pb//&p1,pa//&pb,p2&这三线路&都连通&则可消除
&&p1,pa,//pa,pb//p2,pb&这三线路&都连通&则可消除
老师已经写好了三个函数的代码
bool&CheckLine( POINT&p1,POINT&p2)
int&x,y,t;&&&&//同一线上的两点间&全为0&则返回真&
&&//如果&p1==p2&也返回真
&&if&((p1.x==p2.x)&&(p1.y==p2.y)&&&&(chessdata[p1.y][p1.x]==0)&&&&(chessdata[p2.y][p2.x]==0))&&{return&&&&&}else
&&if&((p1.x&0)&||&(p1.x&18)&||&(p1.y&0)&||&(p1.y&10)&||
&&&&&(p2.x&0)&||&(p2.x&18)&||&(p2.y&0)&||&(p2.y&10)&)&&{return&&&}
&&if&(p1.x==p2.x)&&&&&//如果X轴相等则&比较
&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&if&(p1.y&p2.y)&{t=p1.y;p1.y=p2.y;p2.y=t;}
&&&&&&&&&&&&&&&&&&&&for&(y=p1.y;y&=p2.y;y++)
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&if&(chessdata[y][p1.x]!=0&)&{return&}
&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&}&
&&if&(p1.y==p2.y)&
&&&&&&&&&&&&&&{&&&&//如果Y轴相等&则比较
&&&&&&&&&&&&&&&&&&if&(p1.x&&&p2.x)&&{t=p1.x;p1.x=p2.x&;p2.x=t;}
&&&&&&&&&&&&&&&&&&&&for(x=p1.x;x&=p2.x;x++)
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&if&(chessdata[p1.y][x]!=0&)&{return&&}
&&&&&&&&&&&&&&&&&&&&&};
&&&&&&&&&&&&&&};
&&return&&
另一个函数,这个因为与窗口有关系,所以就转移到llk_wgDlg.cpp里
bool&&ClearPiar()&//消除一对棋子
//读出棋盘数据至chessdata&11,19
&&&&&updateChess();
//遍历整个棋盘&找出相同类型&一对棋子
&POINT&p1,p2;
&int&x1,y1,x2,y2;
&&for&(y1=0;y1&11;y1++)
&&for&(x1=0;x1&19;x1++)
&&{&&&for&(y2=y1;y2&11;y2++)
&&for&(x2=x1;x2&19;x2++)
&&if&((chessdata[y1][x1]==chessdata[y2][x2])&//&棋子1与棋子2&类型是否相同
&&&&(!((x1==x2)&&(y1==y2)))&&//要求点1与点2&相等则假
&&p1.x=x1;p1.y=y1;
&&p2.x=x2;p2.y=y2;
&&//检测&相同的2个棋子是否可消掉
&if&(&Check2p(p1,p2))//如果可消除&则返回真
&//click2p&鼠标模拟&点击&p1,p2
&click2p(p1,p2);
&m_p1x=x1;
&m_p1y=y1;
&m_p2x=x2;
&m_p2y=y2;
&UpdateData(false);
还有一个最长的函数
bool&Check2p(POINT&a,POINT&b)
&CChessPoint&p1(a),p2(b);
&POINT&&pa,//转角点
//&如果2点为同一点&则返回假
&if&((a.x==b.x)&&&&(a.y==b.y&))&&{&return&}&else
&&&&&&&if&((chessdata[a.y][a.x]==0)&||&(chessdata[b.y][b.x]==0))&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{&return&}&else
&&&&&&&&&&&&&&&&&if&(chessdata[a.y][a.x]!=chessdata[b.y][b.x])&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{&return&}
&&&&&&&&pa=a;pb=b;
&&&&&&&//&在横向一条线上&y坐标&相同
&&&&&&&if&(a.y==b.y)&&
&&&&&&&&&&&&&&&&&&&&{&&&&&//&2点在y轴相邻
&&&&&&&&&&&&&&&&&&&&&&&&&&&if&((p1.right.x==p2.p.x)&||&(p1.left.x==p2.p.x))&&&&&&{&return&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&//检测&这条线是否有一条路径相通
&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(p1.right,p2.left&))&{return&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&//检测&上下
&&&&&&&&&&&&&&&&&&&&&&&&&&&&//y&上
&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa=a;pb=b;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&((p1.up.y&&=0)&&&&(p1.up.y&=10))&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&for&(&y=0&;y&=p1.up.y;y++)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.y=y;pb.y=y;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,p1.up)&&&&CheckLine(pb,p2.up&)&&&&CheckLine(pa,pb))&&{&return&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//&y下
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa=a;pb=b;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&((p1.down.y&&=0)&&&(p1.down.y&&=10))&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&for&(&y=p1.down.y;y&=10;y++)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.y=y;pb.y=y;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,p1.down&)&&&&CheckLine(pb,p2.down&)&&&&CheckLine(pa,pb))&&{&return&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&//检测&左右&&&&因为&y轴相等,所以不存在左右路径
&&&&&&&&&&&&&&&&&&&&}&else
&&&&&&&//纵向一条线&&x&坐标&相同
&&&&&&&if&(a.x==b.x)
&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&//x下上&相邻不
&&&&&&&&&&&&&&&&&&&&&&&&if&((p1.down.y==p2.p.y&)&||&(p1.up.y==p2.p.y))&&&{&return&&&&}
&&&&&&&&&&&&&&&&&&&&&&&//检测&这条线是否有一条路径相通
&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(p1.down,p2.up)&)&&{&return&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&//检测&上下&&&国为x&轴相等&所以不存在路径
&&&&&&&&&&&&&&&&&&&&&&&//检测&左右
&&&&&&&&&&&&&&&&&&&&&&&&//x左
&&&&&&&&&&&&&&&&&&&&&&&&pa=a;pb=b;
&&&&&&&&&&&&&&&&&&&&&&&&for&(x=0&;x&=p1.left.x&;x++)
&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pb.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,p1.left)&&&&CheckLine(pb,p2.left&)&&&&CheckLine(pa,pb))&&{&return&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&//x右
&&&&&&&&&&&&&&&&&&&&&&&&pa=a;pb=b;
&&&&&&&&&&&&&&&&&&&&&&&&for&(x=p1.right.x;x&=18;x++)
&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pb.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,p1.right&)&&&&CheckLine(pb,p2.right&)&&&&CheckLine(pa,pb))&&{&return&&&}
&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&}&else
&&&&&&&//xy&坐标&都不相同&{{{{{{
&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&pa=a;pb=b;
&&&&&&&&&&&&&&&&&&&&&if&(a.x&b.x)&&{&&&//&p2点&在&左&left
&&&&&&&&&&&&&&&&&&&&////////////////xxxxxxxxxxxxxxxxx&&找x轴路径
&&&&&&&&&&&&&&&&&&&&&for&(x=0;x&=p2.left.x;x++)
&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&pa.x=x;pb.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,p1.left)&&&&CheckLine(pa,pb)&&&&CheckLine(pb,p2.left))&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{return&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&}&//&end&for
&&&&&&&&&&&&&&&&&&&&&&for&(x=p2.right.x&;x&=&p1.left.x;x++)
&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&pa.x=x;pb.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(p2.right,pb)&&&&CheckLine(pa,pb)&&&CheckLine(pa,p1.left))&&{return&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&for&(x=p2.right.x;x&=18;x++)
&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&pa.x=x;pb.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(p1.right&,pa)&&&CheckLine(p2.right&,pb)&&&&CheckLine(pa,pb))&&{&return&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&/////////////////yyyyyyyyyyyyyyyyyyyy&找y轴路径&由于是从上向下&搜索&所以p1.y&p2.y
&&&&&&&&&&&&&&&&&&&&&&&pa.x=a.x;&&&pb.x=b.x;&//初始化坐标&y軕渐变
&&&&&&&&&&&&&&&&&&&&&for&(&y=0&;y&=p1.up.y;y++)&&&&//1段
&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&pa.y=y;pb.y=y;
&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pb,pa)&&&&CheckLine(pa,p1.up)&&&&CheckLine(pb,p2.up))&&&&&&{&return&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&////////////////////////
&&&&&&&&&&&&&&&&&&&&&for&(y=p1.down.y&;y&=p2.up.y;y++)//2段
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&pa.y=y;pb.y=y;
&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pb,pa)&&&CheckLine(p1.down,pa)&&&&CheckLine(pb,p2.up))&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&return&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&///////////////////////
&&&&&&&&&&&&&&&&&&&&&for&(y=p2.down.y&;y&=10&;y++)&//3段
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&///////////////////////////////
&&&&&&&&&&&&&&&&&&&&&pa.y=y;pb.y=y;
&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pb,pa)&&&&CheckLine(p1.down,pa)&&&&CheckLine(p2.down,pb))&&&{&return&&&&}
&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&else
&&&&&&&&&&&&&&&////////////p2点&&在&右&right&a.x&b.x
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.y=a.y;&&&pb.y=b.y;&//初始化坐标
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&for&(x=0&;x&=&p1.left.x&;x++);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.x=x;pb.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,pb)&&&CheckLine(pa,p1.left)&&&CheckLine(pb,p2.left))&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&return&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&/////////////////////
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&for&(x=p1.right.x&;x&=p2.left.x;x++)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.x=x;pb.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,pb)&&&CheckLine(p1.right,pa)&&&CheckLine(pb,p2.left))&&{&return&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&///////////////////////
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&for&(x=p2.right.x&;x&=18;x++)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.x=0;pb.x=x;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,pb)&&&&CheckLine(p1.right,pa)&&&CheckLine(p2.right,pb))&{return&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&///////////////////////yyyyyyyyyyyyyyyyyy&&&y轴渐变
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.x&=a.x;&&&pb.x&=b.x&;&//初始化坐标
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&((p1.up.y&=0)&&&&(p1.up.y&=10))
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&for&(y=0&;y&=p1.up.y&;y++)&&&&//1段
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.y=y;pb.y=y;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,pb)&&&CheckLine(pa,p1.up)&&&&CheckLine(pb,p2.up))&&{&return&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//////
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.x&=a.x;&&&pb.x&=b.x&;&//初始化坐标
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&((p1.down.y&=10)&&&&(p2.up.y&=0))&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&for&(y=p1.down.y&;y&=p2.up.y;y++)&&//2段
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.y=y;pb.y=y;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,pb)&&&CheckLine(p1.down,pa)&&&&CheckLine(pb,p2.up))&&{&return&
}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&////
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.x&=a.x;&&&pb.x&=b.x&;&//初始化坐标
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(p2.down.y&&=10)&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&for&(&y=p2.down.y;y&=10;y++)&&&&&&&&&&&//3段
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pa.y=y;pb.y=y;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(CheckLine(pa,pb)&&&&CheckLine(p1.down,pa)&&&CheckLine(p2.down&,pb))&&{&return&&}
}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&//xy&坐标&都不相同&}}}}}}}}}
这节课的代码实在太长了,老师也是先自己写好了再发出来的,他说如果在教程中写代码的话起码要1个小时.添加一个按钮两个编辑框,将代码来测试一下,先单消一次看看,好像已经找到能够消除的棋子了,但是还没有实现自动点击,下节课继续……
这节课太难懂了,本来还想通过课程学学VC代码,但是感觉更晕了.
今天我们要一起学习的是1.3.6
&&教学目标:&&
&&&&&1.3.6&Click2p函数实现,单消棋子功能实现
&&&&&&&&&&&&&&&a、完成Click2p函数
&&&&&&&&&&&&&&&b、单消一对棋子的实现
&&&&&&&&&&&&&&&c、修改ClearPair函数
&棋盘第一格&坐标&x=21,y=192
31*35&棋子宽度,高度
SendMessage(hwnd,WM_LBUTTONDOWN,0,(y&&16)+x+31*2);//
SendMessage(hwnd,WM_LBUTTONUP,0,(y&&16)+x);&&//&
bool&Click2p(POINT&p1,POINT&p2)
HWND&hwnd=FindWindow(NULL,gameCaption);
&lparam=((p1.y*35+192)&&16)+(p1.x*31+21);
SendMessage(hwnd,WM_LBUTTONDOWN,0,lparam);//
SendMessage(hwnd,WM_LBUTTONUP,0,lparam);//
lparam=((p2.y*35+192)&&16)+(p2.x*31+21);
SendMessage(hwnd,WM_LBUTTONDOWN,0,lparam);//
SendMessage(hwnd,WM_LBUTTONUP,0,lparam);//
&//////////////////////
前面的代码只是分析出可消除的棋子,并没有实现真正消除,所以本节课将模拟鼠标点击,发送鼠标信息来实现自动消除棋子
bool&Click2p(POINT&p1,POINT&p2)//点击两点函数
HWND&hwnd=FindWindow(NULL,gameCaption);//查找游戏窗口
&int&//定义参数
//192是棋盘距离窗口上面的距离,21是棋盘距离左边的距离
&lparam=((p1.y*35+192)&&16)+(p1.x*31+21);//通过棋子格子计算位置
SendMessage(hwnd,WM_LBUTTONDOWN,0,lparam);//鼠标按下
SendMessage(hwnd,WM_LBUTTONUP,0,lparam);//鼠标抬起
lparam=((p2.y*35+192)&&16)+(p2.x*31+21);//计算配对棋子位置
SendMessage(hwnd,WM_LBUTTONDOWN,0,lparam);//
SendMessage(hwnd,WM_LBUTTONUP,0,lparam);//
代码添加完之后挂上游戏测试了一下,发现开始可以消除棋子,后面就不动了,再继续查找代码,分析哪里出错.
将bool&CLlk_wgDlg::ClearPiar()&函数的
for&(x1=x1;x1&19;x1++)
for&(x1=0;x1&19;x1++)//不要限制其格子数
还要将for&(x2=x1;x2&19;x2++)
改成for&(x2=0;x2&19;x2++)
这回可以消除所有棋子了
这节课才14分钟,代码写的比较少,相比上节的代码简单太多了,很容易理解,老师上节的代码也没仔细讲解一下………..看看后面有没有讲,如果没讲我就让他有空给讲讲,嘿嘿.
其实记笔记主要是记课程当中都讲了什么内容,以便以后查阅起来方便.
今天我们要一起学习的是1.3.7
&&教学目标:&&
&&&&&&1.3.7&挂机/秒杀/
&&&&&&&&&&&&&a、自动开局
&&&&&&&&&&&&&b、挂机下棋
&&&&&&&&&&&&&c、秒杀
&UINT&SetTimer(
&&HWND&hWnd,&&&&&&&&&&&&&&//&指向窗口句柄&
&&UINT&nIDEvent,&&&&&&&&&&//&时钟标识
&&UINT&uElapse,&&&&&&&&&&&//&时间间隔&(毫秒)
&&TIMERPROC&lpTimerFunc&&&//&指向回调函数的地址
&KillTimer(UINT&nIDEvent);&&&&&&&&&&//&时钟标识
VOID&CALLBACK&playproc(
&&HWND&hwnd,&&&&&//&handle&of&window&for&timer&messages
&&UINT&uMsg,&&&&&//&WM_TIMER&message
&&UINT&idEvent,&&//&timer&identifier
&&DWORD&dwTime&&&//&current&system&time
&ClearPiar();
VOID&CALLBACK&strartproc(
&&HWND&hwnd,&&&&&//&handle&of&window&for&timer&messages
&&UINT&uMsg,&&&&&//&WM_TIMER&message
&&UINT&idEvent,&&//&timer&identifier
&&DWORD&dwTime&&&//&current&system&time
&startGame();&//自动开局
const&PLAYID=111;
&const&STARTID=112;
void&CLlk_wgDlg::OnCheck1()&
//&TODO:&Add&your&control&notification&handler&code&here
UpdateData(true);//更新窗口内容至变量
if&(m_autoplay)
SetTimer(PLAYID,1500,&playproc);
KillTimer(PLAYID);
void&CLlk_wgDlg::OnCheck2()&
//&TODO:&Add&your&control&notification&handler&code&here
UpdateData(true);//更新窗口内容至变量
if&(m_autoplay)
SetTimer(STARTID,3*1000,&strartproc);
KillTimer(STARTID);
//////////////上面都是教案中的内容,下面是我记录的内容/////////
在窗口上添加一个复选框CheckBox,设置为自动开局,再关联两个变量
M_autoplay&/&M_autostart
为了运用这两个变量在函数中,又重新调整了一下头llk_wgDlg.cpp中的函数,都是在定义全局变量/标识符一类的代码调整,对我这个没有VC++基础的人来讲,有点看不懂.
这是添加复选框后的界面
在”自动挂机”和”自动开局”中添加如下代码
const&PLAYID=111;//定义一个数值方便调用,不要重复
&const&STARTID=112;//可以随便取数,不要重复
void&CLlk_wgDlg::OnCheck1()&//如果复选框被选中则执行
//&TODO:&Add&your&control&notification&handler&code&here
UpdateData(true);//更新窗口内容至变量
if&(m_autoplay)//如果变量被设置则运行
SetTimer(PLAYID,1500,&playproc);//自动挂机
KillTimer(PLAYID);//关掉定时器,不执行回调函数
void&CLlk_wgDlg::OnCheck2()&
//&TODO:&Add&your&control&notification&handler&code&here
UpdateData(true);//更新窗口内容至变量
if&(m_autoplay)&//如果变量被设置则运行
SetTimer(STARTID,3*1000,&strartproc);//自动开局
}&else//如果没有被选中的话
KillTimer(STARTID);
代码我做了比较多的注释,基本上像我这样的新手都能理解了.我发现VC++与DELPHI在编写代码上确实存在很多不同之处,比如在时间的设置上,DELPHI中是加入时间控件,而VC++中却是添加&了一个函数SetTimer,感觉有点不太习惯,但人家说了,VC++是专业人员用的,这就代表着专业呗&^_^
&今天我们要一起学习的是1.3.8
&&1.3.8&&游戏外挂界面美化
&&&&&&&&&&&&&a、添加进度条
&&&&&&&&&&&&&b、界面调整
&&&&&&&&&&&&&c、Slider控件属性设置
BOOL&MoveWindow(
&&HWND&hWnd,&&&&&&//&窗口句柄
&&int&X,&&&&&&&&&&//&水平坐标X
&&int&Y,&&&&&&&&&&//&垂直坐标Y
&&int&nWidth,&&&&&//&宽度
&&int&nHeight,&&&&//&高度
&&BOOL&bRepaint&&&//&是否重画窗口&true,false
//::MoveWindow(this-&m_hWnd,0,0,330,200,true);
MoveWindow(0,0,330,200,true);
&&滑块(slider)
&&&&void&SetTicFreq(int&nFreq);
&&&&int&GetPos()&
&&&&void&SetRange(int&nMin,&int&nMax,&BOOL&bRedraw&=&FALSE);
MoveWindow(0,0,330,200,true);
this-&m_ctl_slider.SetRange(50,3000);&//设置滑块的&最小值&最大值
this-&m_ctl_slider.SetTicFreq(150);&&&//分隔线&宽度
this-&m_ctl_slider.SetPos(1000);&&&&&&//滑块&位置
this-&m_ctl_check.SetCheck(true);&&&&//选中复选框
//////////////////////////////
这节课是要界面美化,因为前期的核心代码已经编写了.更改界面,要删除一些不用的控件,因为控件与代码是关联的,所以一个懒办法就是将不用的控件移到窗口外面,这样就看不到了.
如果对窗口的调整还不满意,就用编程来实现,因为用代码设置窗口及控件大小最精确了.注意MoveWindow函数,如果是全局使用则是6个参数,局部使用就是5个参数
再给滑块条设置一下分隔线:建立控件变量m_ctl_slider,然后查看一下该变量的定义,用于参考代码写法,这几个就是滑块的类成员函数
&&滑块(slider)
&&&&void&SetTicFreq(int&nFreq);
&&&&int&GetPos()&
&&&&void&SetRange(int&nMin,&int&nMax,&BOOL&bRedraw&=&FALSE);
设置好手放在窗口的初始化处,也就是llk_wgDlg.cpp里的
BOOL&CLlk_wgDlg::OnInitDialog()&函数
这样在启动时就会设置好控件样式
在MoveWindow(0,0,330,200,true);下面添加代码
this-&m_ctl_slider.SetRange(50,3000);&//设置滑块的&最小值&最大值
this-&m_ctl_slider.SetTicFreq(150);&&&//分隔线&宽度
this-&m_ctl_slider.SetPos(1000);&&&&&&//滑块&位置
用编辑框测试一下滑块,调整好样式.
再设置一下”挂机速度调节”复选框来开启/关闭&滑块功能
这个需要先建立一个BOOL类型的变量m_sliderenable&来进行控制,添加代码如下
void&CLlk_wgDlg::OnCheck3()&
//&TODO:&Add&your&control&notification&handler&code&here
UpdateData(true);
::EnableWindow(m_ctl_slider.m_hWnd,m_sliderenable);//通过这个复选框来控制滑块条是否可用
还要设置这个挂机速度调节初始默认为开启,还需要在该控件中建立一个变量m_ctl_check
最终的代码设置如下
在MoveWindow(0,0,330,200,true);下面添加代码
this-&m_ctl_slider.SetRange(50,3000);&//设置滑块的&最小值&最大值
this-&m_ctl_slider.SetTicFreq(150);&&&//分隔线&宽度
this-&m_ctl_slider.SetPos(1000);&&&&&&//滑块&位置
this-&m_ctl_check.SetCheck(true);&&&&//选中复选框
设置的代码都在上面的教案里.感觉VC++的MFC不如DELPHI的窗体/控件用着方便,而且是非常的麻烦,当然也有的人用BCB,可能也是这个原因.
&今天我们要一起学习的是1.3.9
&&1.3.9&倒计时与棋子数(基址查找)
&&&&&&&&&&&&&a、查找棋子数&&//为了优化&自动开局&
&&&&&&&&&&&&&b、查找倒计时&&//这个倒计时有点讨厌,去掉它
&&&&&&&&&&&&&c、开局的标志:
&&1、棋子数:$
&&&&1Byte,变更棋子数&:扫描类型&:精确数值
&&2、倒计时基址:$查找
&&&t=t-n;&//3000-10;
&1、棋子数:&&&&$&//没开局之前&0,&开局之后&大于0
&2、倒计时基址:$&&//毫秒
&3、开局的标志:01C3A7B4,01C4EF74,01C61F9C,01C84CF4&//boolean
///////////////////////////
前面的代码虽然可以自动下棋了,但是有关于自动开局这里还不智能,所以要增加一个棋子数的判断,当棋子为空时就要点击”开始”按钮,多找几次就找到了剩余棋子数的地址.同时为了丰富功能,还要查找倒计时功能,将倒计时去掉.而倒计时是个进度条,没有确切的数值,所以我们只好猜测,假设未开局时是0,如果刚一开始的时候估计其值可能会大于100,然后再查找不断减少的数值,最后走完就是0,注意这个值是4字节的.
找到了这两个数值我们如何做呢?可以将倒计时的数值锁定,或者将其时间控件给去掉;棋子数是我们用来监测是否在开局中,那么我们再来查找一下在游戏中是否有开局的数值,我们猜测未开局时是0,开局后是1,因为这都是编程时的真与假的设置
本节课是CE工具的经典使用
&今天我们要一起学习的是1.4.1
1.4.1&优化自动开局函数StartGame&
&&&&&&&&&&&&&a、让游戏窗口高高在上
&&&&&&&&&&&&&b、优化开局函数
参考&1.3.9&
&&&&3、开局的标志:01C3A7B4,01C4EF74,01C61F9C,01C84CF4&//开局&时为1&未开局为0
int&//这个值为0时&执行&StartG
&HWND&gameh=::FindWindow(NULL,gameCaption);
&//AfxMessageBox(&Findwindow&);
if&(gameh==0)&{&}&//没有找到游戏窗口
//让游戏窗口置顶
SetWindowPos(gameh,HWND_TOP,0,0,0,0,SWP_NOMOVE&|&SWP_NOSIZE&|&SWP_SHOWWINDOW);
//AfxMessageBox(&GetWindowThreadProcessId&);
::GetWindowThreadProcessId(gameh,&pid);
long&flag,byReadS
HANDLE&hp=OpenProcess(PROCESS_ALL_ACCESS,false,pid);
::ReadProcessMemory(hp,(LPCVOID)(0x01C3A7B4),(LPVOID)(&flag),4,(LPDWORD)&(&byReadSize));
if&(byReadSize==0)&{AfxMessageBox(&未成功读出数据&);}
if&((flag==0)&&(byReadSize&0))&{&startGame();}&//自动开局
////////////////////////////////
将上节课中找到的游戏开局4个地址写入代码中,写在计时器的回调函数里
在这个函数里
VOID&CALLBACK&strartproc(
&&HWND&hwnd,&&&&&//&handle&of&window&for&timer&messages
&&UINT&uMsg,&&&&&//&WM_TIMER&message
&&UINT&idEvent,&&//&timer&identifier
&&DWORD&dwTime&&&//&current&system&time
添加如下代码
{&&&HWND&gameh=::FindWindow(NULL,gameCaption);
if&(gameh==0)&{&}&//没有找到游戏窗口
//让游戏窗口置顶,最后参数是忽略掉前面的参数
SetWindowPos(gameh,HWND_TOP,0,0,0,0,SWP_NOMOVE&|&SWP_NOSIZE&|&SWP_SHOWWINDOW);
DWORD&//建立进程ID变量
::GetWindowThreadProcessId(gameh,&pid);//通过窗口找进程ID,参数1窗口句柄,参数2得到的ID
long&flag,byReadS//定义变量用于指针
HANDLE&hp=OpenProcess(PROCESS_ALL_ACCESS,false,pid);//打开线程,参数1为打开权限,参数2为进程派生,参数3为打开句柄ID
::ReadProcessMemory(hp,(LPCVOID)(0x01C3A7B4),(LPVOID)(&flag),4,(LPDWORD)&(&byReadSize));//读取内存,参数1进程句柄,参数2被读进程指针,参数3保存数据指针,参数4读取字节浸透,参数5实际字节数
if&(byReadSize==0)&{AfxMessageBox(&未成功读出数据&);}//检测数据是否读出
if&((flag==0)&&(byReadSize&0))&{&startGame();}&//自动开局
这节课老师改了很长时间的代码,看来VC编程确实不容易,连老手都需要多次做测试,哎~&凭我的水平,我想我只要能读懂VC代码就行了,真正写的时候还是用DELHPI吧.
&今天我们要一起学习的是1.4.2
1.4.2&去掉游戏倒计时限制&&
&&&&&&&&&&&&&a、找到计时代码
&&&&&&&&&&&&&b、动态修改游戏代码(OD使用初探)
&&&&&&&&&&&&&c、去掉计时限制&&&&&&
参考:1.3.9
&&2、倒计时基址:$&&//秒
&分析写入&倒计时的代码:&&&
0042646d:mov&[eax+],edx&//初始化&倒计时的值
:mov&[eax+],ecx&//更新&倒计时的值&=减1
byte&acode[6]={0x90,0x90,0x90,0x90,0x90,0x90};//要将代码NOP掉
bool&ClearCode()
&HWND&gameh=::FindWindow(NULL,gameCaption);
if&(gameh==0)&{&}&//没有找到游戏窗口
::GetWindowThreadProcessId(gameh,&pid);
long&byWriteS
HANDLE&hp=OpenProcess(PROCESS_ALL_ACCESS,false,pid);
::WriteProcessMemory(hp,(LPCVOID)(0x),(LPVOID)(acode),6,(LPDWORD)&(&byWriteSize));//写入NOP代码
///////////////////////////////////////////
先将写入倒计时找到,用OD附加游戏,来到修改倒计时的汇编代码处,多试几次,看看哪行代码是关键的?试试将关键代码NOP掉看看
也就是在这里连续写入6个90的数值,90就是NOP,也就是空操作.接下来在VC里编写代码,让咱们的外挂自己修改游戏的关键地址为6个90,代码已经在教案里了(上面的蓝字)
至于写入的函数WriteProcessMemory的参数,与ReadProcessMemory函数的参数是一样的,只是读出字节数和写入字节数的区别(详细附后).
再新增一个复选框”去掉游戏倒计时”,用来开启修改掉倒计时代码
void&CLlk_wgDlg::OnCleartimer()&
//&TODO:&Add&your&control&notification&handler&code&here
if&(ClearCode())&{m_ctl_cleartime.EnableWindow(false);}&//禁用它
else&{&m_ctl_cleartime.SetCheck(false);}
WriteProcessMemory&函数原型:&
  Declare&Function&WriteProcessMemory&Lib&&kernel32&&(ByVal&hProcess&As&Long,&ByVal&lpBaseAddress&As&Any,&ByVal&lpBuffer&As&Any,&ByVal&nSize&As&Long,&lpNumberOfBytesWritten&As&Long)&As&Long&
  作用:写内存&
  说明:&
  hProcess&,&进程的句柄&
  lpBaseAddress,&写入进程的位置(地址)&
  lpBuffer,&数据当前存放地址&
  nSize,&数据的长度&
  lpNumberOfBytesWritten,实际数据的长度&
  nSize以字节为单位,一个字节Byte等于8位&
  基本数据类型的长度&
  ShortInt&8位&=&1Byte&
  SmallInt&16位&=&2Byte&
  Integer&16位&=&2Byte&
  LongInt&32位&=&4Byte&
  Word&16位&=&2Byte&
  LongWord&32位&=&4Byte&
  Boolean&8位&=&1Byte&
  WordBool&16位&=&2Byte&
  LongBool&32位&=&4Byte&
  比如要写入Integer类型的数据,那么Integer长度2Byte&
  所以nSize&=&2
&今天我们要一起学习的是1.4.3
&1.4.3&编写完整外挂&
&&&&&&&&&&&&a、功能测试
&&&&&&&&&&&&b、修改完善外挂
秒杀:&1、棋子数:&&&&$&//没开局之前&0,&开局之后&大于0
int&chessnum=ReadChessNum();
void&KillAll()//秒杀
//&TODO:&Add&your&control&notification&handler&code&here
while&(chessnum!=0)
ClearPiar();
//Sleep(1);&//0x&棋子数=0时退出
chessnum=ReadChessNum();
int&ReadChessNum()&//读出当前&棋子数
//&TODO:&Add&your&control&notification&handler&code&here
//获取窗口句柄
HWND&gameh=::FindWindow(NULL,gameCaption);
//获取窗口进程ID
::GetWindowThreadProcessId(gameh,&processid);
//打开指定进程
HANDLE&processH=::OpenProcess(PROCESS_ALL_ACCESS,false,processid);
//读指定进程&内存数据
&&&&DWORD&
LPCVOID&pbase=(LPCVOID)0x&;&//棋子数据基址
int&ChessN
LPVOID&&nbuffer=(LPVOID)&ChessN&&&&//存放棋子数据
::ReadProcessMemory(processH,pbase,nbuffer,4,&byread);
return&ChessN
////////////////////////////////////////
再继续完善我们之前的代码,修改一下窗口置顶的代码,因为置顶的选项里没有关联变量,所以不能控制该选项框,新增一个变量m_gametop&,然后再加入代码
void&CLlk_wgDlg::OnGameTop()&
UpdateData(true);&//更新窗口数据至变量
gametop=m_
if( m_gametop)//当变量值为真时则置顶
HWND&gameh=::FindWindow(NULL,gameCaption);&&
&&&&&&&&&if&(gameh==0)&{&}&//没有找到游戏窗口
&&&&&&&&&&&//让游戏窗口置顶
&&::SetWindowPos(gameh,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE&|&SWP_NOSIZE&|&SWP_SHOWWINDOW);&//窗口置顶函数
&&&else&//如果没有窗口被找到
&&&HWND&gameh=::FindWindow(NULL,gameCaption);&&
&&&&&&&&&if&(gameh==0)&{&}&//没有找到游戏窗口
&&&&&&&&&&&&::SetWindowPos(gameh,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE&|&SWP_NOSIZE&|&SWP_SHOWWINDOW);&//取消置顶
再继续添加棋子数功能void&CLlk_wgDlg::OnClearAll()&函数在上面教案里,这个就是秒杀功能.但是还需要读出棋子数,函数是int&ReadChessNum(),在上面教案里.然后再调整一下秒杀功能.然后再调整一下置顶功能,
//让游戏窗口置顶
if&(gametop)//新建的变量方便设置
&{//选中则置顶
SetWindowPos(gameh,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE&|&SWP_NOSIZE&|&SWP_SHOWWINDOW);
&{//未选中则不置顶
&SetWindowPos(gameh,HWND_TOP,0,0,0,0,SWP_NOMOVE&|&SWP_NOSIZE&|&SWP_SHOWWINDOW);
今天我们要一起学习的是1.4.4
&1.4.4&初级篇小结&
&&&&&&&&&&&&a、游戏分析小结
&&&&&&&&&&&&b、编程小结
1、GetWindowRect//窗口信息的获取
BOOL&GetWindowRect(
&&HWND&hWnd,&&&&&&//&handle&to&window
&&LPRECT&lpRect&&&//&存放返回值的首地址&RECT
2、SetCursorPos//设置鼠标指针
BOOL&SetCursorPos(
&&int&X,&&//X
&&int&Y&&&//Y
3、mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//硬件模拟鼠标
4、FindWindow&&&&&&&&&&&&&&&//获取窗口句柄
HWND&FindWindow(
&&LPCTSTR&lpClassName,&&//窗口类名&NULL
&&LPCTSTR&lpWindowName&&//窗口标题&NULL
5、GetWindowThreadProcessId&//获取窗口进程ID
DWORD&GetWindowThreadProcessId(
&&HWND&hWnd,&&&&&&&&&&&&&//&handle&to&window
&&LPDWORD&lpdwProcessId&&//&指向变量的指针&用来返回进程PID
6、OpenProcess&&&&&&&&&&&&&&//打开指定进程
HANDLE&OpenProcess(
&&DWORD&dwDesiredAccess,&&//&访问权限&标记
&&BOOL&bInheritHandle,&&&&//&
&&DWORD&dwProcessId&&&&&&&//&lpdwProcessId&&进程ID标识
7、ReadProcessMemory&&&&&&&&//读指定进程&内存数据
BOOL&ReadProcessMemory(
&&HANDLE&hProcess,&&//&&HANDLE&OpenProcess返回值
&&LPCVOID&lpBaseAddress,
&&&&&&&&&&&&&&&&&&&&//&读取&进程起始地址&基址
&&LPVOID&lpBuffer,&&//&存放数据的缓冲区
&&DWORD&nSize,&&&&&&//&要读出的字节数
&&LPDWORD&lpNumberOfBytesRead&
&&&&&&&&&&&&&&&&&&&&//&实际读出字节数
8、WriteProcessMemory&&&//写内存,参数同读内存
9、SendMessage&//可以软模拟&鼠标&键盘操作
10、SetTimer&
UINT&SetTimer(
&&HWND&hWnd,&&&&&&&&&&&&&&//&指向窗口的句柄
&&UINT&nIDEvent,&&&&&&&&&&//&定时器&标识ID
&&UINT&uElapse,&&&&&&&&&&&//&时间间隔(毫秒)&
&&TIMERPROC&lpTimerFunc&&&//回调函数
VOID&CALLBACK&TimerProc(
&&HWND&hwnd,&&&&&//&handle&of&window&for&timer&messages
&&UINT&uMsg,&&&&&//&WM_TIMER&message
&&UINT&idEvent,&&//&timer&identifier
&&DWORD&dwTime&&&//&当前系统时间
11、KillTimer()
BOOL&KillTimer(
&&HWND&hWnd,&&&&&&//&指向窗口的句柄
&&UINT&uIDEvent&&&//&定时器&标识ID
12、SetWindowPos&//HWND_TOPMOST&窗口置顶
CButton&slider//滑块控件
this-&m_ctl_slider.SetRange(50,3000);&//设置滑块的&最小值&最大值
this-&m_ctl_slider.SetTicFreq(150);&&&//分隔线&宽度
this-&m_ctl_slider.SetPos(1000);&&&&&&//滑块&位置
//复选框控件
this-&m_ctl_check.SetCheck(true);&&&&//选中复选框
a、数据类型:Bit,Byte,Word,Dword,float,double
b、用CE查找数据
c、CE工具使用技巧
///////////////////////////////
本节课是老师对于前面内容的总结,教案写的很详细了.
老师总结,我也总结.初级班的课程我已经全部看完了,&相对于DELPHI班来讲记录的也比较仔细,相信我的记录能够帮助其它同学和网友,其实记录主要就是记一下课程的内容,方便以后回忆学习.总体来讲,VC班的初级教程内容比较多,相对于DELPHI班初级教程来讲,游戏也复杂了些,编写代码就更加复杂,就算是有DELPHI基础,想学起VC代码来我也感觉到非常吃力.不过我也觉着这个学习的顺序是对的,如果一开始就学VC,那恐怕我就没有信心了.想起自己在D班里的感想,弄外挂,编程会则可成.
VC++真的很难懂,看来我要参考其它VC教程来学习了.
Visual&C++从入门到精通完整版视频教程&&
VC视频教程(太平洋)
[视频]思成VC讲座
孙鑫VC视频教程[下载]
今天我们要一起学习的是2.1.1
&&&2.1.1、CALL的概念(远程调用CALL)
&&&&&&&&&&&&&&&&a、写个调用示例(假想游戏客户端)
&&&&&&&&&&&&&&&&b、用OD找CALL,初探(用OD找出我们自己写的CALL)
&&&&&&&&&&&&&&&&c、代码注入器,远程CALL调用
1、先写一个假想的游戏客户端.
&//VC++
&SetWindowText(h,&窗口标题&);
char&s[33];
itoa(BoolValue,s,10);//整型&转字串
m_edt1.SetWindowText(s);
//找加血CALL&
1//CE找的&血值&基址:416680
2&OD硬件&断点&hw&416680
3&//代码注入器
call&402360&//加血
call&4023d0&//减血&40108c
call&&40108c&&//减血
HANDLE&CreateRemoteThread(
&&HANDLE&hProcess,&&&&&&&&//&OpenProcess
&&LPSECURITY_ATTRIBUTES&lpThreadAttributes,&&//&安全结构指针&NULL
&&DWORD&dwStackSize,&&&&&&//&0
&&LPTHREAD_START_ROUTINE&lpStartAddress,&//&指向我们的CALL&地址
&&LPVOID&lpParameter,&&&&&//&传递的参数指针&NULL
&&DWORD&dwCreationFlags,&&//&0
&&LPDWORD&lpThreadId&&&&&&//&返回一个&线程ID标识
//////////////////////////////////
首先讲一下CALL的基本知识,在VC里新建一个窗口,并增加编辑框,关联一个控件类型的变量m_edt1
int&BoolValue=3000;//新建一个血值,假设为3000
HWND&edit_&//设置全局变量
然后添加如下代码
void&addBlood()//加血代码
char&s[33];&//建立缓冲变量
BoolValue+=22;//每次加22血
itoa(BoolValue,s,10);&//整型转换为10进制字符串
SetWindowText(edit_hwnd,s);&//设置编辑框数值
void&decBlood()//减血代码
char&s[33];
BoolValue-=22;
itoa(BoolValue,s,10);
SetWindowText(edit_hwnd,s);
那么我们就要用CE来查找这个加血和减血按钮的CALL,打开CE,搜索一下当前的血值,再改变一下血值再搜索,如果找到的地址是绿色的,那么就证明其值是全局变量,也就是一级基址/主基址,改变一下血值,就找到其地址了,那么我们在OD里下一个内存断点&Hw&416680&,&被断下之后在位置,向上看,我们来到函数的头部,也就是上面全是int&3的第一句那么我们找到的加血的CALL就是402360.
打开代码注入器,输入&&call&402360&&&发现确实加血了
同理,再查找出减血的&CALL&4023d0&
当然除此之外,在此函数头部的上一句是一个JMP语句,而这句也可以调用
最后又讲了一下CreateRemoteThread创建线程函数的用法,参数在上面教案里有详解.
本节课讲了CALL的基础,通过自己编写的一个小程序,让大家明白怎么样查找CALL和调用CALL
&今天我们要一起学习的是2.1.2
&&&2.1.2、远程CALL调用代码实现
&&&&&&&&&&&&&&&&a、CreateRemoteThread&API函数
&&&&&&&&&&&&&&&&b、无参数的远程CALL调用(代码实现)&
1、先写一个假想的游戏客户端.
call&402360&//加血
call&4023d0&//减血&40108c
call&&40108c&&//减血
HANDLE&CreateRemoteThread(
&&HANDLE&hProcess,&&&&&&&&//&OpenProcess
&&LPSECURITY_ATTRIBUTES&lpThreadAttributes,&&//&安全结构指针&NULL
&&DWORD&dwStackSize,&&&&&&//&0
&&LPTHREAD_START_ROUTINE&lpStartAddress,&//&指向我们的CALL&地址
&&LPVOID&lpParameter,&&&&&//&传递的参数指针&NULL&(stdcall)
&&DWORD&dwCreationFlags,&&//&0
&&LPDWORD&lpThreadId&&&&&&//&返回一个&线程ID标识&int&=(LPDWORD)&&
HWND& h=FindWindow(NULL,&Mygame&);
DWORD&LPDWORD&pid=&
GetWindowThreadProcessId(h,Pid);
HANDLE&&hp=OpenProcess(PROCESS_ALL_ACCESS,false,Pid);
CreateRemoteThread(hp,NULL,0,&(LPTHREAD_START_ROUTINE)(0x402360&)&&,NULL,0,&tid);
//////////////////////////////////////////////
上节课我们是用的代码注入器来调用的CALL,那么这次我们自己编写代码来调用CALL,这需要几个函数的联合运用,参数的详解在上面的教案中.
1,&FindWindow
2,&GetWindowThreadProcessId
3,&OpenProcess
4,&CreateRemoteThread
新建一个窗口
具体的调用代码如下:
void&RemoteCall(int&CallAddr)//整理出来的CALL调用函数
HWND&&&&&&&&&//窗口变量
h=::FindWindow(NULL,&Mygame&);&//查找窗口句柄需要全局标识符
DWORD&&&&&&&&&//进程ID
LPDWORD&Pid=&&//定义临时变量方便调用
::GetWindowThreadProcessId(h,Pid);&//取得指定窗口的进程ID&存放到变量id里边
HANDLE&&hp=OpenProcess(PROCESS_ALL_ACCESS,false,id);//获取访问进程权限&存放至hp
DWORD&&&&&&&&//定义临时变量方便调用
//在进程里调用&CallAddr
CreateRemoteThread(hp,NULL,0,(LPTHREAD_START_ROUTINE)CallAddr&,NULL,0,&tid);
void&CCALLDlg::OnRemoteAdd()&//加血调用
RemoteCall(0x402360);&//加血CALL&&&16进制写法
void&CCALLDlg::OnBTNDecBlood()&//减血调用
RemoteCall(0x40108c&);//减血CALL&&&16进制写法
备注:LPTHREAD_START_ROUTINE&指向的函数是回调函数,并且必须由宿主应用程序的编写器实现。
因为我有DELPHI基础,上面的4个函数我在DELPHI当中可是经常用,所以很熟悉,我只需要了解VC中的写法即可
&2.1.3、调试工具OD简介(人物角色)血值,魔力值;
&&&&&&&&&&&&&&&&a、CE找出当前血值偏移
&&&&&&&&&&&&&&&&b、OD&分析出魔力值&
&&&&&&&&&&&&&&&&c、导出游戏关键代码&
血值&基址&0x45657F0
&&&&&&&+4:&魔力值
&&&&&&&+8:&持久力&
&&&&&&&+C:血值上限
&&&&&&&+10:魔力值上限
&&&&&&&+14:持久力上限&1000
&&&&&&&+1C:善恶度
&&&&&&&+18:当前经验值
&&&&&&&+20:升级到下一级所需经验值
&&&&&&&+24:&灵兽&持有数量&上限2
&&&&&&&+2C:历练值
&&&&&&&+30:心
&&&&&&&+34:力
&&&&&&&+38:体
&&&&&&&+3C:身
//////////////////////////////////////////
终于要正式搞游戏了,下载RXJH吧,首先从血值入手,用CE查找当前的血&#,打两下怪,再CE查找当前的血&#,再吃点药,又变成631了,继续用CE一搜就找到了,基址都是绿色的,当前搜索到的值不是绿色,那么这就是一个变量的值,还好我们找到了一个绿色地址
再用OD附加一下,确定此位置,显示一下内存区域
通过猜测,我们找到了相关的血值上限和蓝值等,详细在上面的教案中.但是我们需要找到一级基址,我们在血值处下一个断点,被断在0058

我要回帖

更多关于 全局出击和刺激战场 的文章

 

随机推荐