五子棋游戏禁手算法的改进
五子棋游戏禁手算法的改进
五子棋最新的禁手规则:
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分就是冲四活三必胜点。
图例:
黄色点是计分点,紫色点是禁手点

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 ( )
图例:
在下拉菜单设置禁手

上图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**
相关文章:
五子棋游戏禁手算法的改进
五子棋游戏禁手算法的改进 五子棋最新的禁手规则: 1.黑棋禁手判负、白棋无禁手。黑棋禁手有“三三”(包括“四三三”)、“四四”(包括“四四三”)和“长连”。黑棋只能以“四三”取胜。 2.黑方…...
基于 Debian 12 的 Devuan GNU+Linux 5 为软件自由爱好者而生
导读Devuan 开发人员宣布发布 Devuan GNULinux 5.0 “代达罗斯 “发行版,它是 Debian GNU/Linux 操作系统的 100% 衍生版本,不包含 systemd 和相关组件。 Devuan GNULinux 5 基于最新的 Debian GNU/Linux 12 “书虫 “操作系统系列,采用长期支…...
算法系列-力扣234-回文链表判定
回文链表判定 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 方法一:栈反转对比法 解题思路:找到中间节点后用栈辅助反转对比 解题方法࿱…...
算法通关村——海量数据场景下的热门算法题的处理方法
1. 从40个亿中产生一个不存在的整数 题目要求:给定一个输入文件,包含40亿个非负整数,请设计一个算法,产生一个不存在该文件中的整数,假设你有1GB的内存来完成这项任务。 ● 进阶:如果只有10MB的内存可用&a…...
【C++从0到王者】第二十五站:多继承的虚表
文章目录 前言一、多继承的虚函数表二、菱形继承与菱形虚拟继承的虚函数表1.菱形继承2.菱形虚拟继承的虚函数表 三、抽象类1.抽象类的概念2.接口继承与实现继承 总结 前言 其实关于单继承的虚函数表我们在上一篇文章中已经说过了,就是派生类中的虚表相当于拷贝了一…...
老程序员教你如何笑对问题,轻松培养逻辑思考和解决问题的能力
原文链接 老程序员教你如何笑对问题,轻松培养逻辑思考和解决问题的能力 故事发生在一个阳光明媚的午后,我们的主人公,老李,一位拥有十年工作经验的 Python 老程序员,正悠哉地在喝着咖啡。 这时&#x…...
Omni Recover for Mac(专业的iPhone数据恢复软件)
Omni Recover for Mac是一款专业的Mac数据恢复软件,能够帮助用户快速找回被误删除、格式化、病毒攻击等原因造成的文件和数据,包括图片、视频、音频、文档、邮件、应用程序等。同时,Omni Recover for Mac还具有数据备份和清理功能,…...
视频垂直镜像播放,为您的影片带来新鲜感
大家好!在制作视频时,我们常常希望能够给观众带来一些新鲜感和独特的视觉效果。而垂直镜像播放是一个能够让您的影片与众不同的技巧。然而,传统的视频剪辑软件往往无法直接实现视频的垂直镜像播放,给我们带来了一些困扰。现在&…...
十一、MySQL(DQL)聚合函数
1、聚合函数 注意:在使用聚合函数时,所有的NULL是不参与运算的。 2、实际操作: (1)初始化表格 (2)统计该列数据的个数 基础语法: select count(字段名) from 表名; ;统…...
C语言:三子棋小游戏
简介: 目标很简单:实现一个 三子棋小游戏。三子棋大家都玩过,规则就不提及了。本博文中实现的三子棋在对局中,电脑落子是随机的,不具有智能性,玩家的落子位置使用键盘输入坐标。下面开始详细介绍如何实现一…...
JAVA - PO DTO 生成器
PO DTO 生成器 假设你是一个Java 高级程序员,我会提供一些信息,你需要帮我自动生成Java的PO、DTO 对象。 这些信息有着固定的形式,第一行是对象的类名,其后的每一行都是该对象的属性(简称“属性”)。 对于我属性,格式…...
tcpdump
TCPDump是一个用于抓取网络数据包的命令行工具。它可以帮助网络管理员和开发人员分析网络流量、故障排除以及安全问题。下面是一些TCPDump的详细用法: 基本用法: 监听指定网络接口:tcpdump -i eth0通过IP地址过滤:tcpdump host 19…...
数据通信——传输层TCP(可靠传输原理的ARQ)
引言 上一篇讲述了停止等待协议的工作流程,在最后提到了ARQ自动请求重传机制。接下来,我们就接着上一篇的篇幅,讲一下ARQ这个机制 还是这个图来镇楼 ARQ是什么? 发送端对出错的数据帧进行重传是自动进行的,因而这种…...
Compose - 交互组合项
按钮 Button OutLinedButton带外边框、TextButton只是文字、IconButton只是图标形状。 Button(onClick { }, //点击回调modifier Modifier,enabled true, //启用或禁用interactionSource MutableInteractionSource(),elevation ButtonDefaults.elevatedButtonElevation( /…...
【发版公告】Virbox Protector 3.1.3.19051 发版- elf 文件支持导入表保护
深盾安全-软件保护工具 Virbox Protector 3 ( 3.1.3.19051)迎来了版本升级.本次升级支持了 elf 文件导入表保护。 以下是本次 Virbox Protector 发版的主要功能: 新功能 1. ELF格式的程序支持导入表保护(Beta);; 2…...
点云数据做简单的平面的分割 三维场景中有平面,杯子,和其他物体 实现欧式聚类提取 对三维点云组成的场景进行分割
点云分割是根据空间,几何和纹理等特征对点云进行划分,使得同一划分内的点云拥有相似的特征,点云的有效分割往往是许多应用的前提,例如逆向工作,CAD领域对零件的不同扫描表面进行分割,然后才能更好的进行空洞修复曲面重建,特征描述和提取,进而进行基于3D内容的检索,组合…...
C++之std::search应用实例(一百八十九)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
一文详解 requests 库中 json 参数和 data 参数的用法
在requests库当中,requests请求方法,当发送post/put/delete等带有请求体的请求时,有json和data2个参数可选。 众所周知,http请求的请求体格式主要有以下4种: application/json applicaiton/x-www-from-urlencoded mu…...
Django学习笔记-AcApp端授权AcWing一键登录
笔记内容转载自 AcWing 的 Django 框架课讲义,课程链接:AcWing Django 框架课。 AcApp 端使用 AcWing 一键授权登录的流程与之前网页端的流程一样,只有申请授权码这一步有一点细微的差别: 我们在打开 AcApp 应用之后会自动向 AcW…...
如何在小红书进行学习直播
诸神缄默不语-个人CSDN博文目录 因为我是从B站开始的,所以一些直播常识型的东西请见我之前写的如何在B站进行学习直播这一篇。 本篇主要介绍一些小红书之与B站不同之处。 小红书在手机端是可以直接点击“”选择直播的。 文章目录 1. 电脑直播-小红书直播软件2. 电…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
