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


    五子棋游戏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 ()

  • 相关阅读:
    基于JAVA企业员工工资管理系统计算机毕业设计源码+数据库+lw文档+系统+部署
    【利用Selenium+autoIt实现文件上传】
    axios发送常见请求方式以及拦截器的封装
    Mysql之聚合函数
    Mathorcup数学建模竞赛第四届-【妈妈杯】C题:面向多层次需求的西安旅游线路优化设计(lingo代码实现)
    部署elasticsearch需要调整的系统参数
    基于casbin的RBAC权限实践
    《asp.net core 3 高级编程(第8版)》学习笔记 02
    电脑基础知识—————— 删除文件
    JavaScript:模拟拍照
  • 原文地址:https://blog.csdn.net/baidu_41801770/article/details/128178384