五子棋游戏禁手算法的改进

五子棋游戏禁手算法的改进

五子棋最新的禁手规则:

1.黑棋禁手判负、白棋无禁手。黑棋禁手有“三三”(包括“四三三”)、“四四”(包括“四四三”)和“长连”。黑棋只能以“四三”取胜。
2.黑方五连与禁手同时形成,判黑方胜。
3.黑方禁手形成时,白方应立即指出。若白方在之后继续落子,则禁手失效,此后指出禁手也不判黑方负。
注意:本条仅限于“三三”和“四四”禁手点,黑方走出的长连则不同:在对局结束前,白方无论何时指出黑方出现长连,都判白方胜。

禁手设置算法:
禁手有三种基本形,即三三禁手和四四禁手,以及长连禁手。
另外还有三三四,四四三类禁手,以及一些特殊形态的禁手。
三三禁手形态:00 10100    >   0 x K x 1 x 0
                           00 1100      >   0 x K 1 x  0
                           0 10010      >   0 K x x 1  0
四四禁手形态:00 11100    >   0 x K 1 1 x  0
                           0 11010      >   0  K 1 x 1  0
                           0 10110      >   0  K x 1  1  0
  K  是遍历搜索点,if (K=1) 黑子时,  x  点位就是三连和四连的禁手点位。
用遍历搜索算法按15 * 15 棋盘点位pn ( 1 -225 ),
分四个方向搜索,即左右,上下,右斜,斜左。遇黑子则计算加权分,赋100分值。此方法可减少计算量,无黑子位不计算。三三四四各形态同时搜索查验加权计算,一次遍历加权计分,最后查验加权分情况,超过100分的点位就是禁手点位。如有超过200分的情况就是三三四和四四三禁手。
长连禁手设置:在判胜负函数detect()时黑棋超过五连即是长连禁手,判黑负,白棋胜。
有一些特殊的形态如扁担阵暂不设置。此程序是简版,完整版本要全面设置。
代码中有显示计算的分值点标记,黄色是100分的点位,紫色是超过100分的点位,即禁手点位。这是测试算法时用来查看的,应用时可注释掉。
此算法是基本的算法,优点是简单和易于理解。

黑棋如设置禁手要想获胜就只有活四和嵌五,还有就是冲四活三,原先发布的博文有bug,当时较仓促,算法测试不充分,忽略了冲四活三的情况。今就此补充修正代码。

这里有个巧妙的算法,在原代码上改一下就成了。算法是三三计权分仍然是100而四四的计权分改为110,这样三三禁手分是200,四四禁手分是220,如是三三四就310分,四四三就320分,
         if ( js[i]>110 && js[i]!=210 ) {  ......   }
这样计分大于110就触发禁手,而若等于210分就是冲四活三必胜点。

图例:
黄色点是计分点,紫色点是禁手点

39becd15fca149bb9764d6e3951930c5.png

eae195c27fe3462d828fecf2e0a8f7a6.png 

 

