zoukankan      html  css  js  c++  java
  • 五子棋(人机对弈)——Java权值法五子棋博弈

    五子棋人机博弈


    五子棋,人与人之间博弈,我们不用考虑太多,都是玩家自动思考。
    但是如果我们要玩一个单机的五子棋,实现人机的对战,那么我就得“帮”电脑考虑下走哪步了。
    实现的方法大概有三种:

    1. 最大权值法
    2. 决策树法
    3. 机器学习训练

    这里我们主要针对第一种方法讨论下,大致思路如下:

    1. 我们绘制好一个棋盘后,假定大小为 15*15;
    2. 下棋之前,对于棋盘中的每个空位,我们每都替电脑人“掂一掂”下在哪里合算;(估权过程)
    3. 对每个空位按照规则都计算完权重,我们找出权重最大的位置,此位置就是npc落子位置

    那么现在的问题就是,这个权重的计算规则是怎样的呢?
    首先,我们思考一下人是怎么下子的。

    1. 当该位置四周为空时,这个位置落子可能就不是那么有意义;
    2. 我们最大可能地去实现将棋子相连,若该位置四周已出现一条连线,则连子数越多,该子越重要
    3. 就算一条线有很多子已经相连,如果该线的一端被堵住,那么该线的重要程度降低,我们称之为眠连,otherwise,两端都没堵住我们称之为活连。

    现在我们来将棋子相连的情况进行下归类赋权

    空子位置我们用 “0” 表示,白子用“2”表示,黑子用“1”表示;
    我们主要分为以下几种情况:

    定义 棋子相连情况 权值
    活一连 010、020 40
    活二连 0110、0220 400
    活三连 01110、02220 3000
    活四连 011110、022220 10000
    眠一连 012、021 20
    眠二连 0112、0221 200
    眠三连 01112、02221 500
    眠四连 011112、022221 3000

    主要被分为了以上几类,当然可以考虑更多以使你的npc更加“智能”;

    现在考虑算法

    对于每个空位,我们从四个方向进行考察:

    • 水平
    • 竖直
    • 左斜
    • 右斜

    我们以水平方向为例进行代码考察:

        int go[row][column];   //记录每个点的落子情况
        int weightarr[row][column];  //记录每个空位的权值 
    
        for piece in chessboard{
            if(piece为空){
                key1="0";    //记录空位左边连子情况
                key2="0";    //记录空位右边连子情况
                (i,j)为空位坐标
                ux=i;uy=j;   //(ux,uy)记录左边连子边界
                dx=i;dy=j;   //(dx,dy)记录右边边界
                first1=0;
                first2=0;    
                //first1 记录空位左边第一个子颜色,first2记录右边第一个颜色
                //while的目的在于找到最多的颜色相同的连线
                while(左边不越界){
                    int first=go[i-1][j].color;
                    first1=first;
                    if(first==0) break;   //如果空位相邻也为空,退出
                    else {      //如果不为空位
                        --ux;
                        if(颜色和first相同) {
                            key1+=go[ux][uy].color;
                        }
                        else {
                            key1+=go[ux][uy].color;
                            break;
                        }
                    }   
                }
                while(右边不越界){
                        ...   //和上面同理
                }
                value1=左边连线权值;
                value2=右边连线权值;
                if(左右连线颜色相同) 权值翻倍;
                weightarr[i][j]+=该方向权值;
    
                //同理,依此计算 左斜,右斜,竖直情况;
            }   
        }
    

    要注意的是,因为对于每个大方向,比如说水平方向,我们以该空位做间断点分了水平左和水平右,当水平左和水平右的颜色相同时,权值注意要加强,因为比如说隔开的2个黑子和1个黑子填上空位可以变成4个黑子;

    大家可以具体自己重新设置权值,添加更多情况。
    我们将具体实现代码放在github中,供大家参考:
    https://github.com/Gray-way/Gobang

  • 相关阅读:
    RedHat7安装NetCore环境并发布网站
    【WPF学习】第四十二章 透明
    细说枚举
    js获取ip地址,操作系统,浏览器版本等信息,可兼容
    js实现数据流(日志流,报警信息等)滚动展示,并分页(含实现demo)
    js实现点击copy,可兼容
    js实现htmlToWordDemo
    H5 web 存储之 Webstorage
    已发布的WEB项目,如何挂在服务器或者本机的IIS下
    Nuget打包没有注释显示
  • 原文地址:https://www.cnblogs.com/gujiewei/p/9670587.html
Copyright © 2011-2022 走看看