五子棋游戏AI智能算法设计

news2024/11/15 15:55:33

五子棋游戏C语言AI智能算法设计 

近来发现编制五子棋游戏很有趣,尤其是AI智能算法很烧脑。网上介绍有什么贪心算法,剪枝算法,博弈树算法等等,不一而足。

对于人机对战的电脑智能应子算法,参阅很多五子棋书籍棋谱和五子棋竞赛的对抗棋谱。我感到白棋的后手防御算法很难取胜,棋界有黑棋高手先手必胜一说。算法么想了很多,既然是人工智能下棋就得按人的思路来算计。棋书阐述有许多思路和棋局解说。如活四冲四,嵌五,活三嵌四,活二嵌二。这些是高级棋手的总结。我就按此思路用加权计权方法来表现此类各种情况。

下面程序代码写出了基本算法。代码是function   testAIq ( )。
另外代码中有一算法测试的方法autotest( ) 可供参考。
此测试黑白双方用同一算法互斗难分胜负,这就像周伯通双手互搏,难分高下。想来要另写白棋防守算法,设置白棋VS黑棋才可看出哪个算法好。我的思路是博弈双方的白棋后手防守点也就是黑棋的加权高分点,白棋加权高分点就是进攻点。我就以计算的高分点为AI下子点。

还有一种说法五子棋博弈要算杀,算杀就是计算必杀之局,如嵌四加活三,冲四加活三,嵌五加活三,嵌五加冲四,这些就是必杀局,就是必胜法宝。算杀的最高境界是做杀,预判算出必杀点提前几子做出必杀局。此谓奕道高手中的高手,乃高高手也。此种算法也就是编程界的高手,是谓大咖也。我望之有些高仰,自感境界还没到。锲而不舍,持之以恒,努力吧。

为了摆谱,就在游戏程序上添加了复盘功能。程序没退出就能复现出上一次的盘面。另外还加了记录功能和显示下子序号,每盘棋都打印黑白双方下子记录,界面上也显示记录。有一点就是程序退出记录也就没了。解决的方法是把记录存为文本文件,需要时可作为复盘数据。也可以采用截屏方法保存棋局图片,以便以后复盘研究。

完整的源码可参阅我在本站的博文《五子棋游戏程序禁手设置算法》。
此博文是有禁手设置算法的完整的游戏程序源码。

还有精彩的AI对战演示功能设计autotest( ){ } 用于测试算法。

 

f2be298e793f41ed93b6b8877fc500f8.png

8cc43d4d9e2447cea8540ab0e86750d0.png 

 

//**************************************
//****     五子棋 Gobang  AI    
//****     人机对战 AI 设计   
//**************************************
Canvas cs;    //画布
 int dx,dy;        //draw X, Y
int i,j,t,a;           //t = times
int pn[225];     // pn  0=" " , 1=black , 2=white
int n;                // 225 棋子编码号
int px,py;        // piece x,y
int dn,dn1 ;        //下子计数
 int isDo;      //游戏操作控制 1=可下子,0=不可下
int B,W,k;   //detect win Black White
string cordp,cordp1;   //record pn & G9
int cord;        //record switch
int mode;      //0=人人,1=人机
int wn;    
int sn;
 int dwn[120];    //记录,下子60回合120子为和棋
int col,row ;
int cn,kn;      //show record num
int gn ;    //game round number
 int fudat[200];      //复盘数据
int fusum;    //复盘记录总数
int sd;         //复盘
 int jqn[255];      //计权数
int jqf,jqfn ;        //计权分,优选点位码
int js[255];         //禁手设置
int jsset ;    //s8 show restrict mark
//**********

6e1dc0a870b94e848d02bea3a7855376.png
//AI智能下子算法求解方案:
//(一) 四连情况,黑棋下子,黑冲四嵌五,白必应子,若白无活四 022220 冲四 22220 02222 和嵌五 22022 22202 20222 则必应,有则先着取胜  

//(二) 三连情况,黑棋下子,黑成活三嵌四,
//   若白无活三 02220 嵌四 2022 2202 则必应,
//    有则先着下子成活四     

//(三) 二连情况,黑棋下子,
 //   有活二 01100  嵌三 01010    基本都是这样,
//   二连应子:抢先手原则,白棋先找自己的活二嵌三
 //   先下子成活三嵌四      

//(四) 开局应首子,定标黑子 pn113,白应首子
//       大多棋  谱是 应上 pn98,上右 pn99,暂定此
//       白应起首三子:按棋谱法

//黑白双方博弈,加权计分,黑攻方进攻点就是白守方
//防守点。计分累加标记此点,乃此算法要点。

//将下面 testAIq ()算法分二部分,来测试一下

autotest (){
  //用于检测AI智能下子算法 testAIq ()
  //黑白棋用同一个算法下子很难区分算法的优劣,
  //要设计二种算法分别以黑棋VS白棋才能显示出
  //算法的优劣。下面代码只可检测算法的可行性。
      s7="游戏模式:对战演示"; 
  if (isDo==0||dn>120) return ; //结束标志,测试120子   
  if (mode==1) return ; //双人模式可演示
           wn=wn+1 ;
     if (dn==0) {        //设定首子黑先天元位
         n=113;  black_do () ; 
         n=82 ;  wn=0 ;   //变换n 加以检测
         white_do () ;
          cs.Update () ;      }
       testAIq () ;    //智能计权取得下子点位
      if (wn>1) wn=0 ;    //轮流下子
       if (wn==1) white_do () ;  //白棋下子
       if (wn==0) black_do () ;  //黑棋下子         
    detect () ;
}//autotest ()