restrict_move ( ) {  //禁手设置
 //黑棋禁手,加权计算查找
   for (i=1;i<=225;i++) {  js[i]=0 ;    }  //init scan
 //三三禁手,01010 此情况中间为可成三三的交点
 //此点记100,若有两个三三,此点就计分200,
 //即禁手点位,黑棋若下子即可判负
  for (i=1;i<=15;i++){    //遍历scan 黑子
  for (j=1;j<=15;j++){    
           k=(i-1)*15+j ;    //pn(n) number
  //三三禁手形 0 0  1  010 0,  k前后 0位计权
 //两边为空中间可成活三,有子是假活三
     if (pn[k]==1){  // scan B (k)
      if (pn[k-1]==0&&pn[k+1]==0&&pn[k+2]==1&&pn[k+3]==0){
        js[k+1]= js[k+1]+100 ;
      if ( pn[k-2]==0)  js[k-1]= js[k-1]+100 ;  
      if (pn[k+4]==0)  js[k+3]= js[k+3]+100 ;   
      if ( pn[k-2]==1&&pn[k+4]==1) { //101(0)101四四的特殊情况
            js[k+1]= js[k+1]+200 ;   }     }//左右
   
     if (pn[k-15]==0&&pn[k+15]==0&&pn[k+30]==1&&pn[k+45]==0){  
         js[k+15]= js[k+15]+100 ;   
      if ( pn[k-30]==0) js[k-15]= js[k-15]+100 ;   
      if (pn[k+60]==0) js[k+45]= js[k+45]+100 ;   
      if ( pn[k-30]==1&&pn[k+60]==1) { //四四
             js[k+15]= js[k+15]+200 ;   }     }//上下

     if (pn[k-14]==0&&pn[k+14]==0&&pn[k+28]==1&&pn[k+42]==0){  
          js[k+14]= js[k+14]+100 ;  
     if ( pn[k-28]==0) js[k-14]= js[k-14]+100 ;   
      if (pn[k+56]==0) js[k+42]= js[k+42]+100 ;   
      if ( pn[k-28]==1&&pn[k+56]==1) {  //四四
            js[k+14]= js[k+14]+200 ;   }     }//斜左

     if (pn[k-16]==0&&pn[k+16]==0&&pn[k+32]==1&&pn[k+48]==0){  
          js[k+16]= js[k+16]+100 ;   
      if ( pn[k-32]==0) js[k-16]= js[k-16]+100 ;   
      if (pn[k+64]==0) js[k+48]= js[k+48]+100 ;   
      if ( pn[k-32]==1&&pn[k+64]==1) { //四四
            js[k+16]= js[k+16]+200 ;   }     }//右斜

            }  //00 1 0100  四四 1(0)101的特殊情况

//禁手形 00  1  100 ,  k前后 0位计权
   if (pn[k]==1){  //scan B (k)
   if (pn[k-1]==0&&pn[k+1]==1&&pn[k+2]==0){  
        if (pn[k-2]==0) js[k-2]= js[k-2]+100 ;   
        if (pn[k-2]==0) js[k-1]= js[k-1]+100 ;   
        if (pn[k+3]==0) js[k+2]= js[k+2]+100 ;   
    if (pn[k+3]==0) js[k+3]= js[k+3]+100 ;   }  //左右

    if (pn[k-15]==0&&pn[k+15]==1&&pn[k+30]==0){  
        if (pn[k-30]==0) js[k-30]= js[k-30]+100 ;   
        if (pn[k-30]==0) js[k-15]= js[k-15]+100 ;   
        if (pn[k+45]==0)  js[k+30]= js[k+30]+100 ;   
    if (pn[k+45]==0) js[k+45]= js[k+45]+100 ;   }  //上下
     
    if (pn[k-14]==0&&pn[k+14]==1&&pn[k+28]==0){  
       if (pn[k-28]==0)  js[k-28]= js[k-28]+100 ;   
       if (pn[k-28]==0) js[k-14]= js[k-14]+100 ;   
        if (j<12&&pn[k+42]==0) js[k+28]= js[k+28]+100 ;   
   if (pn[k+42]==0) js[k+42]= js[k+42]+100 ;   }  //斜左

   if (pn[k-16]==0&&pn[k+16]==1&&pn[k+32]==0){  
        if (pn[k-32]==0) js[k-32]= js[k-32]+100 ;   
        if (pn[k-32]==0) js[k-16]= js[k-16]+100 ;   
        if (pn[k+48]==0) js[k+32]= js[k+32]+100 ;   
   if (pn[k+48]==0) js[k+48]= js[k+48]+100 ;   }  //右斜
              }   //00 1 100

 //禁手形 0 1  0010 ,  中间 0位计权
   if (pn[k]==1){  //scan B (k)
   if (pn[k-1]==0&&pn[k+1]==0&&pn[k+2]==0&&pn[k+3]==1&&pn[k+4]==0){  
        js[k+1]= js[k+1]+100 ;   
        js[k+2]= js[k+2]+100 ;   }  //左右
   if (pn[k-15]==0&&pn[k+15]==0&&pn[k+30]==0&&pn[k+45]==1&&pn[k+60]==0){  
        js[k+15]= js[k+15]+100 ;   
        js[k+30]= js[k+30]+100 ;   }  //上下
   if (pn[k-14]==0&&pn[k+14]==0&&pn[k+28]==0&&pn[k+42]==1&&pn[k+56]==0){  
        js[k+14]= js[k+14]+100 ;   
        js[k+28]= js[k+28]+100 ;   }  //斜左
   if (pn[k-16]==0&&pn[k+16]==0&&pn[k+32]==0&&pn[k+48]==1&&pn[k+64]==0){  
        js[k+16]= js[k+16]+100 ;   
        js[k+32]= js[k+32]+100 ;   }  //右斜
           }  //010010

//四四禁手算法同三三禁手
//四四禁手形 00 1 1100 ,  前后 0 位计权
//更正:冲四加活三不是禁手!! add 110分
//加:特殊禁手 111 0 x 0 111
  if (pn[k]==1){  //scan B (k)
   if (pn[k+1]==1&&pn[k+2]==1){  
     if (pn[k-2]==0&&pn[k-1]==0){ js[k-1]= js[k-1]+110 ;   js[k-2]= js[k-2]+110 ;  }
     if (pn[k+3]==0&&pn[k+4]==0){
          js[k+3]= js[k+3]+110 ; js[k+4]= js[k+4]+110 ;  }     }  //左右

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

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

   if (pn[k+16]==1&&pn[k+32]==1){  
       if (pn[k-32]==0&&pn[k-16]==0){ js[k-16]= js[k-16]+110 ;   js[k-32]= js[k-32]+110 ;  }
       if (pn[k+48]==0&&pn[k+64]==0){ 
           js[k+48]= js[k+48]+110 ;    js[k+64]= js[k+64]+110 ;  }    }  //右斜
          }  //0 1 110   ( 111 0x0 111 )

//四四禁手形 0 1 1010 ,  0 1 0110 前后 0 位计权
   if (pn[k]==1){  //scan B (k)
   if (pn[k-1]==0&&pn[k+1]==0&&pn[k+3]==1&&pn[k+4]==0){  
    if (pn[k+1]==0&&pn[k+2]==1)js[k+1]= js[k+1]+110 ;   
    if (pn[k+1]==1&&pn[k+2]==0)js[k+2]= js[k+2]+110 ;  
               }  //左右

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

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

     if (pn[k-16]==0&&pn[k+16]==0&&pn[k+48]==1&&pn[k+64]==0){  
    if (pn[k+16]==0&&pn[k+32]==1)js[k+16]= js[k+16]+110 ;   
    if (pn[k+16]==1&&pn[k+32]==0)js[k+32]= js[k+32]+110 ;  
               }  //右斜
             } //0 1 1010  0 1 0110
//********
           }    }   //scan i , j   整个搜索过程

//禁手的基本设置就这样
 //长连禁手设置:在判胜负函数 detect ( ) 时
 // 黑棋超过五连即判黑负,白棋胜。

 //********** 
    cs.SetTextSize (16);
     cs.SetTextStyle (0);
     cs.SetFillMode (1);//0不填色,1填色
    for (i=1;i<=225;i++){    //test restrict_move
           if (js[i] !=0) {      //Mark it 标记禁手点
             s=intToString ( js[i]) ;
     dx=(i-(i/15*15))*40;
     dy=(i/15)*40+40;
       if (dx==0){ dx=15*40;    dy=dy-40;   }
           cs.SetColor (255,250,250,0) ;
           cs.DrawCircle (dx,dy,3) ;     //draw mark
//更正:冲四加活三不是禁手!! 四加 110分   
    if (js[i]>110&&js[i]!=210){
           cs.SetColor (255,180,0,180) ;
           cs.DrawCircle (dx,dy,5) ;  } //draw mark
              }     }
    cs.Update ( ) ;
    
}//restrict_move ( )

