[外挂7] 井字棋外挂 博弈算法

 

 

>_<:本次是综合以上的学习,然后加入博弈算法,来实现井字棋的外挂[井字棋代码可以在[软件项目]里找到!]

>_<:首先还是要加一个按钮:即[自动对战]button5

 

>_<:这里包括博弈算法的初始函数init(),根据游戏状态表更新博弈计算相关表的函数reup(),还有博弈主体部分getPos()来获得下棋位置,然后在button-5的监听里模拟鼠标点击

>_<:这里简单说一下该算法里的博弈思想:

  1. win[2][8]分别保存计算机和外挂8种胜利情况的棋子数,如果值为5则表示此种情况不能胜利
  2. ptab[9][8]表示电脑第i号棋子在第j号胜利情况下是否有效
  3. ctab[9][8]表示外挂第i号棋子在第j号胜利情况下是否有效
  • init()函数中主要将各组合状态的棋子数归零,将横竖对角线8种获胜情况置有效
  • reup()函数中主要根据当前棋盘状态,更新每种组合状态的棋子数及电脑和外挂对应棋子在对应胜利情况的有效性更新
  • getPos()函数中主要分别计算每个可以下棋的点对电脑和外挂的获胜权值来选择下棋的位置,注意这里相同情况下外挂的权值稍高

 

  1 int chessdata[3][3];//a[y][x]棋盘状态0-1-2
  2 int win[2][8];//PC和外挂在8种情况下的棋子数
  3 bool ptab[9][8];            //电脑的获胜的状态表
  4 bool ctab[9][8];            //外挂的获胜的状态表
  5 
  6 void init()
  7 {    
  8     int count=0,i,k;
  9     //设定外挂与计算机在各个获胜组合中的棋子数
 10     for(i=0;i<8;i++)
 11     {
 12         win[0][i]=0;
 13         win[1][i]=0;
 14     }
 15 
 16 
 17     //设定水平方向的获胜组合
 18     for(i=0;i<=6;i+=3)
 19     {
 20         for(k=0;k<3;k++)//3个棋子1个获胜组合
 21         {
 22             ptab[i+k][count]=true;
 23             ctab[i+k][count]=true;
 24         }
 25         count++;
 26     }
 27     //设定垂直方向的获胜组合
 28     for(k=0;k<3;k++)
 29     {
 30         for(i=0;i<=6;i+=3)//3个棋子1个获胜组合
 31         {
 32             ptab[i+k][count]=true;
 33             ctab[i+k][count]=true;
 34         }
 35         count++;
 36     }
 37     //设定对角线方向上的获胜组合
 38     for(i=2;i<=6;i+=2){
 39         ptab[i][count]=true;
 40         ctab[i][count]=true;
 41     }count++;
 42     for(i=0;i<=8;i+=4){
 43         ptab[i][count]=true;
 44         ctab[i][count]=true;
 45     }
 46 }
 47 void reup()//根据棋盘状态更新胜利表、外挂、电脑表
 48 {
 49     for(int i=0;i<3;i++){
 50         for(int j=0;j<3;j++){
 51             if(chessdata[i][j]==2){
 52                 //改变胜利表和各外挂、PC各胜利组合的棋子数
 53                 for(int k=0;k<8;k++){
 54                     if(ptab[i*3+j][k]){
 55                         win[0][k]++;
 56                         ctab[i*3+j][k]=false;
 57                         win[1][k]=5;
 58                     }
 59                 }
 60             }else if(chessdata[i][j]==1){
 61                 //改变胜利表和各外挂、PC各胜利组合的棋子数
 62                 for(int k=0;k<8;k++){
 63                     if(ptab[i*3+j][k]){
 64                         win[1][k]++;
 65                         ptab[i*3+j][k]=false;
 66                         win[0][k]=5;
 67                     }
 68                 }
 69             }            
 70         }
 71     }
 72 }
 73 int getPos()//获取该下棋位置
 74 {
 75     int grades[2][9];
 76     int m,i,max=0;
 77     int u;
 78 
 79     for(m=0;m<9;m++){
 80         grades[0][m]=0;
 81         grades[1][m]=0;
 82 
 83         if( chessdata[m/3][m%3]==0){
 84             for(i=0;i<8;i++){
 85                 //计算PC在空棋格上的获胜分数
 86                 if(ptab[m][i] && win[0][i]!=5){
 87                         switch(win[0][i]){
 88                         case 0:
 89                             grades[0][m]+=1;
 90                             break;
 91                         case 1:
 92                             grades[0][m]+=2000;
 93                             break;
 94                         case 2:
 95                             grades[0][m]+=10000;
 96                             break;
 97                         }
 98                 }
 99 
100                 //计算外挂在空格上的获胜分数
101                 if(ctab[m][i] && win[1][i]!=5){
102                     switch(win[1][i]){
103                         case 0:
104                             grades[1][m]+=1;
105                             break;
106                         case 1:
107                             grades[1][m]+=2001;
108                             break;
109                         case 2:
110                             grades[1][m]+=10001;
111                             break;
112                     }
113                 }
114             }
115 
116             if(max==0)u=m;
117             
118             if(grades[0][m]>max){
119                 max=grades[0][m];
120                 u=m;    
121             }
122             else if(grades[0][m]==max){
123                 if(grades[1][m]>grades[1][u])u=m;
124             }
125 
126             if(grades[1][m]>max){
127                 max=grades[1][m];
128                 u=m;    
129             }
130             else if(grades[1][m]==max){
131                 if(grades[0][m]>grades[0][u])u=m;
132             }
133         }
134     }
135     return u;
136 }
137 
138 void CFewDlg::OnButton5() 
139 {
140     HWND gameh=::FindWindow(NULL,"井字棋");//获取窗口句柄
141     //获取窗口进程ID
142     DWORD processid;
143     ::GetWindowThreadProcessId(gameh,&processid);
144     HANDLE processH=::OpenProcess(PROCESS_ALL_ACCESS,false,processid);//打开指定进程
145 
146     //读指定进程 内存数据
147     DWORD byread;
148     LPCVOID pbase=(LPCVOID)0x00F5507C; //棋盘数据基址
149     LPVOID  nbuffer=(LPVOID)&chessdata; //存放棋盘数据
150     ::ReadProcessMemory(processH,pbase,nbuffer,3*3*4,&byread);//进程句柄|基址|存放数据缓冲区|要读取数据的字节数|实际读取的字节数
151 
152     //算法部分:自动走下一步
153     init();
154     reup();
155     int pos=getPos();
156 
157     //鼠标点击
158     int   x=50+pos%3*100,y=50+pos/3*100;   //定义座标点
159     int lparam;                            //定义座标点变量
160     lparam=(y<<16)+x;                      //表示指定格,Y<<16是左移16位,发消息用的Y座标点
161     ::SendMessage(gameh,WM_LBUTTONDOWN,0,lparam);//鼠标按下消息
162     ::SendMessage(gameh,WM_LBUTTONUP,0,lparam);  //鼠标抬起消息
163 }

 

posted @ 2014-03-26 17:58  beautifulzzzz  阅读(1805)  评论(0编辑  收藏  举报