07d2b5335b314e55a945a6d6456ecdc2.png

 


testAIq (){
 //人机对战AI选子,加权计算
   for (i=1;i<=225;i++) {
         jqn[i]=0 ;    }      //scan init
   //遍历加权
  for (i=1;i<=15;i++){    //遍历scan B & W 子
  for (j=1;j<=15;j++){    
           k=(i-1)*15+j ;    //pn(n) number
  //独子 左右上下 二对角 八方
     if (pn[k]==2){
        if (pn[k-1]==0) jqn[k-1]= jqn[k-1]+20 ;
        if (pn[k+1]==0) jqn[k+1]= jqn[k+1]+20 ;
        if (pn[k-15]==0) jqn[k-15]= jqn[k-15]+20 ;
        if (pn[k+15]==0) jqn[k+15]= jqn[k+15]+20 ;
        if (pn[k+14]==0) jqn[k+14]= jqn[k+14]+20 ;
        if (pn[k+16]==0) jqn[k+16]= jqn[k+16]+20 ;
        if (pn[k-14]==0) jqn[k-14]= jqn[k-14]+20 ;
        if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+20 ;
             }//pn
 //连二
  if (pn[k]==2&&pn[k+1]==2){  //左右
       if (pn[k-1]==0)  jqn[k-1]= jqn[k-1]+520 ;
       if (pn[k+2]==0)  jqn[k+2]= jqn[k+2]+520 ;       }

 

  if (pn[k]==2&&pn[k+15]==2){  //上下
       if (pn[k-15]==0)  jqn[k-15]= jqn[k-15]+520 ;
       if (pn[k+30]==0)  jqn[k+30]= jqn[k+30]+520 ;     }

   if (pn[k]==2&&pn[k+14]==2){  //左对角
       if (pn[k-14]==0)  jqn[k-14]= jqn[k-14]+520 ;
       if (pn[k+28]==0)  jqn[k+28]= jqn[k+28]+520 ;     }

 if (pn[k]==2&&pn[k+16]==2){   //右对角
       if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+520 ;
       if (pn[k+32]==0) jqn[k+32]= jqn[k+32]+520 ;    }

//嵌三   02020    +1020 为活三冲四进攻点
 if (pn[k]==2&&pn[k+1]==0&&pn[k+2]==2){  //左右
          jqn[k+1]= jqn[k+1]+520 ;   
      if (pn[k-1]==0)  jqn[k-1]= jqn[k-1]+1020 ; 
      if (pn[k+3]==0)  jqn[k+3]= jqn[k+3]+1020 ; }

 if (pn[k]==2&&pn[k+15]==0&&pn[k+30]==2){  //上下
          jqn[k+15]= jqn[k+15]+520 ;   
      if (pn[k-15]==0)  jqn[k-15]= jqn[k-15]+1020 ; 
      if (pn[k+45]==0)  jqn[k+45]= jqn[k+45]+1020 ; }

 if (pn[k]==2&&pn[k-14]==0&&pn[k-28]==2){//左对角
          jqn[k-14]= jqn[k-14]+520 ;   
      if (pn[k+14]==0)  jqn[k+14]= jqn[k+14]+1020 ; 
      if (pn[k-42]==0)  jqn[k-42]= jqn[k-42]+1020 ; }

 if (pn[k]==2&&pn[k+16]==0&&pn[k+32]==2){//右对角
          jqn[k+16]= jqn[k+16]+520 ;   
      if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+1020 ; 
      if (pn[k+48]==0)  jqn[k+48]= jqn[k+48]+1020 ; }

//三连,眠三抢冲四  12220  02221
 if (pn[k]==2&&pn[k+1]==2&&pn[k+2]==2){  //左右
    if (pn[k-1]==0)  jqn[k-1]= jqn[k-1]+2320 ;  
    if (pn[k+3]==0)  jqn[k+3]= jqn[k+3]+2320 ;   }
 if (pn[k]==2&&pn[k+15]==2&&pn[k+30]==2){  //上下
    if (pn[k-15]==0)  jqn[k-15]= jqn[k-15]+2320 ;  
    if (pn[k+45]==0)  jqn[k+45]= jqn[k+45]+2320 ;   }
 if (pn[k]==2&&pn[k-14]==2&&pn[k-28]==2){//左对角
    if (pn[k+14]==0)  jqn[k+14]= jqn[k+14]+2320 ;  
    if (pn[k-42]==0)  jqn[k-42]= jqn[k-42]+2320 ;   }
 if (pn[k]==2&&pn[k+16]==2&&pn[k+32]==2){//右对角
     if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+2320 ;  
    if (pn[k+48]==0)  jqn[k+48]= jqn[k+48]+2320 ;   }

//三连,活三变活四,必杀  0022200    +2000
    if ( pn[k-2]==0&&pn[k-1]==0&&pn[k]==2&&pn[k+1]==2&&pn[k+2]==2&&pn[k+3]==0&&pn[k+4]==0){  //左右
     jqn[k-1]= jqn[k-1]+3500 ;  
     jqn[k+3]= jqn[k+3]+3500 ;   }

   if (pn[k-30]==0&&pn[k-15]==0&&pn[k]==2&&pn[k+15]==2&&pn[k+30]==2&&pn[k+45]==0&&pn[k+60]==0){  //上下
     jqn[k-15]= jqn[k-15]+3500 ;  
     jqn[k+45]= jqn[k+45]+3500 ;   }
  
    if(pn[k-28]==0&&pn[k-14]==0&&pn[k]==2&&pn[k+14]==2&&pn[k+28]==2&&pn[k+42]==0&&pn[k+56]==0){//左对角
      jqn[k-14]= jqn[k-14]+3500 ;  
      jqn[k+42]= jqn[k+42]+3500 ;   }

 if (pn[k-32]==0&&pn[k-16]==0&&pn[k]==2&&pn[k+16]==2&&pn[k+32]==2&&pn[k+48]==0&&pn[k+64]==0){//右对角
      jqn[k-16]= jqn[k-16]+3500 ;  
      jqn[k+48]= jqn[k+48]+3500 ;   }
//*********
//白子算杀,做杀,找活三嵌四交点 +2500

//嵌四类 做冲四 2022  2202   布杀点 +1800
// 120220  122020 020221 022021
   if (j<12){
  if (pn[k]==2&&pn[k+1]==0&&pn[k+2]==2&&pn[k+3]==2){  //左右
      if (pn[k-1]==0||pn[k+4]==0){ jqn[k+1]= jqn[k+1]+1800 ;   }  }
   if (pn[k]==2&&pn[k+1]==2&&pn[k+2]==0&&pn[k+3]==2){  //左右
    if (pn[k-1]==0||pn[k+4]==0){ jqn[k+2]= jqn[k+2]+1800 ;   }   }
           } //j<12

   if (i<12){
 if (pn[k]==2&&pn[k+15]==0&&pn[k+30]==2&&pn[k+45]==2){  //上下
     if (pn[k-15]==0||pn[k+60]==0){  jqn[k+15]= jqn[k+15]+1800 ;   }   }
   if (pn[k]==2&&pn[k+15]==2&&pn[k+30]==0&&pn[k+45]==2){  //上下
     if (pn[k-15]==0||pn[k+60]==0){  jqn[k+30]= jqn[k+30]+1800 ;   }   }
           } //i<12

      if(j>4&&i<12){
 if (pn[k]==2&&pn[k+14]==0&&pn[k+28]==2&&pn[k+42]==2){  //斜左
     if (pn[k-14]==0||pn[k+56]==0){ jqn[k+14]= jqn[k+14]+1800 ;   }  }
   if (pn[k]==2&&pn[k+14]==2&&pn[k+28]==0&&pn[k+42]==2){  //斜左
     if (pn[k-14]==0||pn[k+56]==0){jqn[k+28]= jqn[k+28]+1800 ;   }  }
            } //j>4, i<12
         
        if (j<12&&i<12){
  if (pn[k]==2&&pn[k+16]==0&&pn[k+32]==2&&pn[k+48]==2){  //右斜
         if (pn[k-16]==0||pn[k+64]==0){ jqn[k+16]= jqn[k+16]+1800 ;   }  }
   if (pn[k]==2&&pn[k+16]==2&&pn[k+32]==0&&pn[k+48]==2){  //右斜
        if (pn[k-16]==0||pn[k+64]==0){  jqn[k+32]= jqn[k+32]+1800 ;   }  }
            } //i<12&&j<12

//嵌四 020220  022020  必杀点+3500  j<12  防越界
  if (j<12){
   if ( pn[k-1]==0&&pn[k]==2&&pn[k+1]==0&&pn[k+2]==2&&pn[k+3]==2&&pn[k+4]==0){  //左右
        jqn[k+1]= jqn[k+1]+3500 ;   }
   if ( pn[k-1]==0&&pn[k]==2&&pn[k+1]==2&&pn[k+2]==0&&pn[k+3]==2&&pn[k+4]==0){  //左右
        jqn[k+2]= jqn[k+2]+3500 ;   }    }

    if (i<12){
  if ( pn[k-15]==0&&pn[k]==2&&pn[k+15]==0&&pn[k+30]==2&&pn[k+45]==2&&pn[k+60]==0){  //上下
        jqn[k+15]= jqn[k+15]+3500 ;   }
   if ( pn[k-15]==0&&pn[k]==2&&pn[k+15]==2&&pn[k+30]==0&&pn[k+45]==2&&pn[k+60]==0){  //上下
        jqn[k+30]= jqn[k+30]+3500 ;   }    }

  if (j>4&&i<12){
  if ( pn[k-14]==0&&pn[k]==2&&pn[k+14]==0&&pn[k+28]==2&&pn[k+42]==2&&pn[k+56]==0){  //斜左
        jqn[k+14]= jqn[k+14]+3500 ;   }
   if ( pn[k-14]==0&&pn[k]==2&&pn[k+14]==2&&pn[k+28]==0&&pn[k+42]==2&&pn[k+56]==0){  //斜左
        jqn[k+28]= jqn[k+28]+3500 ;   }    }

        if (j<12&&i<12){
 if ( pn[k-16]==0&&pn[k]==2&&pn[k+16]==0&&pn[k+32]==2&&pn[k+48]==2&&pn[k+64]==0){  //右斜
        jqn[k+16]= jqn[k+16]+3500 ;   }
   if ( pn[k-16]==0&&pn[k]==2&&pn[k+16]==2&&pn[k+32]==0&&pn[k+48]==2&&pn[k+64]==0){  //右斜
        jqn[k+32]= jqn[k+32]+3500 ;   }    }

//活四冲四 022220  122220  022221   
//此是必杀点  +9000  j<12  防越界
 if (pn[k]==2&&pn[k+1]==2&&pn[k+2]==2&&pn[k+3]==2){  //左右
    if (j>1&&pn[k-1]==0)  jqn[k-1]= jqn[k-1]+9000 ;  
    if (j<12&&pn[k+4]==0)  jqn[k+4]= jqn[k+4]+9000 ;   }  

   if (pn[k]==2&&pn[k+15]==2&&pn[k+30]==2&&pn[k+45]==2){  //上下
    if (i>1&&pn[k-15]==0)  jqn[k-15]= jqn[k-15]+9000 ;  
    if (i<12&&pn[k+60]==0) jqn[k+60]= jqn[k+60]+9000 ; } 

    if(pn[k]==2&&pn[k+14]==2&&pn[k+28]==2&&pn[k+42]==2){//左对角
      if (i>4&&j<14&&pn[k-14]==0)   jqn[k-14]= jqn[k-14]+9000 ;  
    if (i<12&&j>4&&pn[k+56]==0)  jqn[k+56]= jqn[k+56]+9000 ;   }  

   if (pn[k]==2&&pn[k+16]==2&&pn[k+32]==2&&pn[k+48]==2){//右对角     
    if (j>1&&i<12&&pn[k-16]==0)  jqn[k-16]= jqn[k-16]+9000 ;  
    if (j<12&&i<12&&pn[k+64]==0)  jqn[k+64]= jqn[k+64]+9000 ;   }  

//嵌五,此是必杀点 20222  22022  22202 +9000
      if (j<12){      // j<12  防越界
      if ( pn[k]==2&&pn[k+1]==0&&pn[k+2]==2&&pn[k+3]==2&&pn[k+4]==2){  //左右 20222
      jqn[k+1]= jqn[k+1]+9000 ;    }
      if ( pn[k]==2&&pn[k+1]==2&&pn[k+2]==0&&pn[k+3]==2&&pn[k+4]==2){  //左右 22022
      jqn[k+2]= jqn[k+2]+9000 ;    }
      if ( pn[k]==2&&pn[k+1]==2&&pn[k+2]==2&&pn[k+3]==0&&pn[k+4]==2){  //左右 22202
      jqn[k+3]= jqn[k+3]+9000 ;    }     }  //j<12

      if (i<12){
    if ( pn[k]==2&&pn[k+15]==0&&pn[k+30]==2&&pn[k+45]==2&&pn[k+60]==2){  //上下 20222
     jqn[k+15]= jqn[k+15]+9000 ;    }
    if ( pn[k]==2&&pn[k+15]==2&&pn[k+30]==0&&pn[k+45]==2&&pn[k+60]==2){  //上下 22022
     jqn[k+30]= jqn[k+30]+9000 ;    }
    if ( pn[k]==2&&pn[k+15]==2&&pn[k+30]==2&&pn[k+45]==0&&pn[k+60]==2){  //上下 22202
     jqn[k+45]= jqn[k+45]+9000 ;    }    }  //i<12

        if (j>4&&i<12){
    if ( pn[k]==2&&pn[k+14]==0&&pn[k+28]==2&&pn[k+42]==2&&pn[k+56]==2){  //斜左 20222
     jqn[k+14]= jqn[k+14]+9000 ;    }
    if ( pn[k]==2&&pn[k+14]==2&&pn[k+28]==0&&pn[k+42]==2&&pn[k+56]==2){  //斜左 22022
     jqn[k+28]= jqn[k+28]+9000 ;    }
    if ( pn[k]==2&&pn[k+14]==2&&pn[k+28]==2&&pn[k+42]==0&&pn[k+56]==2){  //斜左 22202
     jqn[k+42]= jqn[k+42]+9000 ;    }    }

        if (j<12&&i<12){
   if ( pn[k]==2&&pn[k+16]==0&&pn[k+32]==2&&pn[k+48]==2&&pn[k+64]==2){  //右斜 20222
     jqn[k+16]= jqn[k+16]+9000 ;    }
    if ( pn[k]==2&&pn[k+16]==2&&pn[k+32]==0&&pn[k+48]==2&&pn[k+64]==2){  //右斜 22022
     jqn[k+32]= jqn[k+32]+9000 ;    }
    if ( pn[k]==2&&pn[k+16]==2&&pn[k+32]==2&&pn[k+48]==0&&pn[k+64]==2){  //右斜 22202
     jqn[k+48]= jqn[k+48]+9000 ;    }    }

//****************************
//以下是黑棋估权计分
  //独子 左右上下 二对角 八方
     if (pn[k]==1){
        if (pn[k-1]==0) jqn[k-1]= jqn[k-1]+20 ;
        if (pn[k+1]==0) jqn[k+1]= jqn[k+1]+20 ;
        if (pn[k-15]==0) jqn[k-15]= jqn[k-15]+20 ;
        if (pn[k+15]==0) jqn[k+15]= jqn[k+15]+20 ;
        if (pn[k+14]==0) jqn[k+14]= jqn[k+14]+20 ;
        if (pn[k+16]==0) jqn[k+16]= jqn[k+16]+20 ;
        if (pn[k-14]==0) jqn[k-14]= jqn[k-14]+20 ;
        if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+20 ;
             }//pn
 //连二
  if (pn[k]==1&&pn[k+1]==1){  //左右
       if (pn[k-1]==0)  jqn[k-1]= jqn[k-1]+500 ;
       if (pn[k+2]==0)  jqn[k+2]= jqn[k+2]+500 ;   }
  if (pn[k]==1&&pn[k+15]==1){  //上下
       if (pn[k-15]==0)  jqn[k-15]= jqn[k-15]+500 ;
       if (pn[k+30]==0)  jqn[k+30]= jqn[k+30]+500 ;   }
   if (pn[k]==1&&pn[k+14]==1){  //左对角
       if (pn[k-14]==0)  jqn[k-14]= jqn[k-14]+500 ;
       if (pn[k+28]==0)  jqn[k+28]= jqn[k+28]+500 ;   }
 if (pn[k]==1&&pn[k+16]==1){   //右对角
       if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+500 ;
       if (pn[k+32]==0) jqn[k+32]= jqn[k+32]+500 ;   }
//嵌三   02020
 if (pn[k]==1&&pn[k+1]==0&&pn[k+2]==1){  //左右
          jqn[k+1]= jqn[k+1]+500 ;   }
 if (pn[k]==1&&pn[k+15]==0&&pn[k+30]==1){  //上下
          jqn[k+15]= jqn[k+15]+500 ;   }
 if (pn[k]==1&&pn[k+14]==0&&pn[k+28]==1){//左对角
          jqn[k+14]= jqn[k+14]+500 ;   }
 if (pn[k]==1&&pn[k+16]==0&&pn[k+32]==1){//右对角
          jqn[k+16]= jqn[k+16]+500 ;   }

//三连,眠三12220  02221 逢三必堵
 if (pn[k]==1&&pn[k+1]==1&&pn[k+2]==1){  //左右
    if (pn[k-1]==0)  jqn[k-1]= jqn[k-1]+3000 ;  
    if (pn[k+3]==0)  jqn[k+3]= jqn[k+3]+3000 ;   }
 if (pn[k]==1&&pn[k+15]==1&&pn[k+30]==1){  //上下
    if (pn[k-15]==0)  jqn[k-15]= jqn[k-15]+3000 ;  
    if (pn[k+45]==0)  jqn[k+45]= jqn[k+45]+3000 ;   }

 if (pn[k]==1&&pn[k-14]==1&&pn[k-28]==1){//左对角
    if (pn[k+14]==0)  jqn[k+14]= jqn[k+14]+3000 ;  
    if (pn[k-42]==0)  jqn[k-42]= jqn[k-42]+3000 ;  
    if (pn[k+2]==0)  jqn[k+2]= jqn[k+2]+3050 ;  
    if (pn[k-30]==0)  jqn[k-30]= jqn[k-30]+3050 ;  
             }    //破梅花阵
 if (pn[k]==1&&pn[k+16]==1&&pn[k+32]==1){//右对角
     if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+3000 ;  
    if (pn[k+48]==0)  jqn[k+48]= jqn[k+48]+3000 ;   
    if (pn[k+2]==0)  jqn[k+2]= jqn[k+2]+3050 ;  
    if (pn[k+30]==0)  jqn[k+30]= jqn[k+30]+3050 ;  
             }    //破梅花阵

//三连,活三  01110  逢三必堵
 if ( pn[k-1]==0&&pn[k]==1&&pn[k+1]==1&&pn[k+2]==1&&pn[k+3]==0){  //左右
    if (pn[k-1]==0)  jqn[k-1]= jqn[k-1]+3300 ;  
    if (pn[k+3]==0)  jqn[k+3]= jqn[k+3]+3300 ;   }

   if (pn[k-15]==0&&pn[k]==1&&pn[k+15]==1&&pn[k+30]==1&&pn[k+45]==0){  //上下
    if (pn[k-15]==0)  jqn[k-15]= jqn[k-15]+3300 ;  
    if (pn[k+45]==0)  jqn[k+45]= jqn[k+45]+3300 ;   }

 if (pn[k-14]==0&&pn[k]==1&&pn[k+14]==1&&pn[k+28]==1&&pn[k+42]==0){//左对角
    if (pn[k-14]==0)  jqn[k-14]= jqn[k-14]+3300 ;  
    if (pn[k+42]==0)  jqn[k+42]= jqn[k+42]+3300 ;   }

 if (pn[k-16]==0&&pn[k]==1&&pn[k+16]==1&&pn[k+32]==1&&pn[k+48]==0){//右对角
     if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+3300 ;  
    if (pn[k+48]==0)  jqn[k+48]= jqn[k+48]+3300 ;   }

//嵌四 010110   011010   必杀点 +3500
  if ( pn[k-1]==0&&pn[k]==1&&pn[k+1]==0&&pn[k+2]==1&&pn[k+3]==1&&pn[k+4]==0){  //左右
        jqn[k+1]= jqn[k+1]+3500 ;   }
   if ( pn[k-1]==0&&pn[k]==1&&pn[k+1]==1&&pn[k+2]==0&&pn[k+3]==1&&pn[k+4]==0){  //左右
        jqn[k+2]= jqn[k+2]+3500 ;   }

  if ( pn[k-15]==0&&pn[k]==1&&pn[k+15]==0&&pn[k+30]==1&&pn[k+45]==1&&pn[k+60]==0){  //上下
        jqn[k+15]= jqn[k+15]+3500 ;   }
   if ( pn[k-15]==0&&pn[k]==1&&pn[k+15]==1&&pn[k+30]==0&&pn[k+45]==1&&pn[k+60]==0){  //上下
        jqn[k+30]= jqn[k+30]+3500 ;   }

  if ( pn[k-14]==0&&pn[k]==1&&pn[k+14]==0&&pn[k+28]==1&&pn[k+42]==1&&pn[k+56]==0){  //斜左
        jqn[k+14]= jqn[k+14]+3500 ;   }
   if ( pn[k-14]==0&&pn[k]==1&&pn[k+14]==1&&pn[k+28]==0&&pn[k+42]==1&&pn[k+56]==0){  //斜左
        jqn[k+28]= jqn[k+28]+3500 ;   }

  if ( pn[k-16]==0&&pn[k]==1&&pn[k+16]==0&&pn[k+32]==1&&pn[k+48]==1&&pn[k+64]==0){  //右斜
        jqn[k+16]= jqn[k+16]+3500 ;   }
   if ( pn[k-16]==0&&pn[k]==1&&pn[k+16]==1&&pn[k+32]==0&&pn[k+48]==1&&pn[k+64]==0){  //右斜
        jqn[k+32]= jqn[k+32]+3500 ;   }

//活四冲四 此是必杀点 211110  011112   +6000
//黑有此白必堵,此是必杀点 如白无连五则必应 
    if ( pn[k]==1&&pn[k+1]==1&&pn[k+2]==1&&pn[k+3]==1){  //左右
    if (pn[k-1]==0)  jqn[k-1]= jqn[k-1]+7000 ;  
    if (pn[k+4]==0)  jqn[k+4]= jqn[k+4]+7000 ;   }

   if (pn[k]==1&&pn[k+15]==1&&pn[k+30]==1&&pn[k+45]==1){  //上下
    if (pn[k-15]==0)  jqn[k-15]= jqn[k-15]+7000 ;  
    if (pn[k+60]==0)  jqn[k+60]= jqn[k+60]+7000 ;   }
 if(pn[k]==1&&pn[k-14]==1&&pn[k-28]==1&&pn[k-42]==1){//左对角
    if (pn[k+14]==0)  jqn[k+14]= jqn[k+14]+7000 ;  
    if (pn[k-56]==0)  jqn[k-56]= jqn[k-56]+7000 ;   }

 if (pn[k]==1&&pn[k+16]==1&&pn[k+32]==1&&pn[k+48]==1){//右对角
     if (pn[k-16]==0)  jqn[k-16]= jqn[k-16]+7000 ;  
    if (pn[k+64]==0)  jqn[k+64]= jqn[k+64]+7000 ;   }

//嵌五 10111  11011  11101   +6000
//此是必杀点 如白无连五则必应 
      if ( pn[k]==1&&pn[k+1]==0&&pn[k+2]==1&&pn[k+3]==1&&pn[k+4]==1){  //左右 10111
      jqn[k+1]= jqn[k+1]+7000 ;    }
      if ( pn[k]==1&&pn[k+1]==1&&pn[k+2]==0&&pn[k+3]==1&&pn[k+4]==1){  //左右 11011
      jqn[k+2]= jqn[k+2]+7000 ;    }
      if ( pn[k]==1&&pn[k+1]==1&&pn[k+2]==1&&pn[k+3]==0&&pn[k+4]==1){  //左右 11101
      jqn[k+3]= jqn[k+3]+7000 ;    }

    if ( pn[k]==1&&pn[k+15]==0&&pn[k+30]==1&&pn[k+45]==1&&pn[k+60]==1){  //上下 10111
     jqn[k+15]= jqn[k+15]+7000 ;    }
    if ( pn[k]==1&&pn[k+15]==1&&pn[k+30]==0&&pn[k+45]==1&&pn[k+60]==1){  //上下 11011
     jqn[k+30]= jqn[k+30]+7000 ;    }
    if ( pn[k]==1&&pn[k+15]==1&&pn[k+30]==1&&pn[k+45]==0&&pn[k+60]==1){  //上下 11101
     jqn[k+45]= jqn[k+45]+7000 ;    }

    if ( pn[k]==1&&pn[k+14]==0&&pn[k+28]==1&&pn[k+42]==1&&pn[k+56]==1){  //斜左 10111
     jqn[k+14]= jqn[k+14]+7000 ;    }
    if ( pn[k]==1&&pn[k+14]==1&&pn[k+28]==0&&pn[k+42]==1&&pn[k+56]==1){  //斜左 11011
     jqn[k+28]= jqn[k+28]+7000 ;    }
    if ( pn[k]==1&&pn[k+14]==1&&pn[k+28]==1&&pn[k+42]==0&&pn[k+56]==1){  //斜左 11101
     jqn[k+42]= jqn[k+42]+7000 ;    }

    if ( pn[k]==1&&pn[k+16]==0&&pn[k+32]==1&&pn[k+48]==1&&pn[k+64]==1){  //右斜 10111
     jqn[k+16]= jqn[k+16]+7000 ;    }
    if ( pn[k]==1&&pn[k+16]==1&&pn[k+32]==0&&pn[k+48]==1&&pn[k+64]==1){  //右斜 11011
     jqn[k+32]= jqn[k+32]+7000 ;    }
    if ( pn[k]==1&&pn[k+16]==1&&pn[k+32]==1&&pn[k+48]==0&&pn[k+64]==1){  //右斜 11101
     jqn[k+48]= jqn[k+48]+7000 ;    }

  }    }    //test i , j   pn(225) 棋盘点位

//******************************
//测试:显示加权计分情况,最高分白下子
   if (isDo==0) return ;
     cs.SetTextSize (16);
     cs.SetTextStyle (0);
     cs.SetColor (255,0,150,0) ;
       for (i=1;i<=225;i++){    //test scan
           if (jqn[i] !=0) {
             //print i,"  qn= ",jqn[i] ;    //测试
             s=intToString ( jqn[i]) ;
     dx=(i-(i/15*15))*40;
     dy=(i/15)*40+40;
       if (dx==0){ dx=15*40;    dy=dy-40;   }
               cs.DrawText (s,dx,dy) ;  //draw jqn(i)
          }     }
 
//计算最高分
      jqf=0 ;
 for (i=1;i<=225;i++){  
       k= jqn[i] ;
       if ( k>jqf) { jqf=k ;  jqfn=i ;   }
             } //计算最高分
 
       sn=jqfn ;     //计权最高分点位转坐标
       if (dn==1) {
         if (gn==1) sn=98 ;
         if (gn==2) sn=97 ;
         if (gn==3) sn=99 ;    }
 //   print " sn= ",jqfn ," jqf= ",jqf ;
      dx=(sn-(sn/15*15))*40;
      dy=(sn/15)*40+40;
       if (dx==0) {dx=15*40;   dy=dy-40;   }
      cs.SetColor (255,250,250,0);  
      cs.DrawCircle (dx,dy,5);  //标记下子点
         cs.Update () ;   
      //  sleep (500) ;
         n=sn ;      //下子点号sn转换为n,  draw board
         px=dx ;  py=dy ;    //board ()标记下子点
 //**** AI 走子 ********************** 
}//testAIq ()