图例:

在下拉菜单设置禁手

b8adc3eb9f404515bf356612f0d7a562.png

7ea6e7c06c0f426d97e52f45b5b7055a.png  

上图E 9,  G 10 ,H 6 
此三点位就是冲四活三必杀点

全局变量加:
int js[225];         //禁手设置 遍历棋盘点位
int jsset ;    //0=on 有禁手,1=off 无禁手,下拉菜单

在白棋下子后加禁手判断:
white_do ( ){    //白棋下子
    ............ 
       testAIq (  );     //AI 算法测试 ****
   //scan restricted move and draw mark
   if (jsset==0)  restrict_move ( ) ;  //禁手设置标记
 }//white_do ( )

在判胜负的function detect ( ) 中加代码,
如触禁手判白棋胜

detect ( ) {    
    ......  ......
//*****************************
 if (jsset==0&&pn[n]==1&&js[n]>110&&js[i]!=210){ 
      //禁手,判白棋胜
         print "禁手 pn=", n ;
         cs.SetColor(255,255,0,0);
         cs.SetTextSize (16);
     cs.DrawText ("( 禁手 )",655,(dn+2)*16 );   
         cs.SetTextSize (40);
     cs.DrawText ("( 禁手 )",460,530 );   
         ss9="白棋胜  !"; 
         goto heqi;    }

       ......  ......
}//detect ( ) 

