>_< : 这里用SetTimer函数自动运行![注意添加在里面的回掉函数函数]
1 UINT SetTimer( 2 HWND hWnd, // 指向窗口句柄 3 UINT nIDEvent, // 时钟标识 4 UINT uElapse, // 时间间隔 (毫秒) 5 TIMERPROC lpTimerFunc // 指向回调函数的地址 6 ); 7 8 KillTimer(UINT nIDEvent); // 时钟标识 9 10 VOID CALLBACK playproc( 11 HWND hwnd, // handle of window for timer messages 12 UINT uMsg, // WM_TIMER message 13 UINT idEvent, // timer identifier 14 DWORD dwTime // current system time 15 ) 16 { 17 A();//SetTimer里的回掉函数
18 } 19 VOID CALLBACK strartproc( 20 HWND hwnd, // handle of window for timer messages 21 UINT uMsg, // WM_TIMER message 22 UINT idEvent, // timer identifier 23 DWORD dwTime // current system time 24 ) 25 { 26 B();
27 }
>_< : 在窗口上添加一个复选框CheckBox,设置为自动开局,再关联两个变量m_autoplay / m_autostart
1 //----------------------------------------------------------------------------- 2 void OnStartGame(int x,int y) 3 { 4 HWND gameh;//游戏窗口句柄 5 RECT r1;//RECT结构表示一个矩形区域 6 POINT p;//x,y 7 8 gameh=::FindWindow(NULL,"井字棋"); 9 ::GetWindowRect(gameh,&r1); 10 11 GetCursorPos(&p);//保存当前鼠标指针 //取得当前鼠标位置 12 SetCursorPos(x+r1.left,y+r1.top);//当前窗口坐标+开局按钮坐标 13 14 mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//鼠标在当前位置按下 15 mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//鼠标在当前位置抬起 16 mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0); 17 18 Sleep(200);//过一段时间 再执行后边的代码 19 SetCursorPos(p.x,p.y); //还原鼠标位置 20 } 21 //--------------------------------------------------------------------------- 22 int chessdata[3][3];//a[y][x]棋盘状态0-1-2 23 int win[2][8];//PC和外挂在8种情况下的棋子数 24 bool ptab[9][8]; //电脑的获胜的状态表 25 bool ctab[9][8]; //外挂的获胜的状态表 26 27 void init() 28 { 29 int count=0,i,k; 30 //设定外挂与计算机在各个获胜组合中的棋子数 31 for(i=0;i<8;i++) 32 { 33 win[0][i]=0; 34 win[1][i]=0; 35 } 36 37 38 //设定水平方向的获胜组合 39 for(i=0;i<=6;i+=3) 40 { 41 for(k=0;k<3;k++)//3个棋子1个获胜组合 42 { 43 ptab[i+k][count]=true; 44 ctab[i+k][count]=true; 45 } 46 count++; 47 } 48 //设定垂直方向的获胜组合 49 for(k=0;k<3;k++) 50 { 51 for(i=0;i<=6;i+=3)//3个棋子1个获胜组合 52 { 53 ptab[i+k][count]=true; 54 ctab[i+k][count]=true; 55 } 56 count++; 57 } 58 //设定对角线方向上的获胜组合 59 for(i=2;i<=6;i+=2){ 60 ptab[i][count]=true; 61 ctab[i][count]=true; 62 }count++; 63 for(i=0;i<=8;i+=4){ 64 ptab[i][count]=true; 65 ctab[i][count]=true; 66 } 67 } 68 void reup()//根据棋盘状态更新胜利表、外挂、电脑表 69 { 70 for(int i=0;i<3;i++){ 71 for(int j=0;j<3;j++){ 72 if(chessdata[i][j]==2){ 73 //改变胜利表和各外挂、PC各胜利组合的棋子数 74 for(int k=0;k<8;k++){ 75 if(ptab[i*3+j][k]){ 76 win[0][k]++; 77 ctab[i*3+j][k]=false; 78 win[1][k]=5; 79 } 80 } 81 }else if(chessdata[i][j]==1){ 82 //改变胜利表和各外挂、PC各胜利组合的棋子数 83 for(int k=0;k<8;k++){ 84 if(ptab[i*3+j][k]){ 85 win[1][k]++; 86 ptab[i*3+j][k]=false; 87 win[0][k]=5; 88 } 89 } 90 } 91 } 92 } 93 } 94 int getPos()//获取该下棋位置 95 { 96 int grades[2][9]; 97 int m,i,max=0; 98 int u; 99 100 for(m=0;m<9;m++){ 101 grades[0][m]=0; 102 grades[1][m]=0; 103 104 if( chessdata[m/3][m%3]==0){ 105 for(i=0;i<8;i++){ 106 //计算PC在空棋格上的获胜分数 107 if(ptab[m][i] && win[0][i]!=5){ 108 switch(win[0][i]){ 109 case 0: 110 grades[0][m]+=1; 111 break; 112 case 1: 113 grades[0][m]+=2000; 114 break; 115 case 2: 116 grades[0][m]+=10000; 117 break; 118 } 119 } 120 121 //计算外挂在空格上的获胜分数 122 if(ctab[m][i] && win[1][i]!=5){ 123 switch(win[1][i]){ 124 case 0: 125 grades[1][m]+=1; 126 break; 127 case 1: 128 grades[1][m]+=2001; 129 break; 130 case 2: 131 grades[1][m]+=10001; 132 break; 133 } 134 } 135 } 136 137 if(max==0)u=m; 138 139 if(grades[0][m]>max){ 140 max=grades[0][m]; 141 u=m; 142 } 143 else if(grades[0][m]==max){ 144 if(grades[1][m]>grades[1][u])u=m; 145 } 146 147 if(grades[1][m]>max){ 148 max=grades[1][m]; 149 u=m; 150 } 151 else if(grades[1][m]==max){ 152 if(grades[0][m]>grades[0][u])u=m; 153 } 154 } 155 } 156 return u; 157 } 158 void play_zidong() 159 { 160 HWND gameh=::FindWindow(NULL,"井字棋");//获取窗口句柄 161 //获取窗口进程ID 162 DWORD processid; 163 ::GetWindowThreadProcessId(gameh,&processid); 164 HANDLE processH=::OpenProcess(PROCESS_ALL_ACCESS,false,processid);//打开指定进程 165 166 //读指定进程 内存数据 167 DWORD byread; 168 LPCVOID pbase=(LPCVOID)0x014D507C; //棋盘数据基址 169 LPVOID nbuffer=(LPVOID)&chessdata; //存放棋盘数据 170 ::ReadProcessMemory(processH,pbase,nbuffer,3*3*4,&byread);//进程句柄|基址|存放数据缓冲区|要读取数据的字节数|实际读取的字节数 171 172 //算法部分:自动走下一步 173 init(); 174 reup(); 175 int pos=getPos(); 176 177 //鼠标点击 178 int x=50+pos%3*100,y=50+pos/3*100; //定义座标点 179 int lparam; //定义座标点变量 180 lparam=(y<<16)+x; //表示指定格,Y<<16是左移16位,发消息用的Y座标点 181 ::SendMessage(gameh,WM_LBUTTONDOWN,0,lparam);//鼠标按下消息 182 ::SendMessage(gameh,WM_LBUTTONUP,0,lparam); //鼠标抬起消息 183 } 184 void CFewDlg::OnButton5() 185 { 186 play_zidong(); 187 } 188 //------------------------------------------------------------------------------------- 189 VOID CALLBACK CFewDlg::playproc( 190 HWND hwnd, // handle of window for timer messages 191 UINT uMsg, // WM_TIMER message 192 UINT idEvent, // timer identifier 193 DWORD dwTime // current system time 194 ) 195 { 196 play_zidong(); 197 } 198 VOID CALLBACK CFewDlg::strartproc( 199 HWND hwnd, // handle of window for timer messages 200 UINT uMsg, // WM_TIMER message 201 UINT idEvent, // timer identifier 202 DWORD dwTime // current system time 203 ) 204 { 205 OnStartGame(200,200);//自动开局 206 } 207 208 const PLAYID=111;//定义一个数值方便调用,不要重复 209 const STARTID=112;//可以随便取数,不要重复 210 void CFewDlg::OnCheck1() 211 { 212 UpdateData(true);//更新窗口内容至变量 213 if (m_autoplay){//如果变量被设置则运行 214 SetTimer(PLAYID,1500,&playproc);//自动挂机 215 }else{ 216 KillTimer(PLAYID);//关掉定时器,不执行回调函数 217 } 218 } 219 void CFewDlg::OnCheck2() 220 { 221 UpdateData(true);//更新窗口内容至变量 222 if (m_autoplay){//如果变量被设置则运行 223 SetTimer(STARTID,3*1000,&strartproc);//自动开局 224 }else{//如果没有被选中的话 225 KillTimer(STARTID); 226 } 227 }