black_do (){    //黑棋下子
         pn[n]=1;    
          s6="白棋选子";   
        row=15-(n/15) ;
        col=(n-(n/15*15)) ;
      if (col==0){ col=15 ;    row=row+1 ;   }
        swapabc () ;   //return ss
        cordp=" B   "+intToString (n);    //走子记录
        cordp1=" B  "+ss+intToString (row) ;
     if (cordp != ss2) {    //不重复记录
           dn=dn+1;       //print dn;   
           print dn," ",cordp,"    " , ss,row ;  //打印记录
             ss2=cordp; 
           dwn[dn]=n ;    //print play number
           fudat[dn]=n;    fusum=dn;  //复盘数据                           
         board ();    
               }
         testAIq ();     //test AI 计权白子点位下子 **
          
    if (mode==1) {     //人机模式下子
            white_do () ;      }    // AI Do  白下子
}//black_do ()

white_do (){    //白棋下子
   if (isDo==0) return ;
        pn[n]=2;
          s6="黑棋选子";        
       row=15-(n/15) ;
       col=(n-(n/15*15)) ;
       if (col==0){ col=15 ;    row=row+1 ;   }
       swapabc () ;   //return ss
       cordp=" W  "+intToString (n);     //走子记录
       cordp1="W  "+ss+intToString (row) ;
     if (cordp != ss2) { 
          dn=dn+1;    
          print dn," ",cordp,"    " , ss,row ;  //打印记录
            ss2=cordp;  
          dwn[dn]=n ;    //print play number
          fudat[dn]=n;    fusum=dn;  //复盘数据
        board () ;
               }
      if (jsset==1)  restrict_move () ;    //禁手设置
      //scan restricted move and draw mark
 }//white_do ()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/61558.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

