zoukankan      html  css  js  c++  java
  • 五子棋AI的思路

    隔了一年才把AI思路给写了。。。

    需求分析与设计方案:http://www.cnblogs.com/songdechiu/p/4951634.html

    如需整个工程,移步http://download.csdn.net/detail/sdzuiaidanpianji/9452789

    如没有积分,可在百度网盘下载:

    链接: https://pan.baidu.com/s/1UXzhEDWXfsb6EbFOzRVuqg 提取码: ezm6

    注:全文,都默认以黑方为己方。

    一、五子棋基本棋型

    参考资料:http://game.onegreen.net/wzq/HTML/142336.html

    最常见的基本棋型大体有以下几种:连五,活四,冲四,活三,眠三,活二,眠二

    ①连五:顾名思义,五颗同色棋子连在一起,不需要多讲。
    图2-1  

    ②活四:有两个连五点(即有两个点可以形成五),图中白点即为连五点。
    稍微思考一下就能发现活四出现的时候,如果对方单纯过来防守的话,是已经无法阻止自己连五了。
    图2-2  


    ③冲四:有一个连五点,如下面三图,均为冲四棋型。图中白点为连五点。
    相对比活四来说,冲四的威胁性就小了很多,因为这个时候,对方只要跟着防守在那个唯一的连五点上,冲四就没法形成连五。
    图2-3  图2-4  图2-5  


    ④活三:可以形成活四的三,如下图,代表两种最基本的活三棋型。图中白点为活四点。
    活三棋型是我们进攻中最常见的一种,因为活三之后,如果对方不以理会,将可以下一手将活三变成活四,而我们知道活四是已经无法单纯防守住了。所以,当我们面对活三的时候,需要非常谨慎对待。在自己没有更好的进攻手段的情况下,需要对其进行防守,以防止其形成可怕的活四棋型。
    图2-6  图2-7 

    其中图2-7中间跳着一格的活三,也可以叫做跳活三

    ⑤眠三只能够形成冲四的三,如下各图,分别代表最基础的六种眠三形状。图中白点代表冲四点。眠三的棋型与活三的棋型相比,危险系数下降不少,因为眠三棋型即使不去防守,下一手它也只能形成冲四,而对于单纯的冲四棋型,我们知道,是可以防守住的。
    图2-8  图2-9  图2-10 

    2-11 图2-12 图2-13 

    如上所示,眠三的形状是很丰富的。对于初学者,在下棋过程中,很容易忽略不常见的眠三形状,例如图2-13所示的眠三。

    有新手学了活三眠三后,会提出疑问,说活三也可以形成冲四啊,那岂不是也可以叫眠三?
    会提出这个问题,说明对眠三定义看得不够仔细:眠三的的定义是,只能够形成冲四的三。而活三可以形成眠三,但也能够形成活四。

    此外,在五子棋中,活四棋型比冲四棋型具有更大的优势,所以,我们在既能够形成活四又能够形成冲四时,会选择形成活四。

    温馨提示:学会判断一个三到底是活三还是眠三是非常重要的。所以,需要好好体会。
    后边禁手判断的时候也会有所应用。 

    ⑥活二:能够形成活三的二,如下图,是三种基本的活二棋型。图中白点为活三点。
    活二棋型看起来似乎很无害,因为他下一手棋才能形成活三,等形成活三,我们再防守也不迟。但其实活二棋型是非常重要的,尤其是在开局阶段,我们形成较多的活二棋型的话,当我们将活二变成活三时,才能够令自己的活三绵绵不绝微风里,让对手防不胜防。
    图2-14  图2-15  图2-16 

    ⑦眠二:能够形成眠三的二。图中四个为最基本的眠二棋型,细心且喜欢思考的同学会根据眠三介绍中的图2-13找到与下列四个基本眠二棋型都不一样的眠二。图中白点为眠三点。
    图2-17 图2-18  
    图2-19  图2-20 

    二、打分机制

    1、打分思路

    (1)先对整个棋盘形势进行打分,存在两个矩阵(二维数组)上

    (2)一个为我方的形势分数,一个为敌方的形势分数

    (3)找出我方形势分数的最大值mymaxscore及其对应的位置,找出敌方形势的最大值hismaxscore及其对应的位置

    (4)判断是进攻还是防守:

    如果mymaxscore>=hismaxscore,则进攻,下我方形势最大值mymaxscore对应的位置;如果有多个mymaxscore相等,则下这几个对应位置上hismaxscore最大的位置。

    否则,防守,下敌方形势最大值hismaxscore对应的位置。如果有多个hismaxscore相等,则下这几个对应位置上mymaxscore最大的位置。

    2、打分方法

    (1)在棋盘空位置上添加要判断放的棋子

    (2)取出以空位置为中心的4个方向(上,下,左,右),每个方向以该位置为中心两边各取4个格子信息。如下所示:

    注:中心位置都是预放置,当前判断的时候位置还是空的

    (3)四个方向都判断其棋型,是否连五,活四,冲四,活三,眠三,活二,眠二等中的一种

    (4)最后综合四个方向的棋型,对该位置进行打分。

    3、打分规定

    注:机器方即为本方,人方即为敌方

    综合四个方向后:

    判断是否能5, 如果是机器方的话给予100000分,如果是人方的话给予100000 分;

    判断是否能成4或者是双死4或者是43,如果是机器方的话给予10000分,如果是人方的话给予10000分;

    判断是否已成双活3,如果是机器方的话给予5000分,如果是人方的话给予5000 分;

    判断是否成33(高级),如果是机器方的话给予1000分,如果是人方的话给予1000 分;

    判断是否能成4,如果是机器方的话给予500分,如果是人方的话给予500分;

    判断是否能成低级死4,如果是机器方的话给予400分,如果是人方的话给予400分;

    判断是否能成单活3,如果是机器方的话给予100分,如果是人方的话给予100分;

    判断是否能成跳活3,如果是机器方的话给予90分,如果是人方的话给予90分;

    判断是否能成双活2,如果是机器方的话给予50分,如果是人方的话给予50分;

    判断是否能成2,如果是机器方的话给予10分,如果是人方的话给予10分;

    判断是否能成低级活2,如果是机器方的话给予9分,如果是人方的话给予9分;

    判断是否能成3,如果是机器方的话给予5分,如果是人方的话给予5分;

    判断是否能成2,如果是机器方的话给予2分,如果是人方的话给予2分。

    判断是否其他情况(nothing),如果是机器方的话给予1分,如果是人方的话给予1分。

    有棋子,则直接0分。

    4、棋型判断方法

    (1)在空位置上添加要判断色的棋子

    (2)取出以空位置为中心的,要判断单个方向(上,下,左,右中的一种)上的,两边各4个位置信息,形成

    (3)先找出与中心点相连而成的连续子有多少个

    (4)再进行下一步判断

    注:以下说明都以黑方为例子

    •  中心点相连而成的连续子有5个:不管哪种情况,都可以直接判断为成5

    • 中心点相连而成的连续子有4个

      • 两边均空,活4

    • 1、2均非空,则nothing

    • 1、2只有一个为空,则死4

    • 中心点相连而成的连续子有3个:

     

    • 2,3均空时:
      • 1,4均为白子,则为死3

    • 1,4只要有一个空,则为活3

    • 1,4只要有一个黑,则为死4 

     

    以此类推,根据第一部分中的五子棋棋型去判断棋型类型。

    具体可直接查看源码部分。

     单个方向的棋型判断:

    if (count >= 5)//中心线5连
            return WIN5;//5连珠
    
        if (count == 4)//中心线4连
        {
            if (colorleft == NOTHINGFLAG && colorright == NOTHINGFLAG)//两边断开位置均空
                return ALIVE4;//活四
            else if (colorleft == hiscolor && colorright == hiscolor)//两边断开位置均非空
                return NOTHREAT;//没有威胁
            else if (colorleft == NOTHINGFLAG || colorright == NOTHINGFLAG)//两边断开位置只有一个空
                return DIE4;//死四
        }
    
        if (count == 3) {//中心线3连
            int colorleft1 = chess[left - 1];
            int colorright1 = chess[right + 1];
    
            if (colorleft == NOTHINGFLAG && colorright == NOTHINGFLAG)//两边断开位置均空
            {
    
                if (colorleft1 == hiscolor && colorright1 == hiscolor)//均为对手棋子
                    return DIE3;
                else if (colorleft1 == mycolor || colorright1 == mycolor)//只要一个为自己的棋子
                    return LOWDIE4;
                else if (colorleft1 == NOTHINGFLAG || colorright1 == NOTHINGFLAG)//只要有一个空
                    return ALIVE3;
    
            }
            else if (colorleft == hiscolor && colorright == hiscolor)//两边断开位置均非空
            {
                return NOTHREAT;//没有威胁
            }
            else if (colorleft == NOTHINGFLAG || colorright == NOTHINGFLAG)//两边断开位置只有一个空
            {
    
                if (colorleft == hiscolor) {//左边被对方堵住
                    if (colorright1 == hiscolor)//右边也被对方堵住
                        return NOTHREAT;
                    if (colorright1 == NOTHINGFLAG)//右边均空
                        return DIE3;
                    if (colorright1 == mycolor)
                        return LOWDIE4;
    
                }
                if (colorright == hiscolor) {//右边被对方堵住
                    if (colorleft1 == hiscolor)//左边也被对方堵住
                        return NOTHREAT;
                    if (colorleft1 == NOTHINGFLAG)//左边均空
                        return DIE3;
                    if (colorleft1 == mycolor)//左边还有自己的棋子
                        return LOWDIE4;
                }
            }
        }
    
        if (count == 2) {//中心线2连
            int colorleft1 = chess[left - 1];
            int colorright1 = chess[right + 1];
            int colorleft2 = chess[left - 2];
            int colorright2 = chess[right + 2];
    
            if (colorleft == NOTHINGFLAG && colorright == NOTHINGFLAG)//两边断开位置均空
            {
                if ((colorright1 == NOTHINGFLAG && colorright2 == mycolor) ||
                    (colorleft1 == NOTHINGFLAG && colorleft2 == mycolor))
                    return DIE3;//死3
                else if (colorleft1 == NOTHINGFLAG && colorright1 == NOTHINGFLAG)
                    return ALIVE2;//活2
    
                if ((colorright1 == mycolor && colorright2 == hiscolor) ||
                    (colorleft1 == mycolor && colorleft2 == hiscolor))
                    return DIE3;//死3
                 
                if ((colorright1 == mycolor && colorright2 == mycolor) ||
                    (colorleft1 == mycolor && colorleft2 == mycolor))
                    return LOWDIE4;//死4
    
                if ((colorright1 == mycolor && colorright2 == NOTHINGFLAG) ||
                    (colorleft1 == mycolor && colorleft2 == NOTHINGFLAG))
                    return TIAO3;//跳活3
                //其他情况在下边返回NOTHREAT
            }
            else if (colorleft == hiscolor && colorright == hiscolor)//两边断开位置均非空
            {
                return NOTHREAT;
            }
            else if (colorleft == NOTHINGFLAG || colorright == NOTHINGFLAG)//两边断开位置只有一个空
            {
                if (colorleft == hiscolor) {//左边被对方堵住
                    if (colorright1 == hiscolor || colorright2 == hiscolor) {//只要有对方的一个棋子
                        return NOTHREAT;//没有威胁
                    }
                    else if (colorright1 == NOTHINGFLAG && colorright2 == NOTHINGFLAG) {//均空
                        return DIE2;//死2
                    }
                    else if (colorright1 == mycolor && colorright2 == mycolor) {//均为自己的棋子
                        return LOWDIE4;//死4
                    }
                    else if (colorright1 == mycolor || colorright2 == mycolor) {//只有一个自己的棋子
                        return DIE3;//死3
                    }
                }
                if (colorright == hiscolor) {//右边被对方堵住
                    if (colorleft1 == hiscolor || colorleft2 == hiscolor) {//只要有对方的一个棋子
                        return NOTHREAT;//没有威胁
                    }
                    else if (colorleft1 == NOTHINGFLAG && colorleft2 == NOTHINGFLAG) {//均空
                        return DIE2;//死2
                    }
                    else if (colorleft1 == mycolor && colorleft2 == mycolor) {//均为自己的棋子
                        return LOWDIE4;//死4
                    }
                    else if (colorleft1 == mycolor || colorleft2 == mycolor) {//只有一个自己的棋子
                        return DIE3;//死3
                    }
                }
            }
        }
            
        if (count == 1) {//中心线1连
            int colorleft1 = chess[left - 1];
            int colorright1 = chess[right + 1];
            int colorleft2 = chess[left - 2];
            int colorright2 = chess[right + 2];
            int colorleft3 = chess[left - 3];
            int colorright3 = chess[right + 3];
    
            if (colorleft == NOTHINGFLAG && colorleft1 == mycolor && 
                colorleft2 == mycolor && colorleft3 == mycolor)
                return LOWDIE4;
            if (colorright == NOTHINGFLAG && colorright1 == mycolor && 
                colorright2 == mycolor && colorright3 == mycolor)
                return LOWDIE4;
    
            if (colorleft == NOTHINGFLAG && colorleft1 == mycolor && 
                colorleft2 == mycolor && colorleft3 == NOTHINGFLAG && colorright == NOTHINGFLAG)
                return TIAO3;
            if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
                colorright2 == mycolor && colorright3 == NOTHINGFLAG && colorleft == NOTHINGFLAG)
                return TIAO3;
    
            if (colorleft == NOTHINGFLAG && colorleft1 == mycolor &&
                colorleft2 == mycolor && colorleft3 == hiscolor && colorright == NOTHINGFLAG)
                return DIE3;
            if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
                colorright2 == mycolor && colorright3 == hiscolor && colorleft == NOTHINGFLAG)
                return DIE3;
    
            if (colorleft == NOTHINGFLAG && colorleft1 == NOTHINGFLAG &&
                colorleft2 == mycolor && colorleft3 == mycolor)
                return DIE3;
            if (colorright == NOTHINGFLAG && colorright1 == NOTHINGFLAG &&
                colorright2 == mycolor && colorright3 == mycolor)
                return DIE3;
    
            if (colorleft == NOTHINGFLAG && colorleft1 == mycolor &&
                colorleft2 == NOTHINGFLAG && colorleft3 == mycolor)
                return DIE3;
            if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
                colorright2 == NOTHINGFLAG && colorright3 == mycolor)
                return DIE3;
    
            if (colorleft == NOTHINGFLAG && colorleft1 == mycolor &&
                colorleft2 == NOTHINGFLAG && colorleft3 == NOTHINGFLAG && colorright == NOTHINGFLAG)
                return LOWALIVE2;
            if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
                colorright2 == NOTHINGFLAG && colorright3 == NOTHINGFLAG && colorleft == NOTHINGFLAG)
                return LOWALIVE2;
    
            if (colorleft == NOTHINGFLAG && colorleft1 == NOTHINGFLAG &&
                colorleft2 == mycolor && colorleft3 == NOTHINGFLAG && colorright == NOTHINGFLAG)
                return LOWALIVE2;
            if (colorright == NOTHINGFLAG && colorright1 == NOTHINGFLAG &&
                colorright2 == mycolor && colorright3 == NOTHINGFLAG && colorleft == NOTHINGFLAG)
                return LOWALIVE2;
    
            //其余在下边返回没有威胁
    
        }
        return NOTHREAT;//返回没有威胁

    综合四个方向评分:

    if (situation.win5 >= 1)
            return LevelOne;//赢5
    
        if (situation.alive4 >= 1 || die4 >= 2 || (die4 >= 1 && alive3 >= 1))
            return Leveltwo;//活4 双死4 死4活3
    
        if (alive3 >= 2)
            return Levelthree;//双活3
    
        if (situation.die3 >= 1 && situation.alive3 >= 1)
            return Levelfour;//死3高级活3
    
        if (situation.die4 >= 1)
            return Levelfive;//高级死4
    
        if (situation.lowdie4 >= 1)
            return Levelsix;//低级死4
    
        if (situation.alive3 >= 1)
            return Levelseven;//单活3
    
        if (situation.tiao3 >= 1)
            return LevelEight;//跳活3
    
        if (alive2 >= 2)
            return LevelNight;//双活2
    
        if (situation.alive2 >= 1)
            return LevelTen;//活2
    
        if (situation.lowalive2 >= 1)
            return LevelEleven;//低级活2
    
        if (situation.die3 >= 1)
            return LevelTwelve;//死3
    
        if (situation.die2 >= 1)
            return LevelThirteen;//死2
    
        return LevelFourteen;//没有威胁
  • 相关阅读:
    CSS3 动画-- 鼠标移上去,div 会旋转、放大、移动
    jquery 微信端 点击物理返回按钮,弹出提示框
    H5 canvas pc 端米字格 写字板
    【三剑客】awk函数
    【三剑客】awk运算符
    【三剑客】awk命令2
    【三剑客】awk命令
    磁盘
    用户管理
    定时任务Crond
  • 原文地址:https://www.cnblogs.com/songdechiu/p/5768999.html
Copyright © 2011-2022 走看看