其他功能设置感兴趣的朋友可参阅我本站其他博文,

需要游戏程序源码可联系我:micelu@126.com

//**End**

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

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

相关文章

创新科技改变城市:智慧城市建设全景展望

在当今科技飞速发展的时代&#xff0c;智慧城市的概念已经成为城市发展的新趋势&#xff0c;为人们的生活带来了前所未有的便利和改变。智慧城市&#xff0c;顾名思义&#xff0c;是以先进的信息技术为基础&#xff0c;通过数字化、互联网化和智能化手段&#xff0c;实现城市基…

合宙Air724UG LuatOS-Air LVGL API控件--图表 (Chart)

图表 (Chart) 一幅图胜过一千个字&#xff0c;通过图表展示出的数据内容能让用户更快速有效的了解数据特征。 代码示例 – 创建图表 chart lvgl.chart_create(lvgl.scr_act(), nil) lvgl.obj_set_size(chart, 200, 150) lvgl.obj_align(chart, nil, lvgl.ALIGN_CENTER, 0, …

Node 执行命令时传参 process.argv

process 对象是一个全局变量&#xff0c;提供当前 Node.js 进程的有关信息&#xff0c;以及控制当前 Node.js 进程。 因为是全局变量&#xff0c;所以无需使用 require()。 process.argv 属性返回一个数组&#xff0c;这个数组包含了启动Node.js进程时的命令行参数&#xff0c…

java-thread-affinity线程绑核

通过将线程绑定到指定的cpu上&#xff0c;可以提高执行效率。因为每次都是相同的cpu,可以充分利用高速缓存&#xff0c;在java中可以使用以下依赖来使用。 <dependency><groupId>net.openhft</groupId><artifactId>affinity</artifactId><ver…

2023新,centos7安装mysql8.0.25

2023新&#xff0c;centos7安装mysql8.0.25 目录 2023新&#xff0c;centos7安装mysql8.0.251、下载rpm文件2、安装3、配置my.cnf4、启动查看重启服务5、登入mysql并修改密码6、修改可以远程登录 1、下载rpm文件 进入到你想要的文件地址下 wget https://repo.mysql.com//mysq…

Unity RenderStreaming 云渲染-黑屏

&#x1f96a;云渲染-黑屏 网页加载出来了&#xff0c;点击播放黑屏 &#xff0c;关闭防火墙即可&#xff01;&#xff01;&#xff01;&#xff01;

springboot添加SSL证书,支持https与http

文章目录 一、添加ssl证书二、配置文件三、配置同时支持HTTPS与HTTP四、启动 一、添加ssl证书 将证书文件放在/resource目录下 二、配置文件 修改配置文件 server:ssl:# 指定保存SSL证书的秘钥存储的路径key-store: classpath:dev.cobona.cn.pfx# 访问秘钥存储的密码key-store-…

SKU助手

属性SKU助手可以帮你快速选中目标商品属性 下载安装与运行 下载、安装与运行 语雀 如何使用 下面以1688批量自动下单为例&#xff0c;演示用法&#xff0c;同样适用于淘宝天猫拼多多批量自动下单 功能说明 SKU助手弹出的时机 同时满足如下两个条件 Excel提供的SKU与真实…

CAD图纸加密软件——公司核心文件数据防泄密「天锐绿盾」