有序Map集合:LinkedHashMap和TreeMap该如何选用

文章目录前言一、为什么HashMap是无序的二、LinkedHashMap如何保证有序性三、TreeMap的底层原理四、LinkedHashMap和TreeMap比较总结前言 为什么HashMap是无序的&#xff1f;有序的Map集合有哪些&#xff1f;LinkedHashMap和TreeMap都是有序的Map集合&#xff0c;他们有什么区…

智能优化算法期末复习(更新ing)

目录 一、GA遗传算法 二、ACO蚁群算法 三、PSO粒子群算法 四、SA模拟退火算法 五、ABC人工蜂群算法 六、综合 一、GA遗传算法 1.运算流程 2.遗传算法适应值分配策略&#xff08;基于目标函数的直接分配、基于排名的分配&#xff09; 3.遗传算法在二进制问题&#xff08;如0…

Windows OpenGL ES 图像绿幕抠图

目录 一.OpenGL ES 图像绿幕抠图 1.原始图片2.效果演示 二.OpenGL ES 图像绿幕抠图源码下载三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础…

Java开发必须掌握的运维知识 (十)-- Docker集群自动化部署管理:Kubernetes快速入门

一、什么是Kubernetes Kubernetes(K8S)是Google在2014年发布的一个开源项目&#xff0c;用于自动化容器化应用程序的部署、扩展和管理。 Kubernetes通常结合docker容器工作&#xff0c;并且整合多个运行着docker容器的主机集群。 Kubernetes官网地址 二、Kubernetes相关特性 …

JavaWeb_第3章_HTTPTomcatServlet

JavaWeb_第3章_HTTP&Tomcat&Servlet 文章目录JavaWeb_第3章_HTTP&Tomcat&Servlet1&#xff0c;Web概述1.1 Web和JavaWeb的概念1.2 JavaWeb技术栈1.2.1 B/S架构1.2.2 静态资源1.2.3 动态资源1.2.4 数据库1.2.5 HTTP协议1.2.6 Web服务器1.3 Web核心课程安排2, HT…

vue中,页面布局之使用vue-splitpane实现窗格的拆分和调节,类似于flex布局

vue中&#xff0c;页面布局之使用vue-splitpane实现窗格的拆分和调节&#xff0c;类似于flex布局 1、基本介绍 npm地址&#xff1a;https://www.npmjs.com/package/vue-splitpane 安包 npm install vue-splitpane注册 main.js import splitPane from vue-splitpane // 注…

土豆清洗去皮机设计

目 录 摘 要 I Abstract II 1绪论 1 1.1选题背景及意义 1 1.2国内外研究现状 1 1.2.1国内外现状 2 1.2.2国外研究现状 2 1.3 发展趋势 3 1.4研究内容及方法 4 2毛刷式土豆清洗去皮机总体设计 5 2.1毛刷式土豆清洗去皮机的构造及工作原理 5 2.2 土豆擦皮机的相关计算 6 2.2.1设计…