PC访问地址&#xff1a; isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 数据安全保护系统 数据安全保护系统以全面数据文件安全策略、加解密技术与强制访问控制有机结合为设计思想&#xff0c;对信息媒介上的各种数据资产&#xff0c;实施不同安全等级…

stable diffusion实践操作-提示词-人物属性

系列文章目录 stable diffusion实践操作-提示词 文章目录 系列文章目录前言一、提示词汇总1.1 人物属性11.2 人物属性2 前言 本文主要收纳总结了提示词-人物属性。 一、提示词汇总 1.1 人物属性1 角色类型人物身材胸部头发-发型头发-发色[女仆][霊烏路空][大腿][乳房][呆毛…

Tomcat安装及环境配置

一、首先确认自己是否已经安装JDK WinR打开运行&#xff0c;输入cmd回车&#xff0c;在DOS窗口中输入java 出现这些说明已经安装了&#xff0c;然后就是查看自己的版本 然后输入java -version 可以看到版本是1.8的 如果没有配置java环境变量&#xff0c;打开系统设置&#…

【力扣】55. 跳跃游戏 <贪心>

【力扣】55. 跳跃游戏 给一个非负整数数组 nums &#xff0c;最初位于数组的第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1…

[国产MCU]-W801开发实例-UART控制器

UART控制器 文章目录 UART控制器1、UART控制器介绍2、UART驱动API介绍3、UART使用示例本文将详细如何使用W801的UART模块。 1、UART控制器介绍 UART是一种通用串行 数据总线 ,用于 异步通信 。该总线支持双向通信,可以实现 全双工传输 和接收。 W801 共 6组普通 UART口,通…

OpenCV(九):LUT查找表

LUT&#xff08;Look-Up Table&#xff09;查找表是OpenCV中一种常用的图像处理方法&#xff0c;用于对图像进行像素级别的颜色映射或图像增强操作。LUT查找表可以实现快速、高效的颜色转换和像素操作&#xff0c;尤其在处理大量像素的情况下具有优势。以下是关于OpenCV LUT查找…

Rxjava retryWhen and repeatWhen

retry 当Observable发生错误时接收到onError事件&#xff0c;重新发射数据。可以拦截Throwable 和 Exception。 重载方法如下&#xff1a; // 一直错误&#xff0c;一直重试 public final Observable<T> retry() {return retry(Long.MAX_VALUE, Functions.alwaysTrue()…

JVM-内存溢出的原因、CPU占满的原因

1.内存溢出的原因 OOM的排查思路_oom排查_java排坑日记的博客-CSDN博客 每个进程的内存&#xff08;限制&#xff0c;譬如2G&#xff09;最大堆容量最大方法区容量程序计数器虚拟机栈和本地方法栈。多线程下每个线程栈越大&#xff0c;越容易OOM. 1.堆内存溢出&#xff08;OO…

网易24届内推

【网易】2024届网易互联网秋季校园招聘内推开始啦&#xff01;给你分享我的专属内推邀请函&#xff1a;https://bole.campus.163.com/campus/home?projectId55&type99&isShare1&boleId7b842acc7c2b42db&boleType2&signatured5f2a3dc23bed70777a8be1a14b49…

opendds qos策略之HISTORY

HISTORY策略的含义 顾名思义&#xff0c;该策略会影响历史样本数据的保存策略&#xff0c;即历史样本数据保存策略。这个策略是针对instance的&#xff0c;一个datawriter或者datareader可以根据key成员为设置多个instance&#xff0c;每个instance也可以独立的保存多个历史样…

经管博士必备基础【12】包络定理

当我们知道一个函数的最优解时&#xff0c;我们要求解这一个函数的值函数关于函数中某一个参数的导数&#xff0c;那么就可以使用包络定理。 1. 无约束条件下的包络定理 函数在其极值点处对一个参数&#xff08;参数不是自变量&#xff09;取偏导数的结果&#xff0c;等价于这…

软件工程(十七) 行为型设计模式(三)

1、观察者模式 简要说明 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新 速记关键字 联动,广播消息 类图如下 基于上面的类图,我们来实现一个监听器。类图中的Subject对应我们的被观察对象接口(IObservable),…