动手学深度学习(1)—— 基础知识

文章目录一、基本概念1.1 关键组件数据模型目标函数优化算法1.2 各种机器学习问题监督学习无监督学习强化学习1.3 神经网络的特点二、预备知识2.1 数据操作入门运算符广播机制索引和切片节省内存转换为其他python 对象2.2 数据预处理读取数据集处理缺失的数据2.3 线性代数标量向…

WPS通过“文档部件”的“域”设置图、表和公式的自动序列号

写文档时&#xff0c;当有多张图片、多个表格和多个公式需要编号时&#xff0c;可以通过设置自动序列号&#xff0c;实现一定程度的自动编号和任意位置插入后随时更新序号。具体操作如下 ​ 1. 图的设置 在WPS中&#xff0c;首先设置好一张图片的格式后&#xff0c;对于需要设…

【并发】J.U.C线程池

线程池 经历了Java内存模型、JUC基础之AQS、CAS、Lock、并发工具类、并发容器、阻塞队列、atomic类后&#xff0c;我们开始JUC的最后一部分&#xff1a;线程池。 线程池的优势 为什么多线程会带来性能问题 多线程的性能问题&#xff0c;分为两类&#xff0c;一类是线程本身…

从今天起真正释放创造力——亚马逊云科技re:Invent

对于开发者而言&#xff0c;成就感来自于每一次敲下代码后可实现的创造力&#xff0c;而不是把时间和精力消耗在写千篇一律又无法复用的“胶水”代码&#xff0c;或是在越来越复杂的软件栈面前&#xff0c;疲惫地写业务流程并尽量减少Bug。更加不堪的是&#xff0c;有时仅仅是因…

2022.12.4 学习周报

文章目录摘要文献阅读1.题目2.摘要3.介绍4.方法5.实验5.1 数据集5.2 网络模型5.3 实验表现6.展望深度学习1.LSTM原理1.1 什么是LSTM&#xff1f;1.2 遗忘门&#xff08;forget gate&#xff09;1.3 输入门&#xff08;input gate&#xff09;1.4 输出门&#xff08;output gate…

Python声明式统计可视化库 altair-GitHub鉴赏官

推荐理由&#xff1a;Vega-Altair是 Python 的声明式统计可视化库。借助 Vega-Altair&#xff0c;您可以花更多时间来理解数据及其含义。Vega-Altair 的 API 简单、友好且一致&#xff0c;建立在强大的 Vega-Lite JSON 规范之上。这种优雅的简单性可以用最少的代码产生漂亮而有…

FT2004(D2000)开发实战之在线开发GPIO LED程序

一 在线开发GPIO LED程序 分析GPIO LED原理图 从飞腾FT2004原理图可知,开发板将GPIO1_A3和GPIO1_A4连接到LED上,具体如下: 开发板将GPIO1_A3和GPIO1_A4连接到LED上,因此代码初始化时需要注意以下几点: => 打开/dev/gpiochip1设备 => gpio偏移量为3和4创建led.c roo…

OpenShift 4 - 从 FreeIPA/RHIdM 向 RHSSO 同步用户和组

《OpenShift / RHEL / DevSecOps / Ansible 汇总目录》 说明&#xff1a;本文已经在 OpenShift 4.11 环境中验证 文章目录安装 FreeIPA/RHIdM在 FreeIPA/RHIdM 中添加用户和组从 FreeIPA/RHIdM 向 RHSSO 同步用户和组参考红帽 RHIdM 基于开源项目 FreeIPA&#xff0c;其内部提供…

Windows Access Token

Windows Access Token Windows Token其实叫Access Token(访问令牌)&#xff0c;它是一个描 述进程或者线程安全上下文的一个对象。不同的用户登录计算机后&#xff0c; 都会生成一个Access Token&#xff0c;这个Token在用户创建进程或者线程 时会被使用&#xff0c;不断的拷贝…

如何选择和使用腾讯云服务器的方法新手教程

本文将介绍如何选择和使用腾讯云服务器的方法新手教程。云服务器能帮助快速构建更稳定、安全的应用&#xff0c;降低开发运维的难度和整体IT成本。腾讯云CVM云服务器提供多种类型的实例、操作系统和软件包。各实例中的 CPU、内存、硬盘和带宽可以灵活调整&#xff0c;以满足应用…

C++11中可变参数模板使用

在看同事编写的代码&#xff0c;发现有如下的代码&#xff0c;因为没用过&#xff0c;所以查了一下这是什么语法&#xff0c;通过查询资料知道了这是C11中增加的可变参数模板。 template<class T, class ...Args> bool GetValue(T &value, Args &&...args) c…

12.2-12.4总结

12.2 明明跟着Vue3的视频学的&#xff0c;结果今天发现我学的都是vue2的写法&#xff0c;导致网上查阅资料调用组件有很多东西看不懂。设置langts也用不了&#xff0c;所以去查文档&#xff0c;增加配置了。 -安装vue-cli手脚架 解决lang"ts"报错http://t.csdn.cn/…

【力扣周总结】

题目汇总 判断括号的合法 #20 有效的括号&#xff08;栈问题 stack &#xff09;#921. 使括号有效的最少添加&#xff08;纯逻辑题&#xff09;#1541. 平衡括号字符串的最少插入次数&#xff08;纯逻辑题&#xff09; 单调(递减)栈 - Next Greater Element 题型 496. 下一个…