基于博弈树的开源五子棋AI教程[6 置换表]

这篇具有很好参考价值的文章主要介绍了基于博弈树的开源五子棋AI教程[6 置换表]。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引子

置换表是记忆化搜索技术的应用,置换表保存了某一盘面的搜索结果。当博弈树搜索遇到相同的局面时可以调用这些信息来减少重复搜索。那么如何设计一个置换表的节点就显得比较重要,本文在经典的置换表节点增加一个显示当前玩家的字段,这一字段补足了zobrist hash单向函数的缺点,如果节点需要使用更浅深度的信息,可以通过迭代的方式来求解,丰富了置换表的信息。

定义

置换表中包换了搜索状态的散列值,剪枝信息,PV信息以及用于迭代获取浅层深度的玩家信息。

//EXACT :表示记录中存储的分数是一个精确的估值分数。
//hashfBETA :表示记录中存储的分数是一个下界(lower bound)。这意味着在搜索中发现了一个分数,它至少是某一分支的分数下限,可能更高。
//hashfALPHA :表示记录中存储的分数是一个上界(upper bound)。这意味着在搜索中发现了一个分数,它至多是某一分支的分数上限,可能更低。
struct NABtransportTableNode {
    quint64 key;
    int value;
    quint8 depth;
    quint8 flags;
    MPoint bestMove;
    MPlayerType lastPlayer; //当前hash状态下,最后一个落子类型

    NABtransportTableNode() : key(InitialZobristHash), value(0), depth(InitialDepth), flags(hashfEmpty),
        bestMove(InvalidMPoint), lastPlayer(PLAYER_NONE){}
};

实现

置换表需要实现三个最主要的功能,获取,添加,清除。根据获取信息的需求不同给出三个函数getNABTranspositionTable用于获取并修改搜索中的剪枝信息,getPVNABTranspositionTable更关注获取某一指定盘面下的搜索结果,getBestMoveNABTranspositionTable更暴力,我只需要当前状下最佳着法即可。

    //置换表[用于负极大搜索,对于其他搜索方式需要修改,未做测试]
    bool getNABTranspositionTable(int &score, int depth, int &alpha, int &beta) const;
    bool getPVNABTranspositionTable(int&score, MPoint& bestMove, int depth, const quint64 &curhash) const;
    bool getBestMoveNABTranspositionTable(MPoint &bestMove) const;
    void appendNABTranspositionTable(int depth, int val, int hashf, MPoint bestMove, MPlayerType lastPlayer);
    void clearNABTranspositionTable(quint8 minCutDepth = InitialDepth);

这里只给出置换表中使用最多的获取节点剪枝信息到置换表中实现。追加表项的方法和清除置换表的方法相对简单,可以移步源代码一观。

//置换表
/*不用标记玩家或者交换上下界:因为评估是根据当前层的玩家决定的,无论是否交换手,
该层玩家始终没有变化,区别只不过是Max还是Min玩家罢了*/
bool ZobristHash::getNABTranspositionTable(int& score, int depth, int &alpha, int &beta) const
{

    if(!globalParam::utilGameSetting.IsOpenTranspositionTable) return false;

    QReadLocker locker(&globalParam::transportTableLock);
    NABtransportTableNode *hashNode = &globalParam::transportTable[m_hash & globalParam::transportTableSizeMask];
    if (hashNode->key == m_hash) {
        //因为不同棋子数目的棋盘分数没有可比性
        if(hashNode->depth < depth) return false;
        int storedScore(-INT_MAX);
        if(hashNode->depth == depth){
            storedScore = hashNode->value;
        }
        else{
            MPoint nextMove = hashNode->bestMove;
            MPlayerType nextPlayer = UtilReservePlayer(hashNode->lastPlayer);
            if(nextMove == InvalidMPoint || nextPlayer == PLAYER_NONE) return false;
            quint64 nextHash = generateHash(m_hash, nextMove, PLAYER_NONE, nextPlayer);

            for (int curDepth = 1; curDepth < depth; ++curDepth) {
                NABtransportTableNode *nextHashNode = &globalParam::transportTable[nextHash & globalParam::transportTableSizeMask];
                if (nextHashNode->key == nextHash) {
                    nextMove = nextHashNode->bestMove;
                    nextPlayer = UtilReservePlayer(nextPlayer);
                    nextHash = generateHash(nextHash, nextMove, PLAYER_NONE, nextPlayer);
                }
            }
            if(getLeafTable(globalParam::AIPlayer, storedScore, nextHash)){
                if(nextPlayer != globalParam::AIPlayer) storedScore *= -1;
            }
        }
        if(hashNode->flags == hashfExact) {//精确值
            score = storedScore;
            return true;
        }
        else if((hashNode->flags == hashfLowerBound) && score > alpha) alpha = score;//更新alpha
        else if ((hashNode->flags == hashfUperBound) && score < beta)  beta = score;//更新beta
        if(alpha >= beta){//剪枝
            score = hashNode->value;
            return true;
        }
    }
    return false;
}

这里实现区别于网上经典的实现方法,一般而言置换表中某一节点的深度越深,得到的信息越可靠。然而在五子棋中并不能一概而论,深度越深,着法越可靠,但是得分就不可靠了。深度不同,叶子棋盘的落子数必然不同,在得分没有归一化的情况下盲目使用是非常不安全的。基于这点发现,实现是通过迭代寻找指定深度,然后通过查找叶子表来求解分数,这样避免了子数不一致进行尴尬局面。
这种实现方式也可以认为是一种时间换空间策略,如果保存某一盘面的所有深度下搜索信息,置换表将成倍数递增,增加了程序的内存负担。

讨论与尾记

通过对极大极小的讨论我们可以知道一点,剪枝算法是安全可靠的,无论剪枝与否,PV路径始终是可以被搜索出来,然而置换表的引入虽加快了搜索,但搜索的不稳定性问题便会凸显出来。在对弈基本技术-置换表篇中指出

当你用置换表时,如果你允许搜索过程根据散列项来截断,那就会产生另一个问题,你的搜索会受“不稳定性”的捆扰。
  不稳定性至少是由以下因素引起的:
  1. 你可能在做6层的搜索,但是如果你在散列项中得到10层搜索的结果,就可能根据这个值来截断。在后来的搜索中,这个散列项被覆盖了,因此你在这个结点上得到了两个不同的值。
  2. Zobrist键值无法记录到达结点的线路,这个结点上不是每条线路都有相同结果的。如果某条线路遇到重复局面,那么散列项的值就会跟路线有关。因为重复局面会导致和局的分值,或者至少不一样的分值。

还有一个原因已经在搜索篇章点出,评分视角的不同,评分会有差异,如果直接使用这些信息截断,极有可能将PV路径拒之门外。文章来源地址https://www.toymoban.com/news/detail-796750.html

到了这里,关于基于博弈树的开源五子棋AI教程[6 置换表]的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

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

    五子棋游戏C语言AI智能算法设计  近来发现编制五子棋游戏很有趣,尤其是AI智能算法很烧脑。网上介绍有什么贪心算法,剪枝算法,博弈树算法等等,不一而足。 对于人机对战的电脑智能应子算法,参阅很多五子棋书籍棋谱和五子棋竞赛的对抗棋谱。我感到白棋的后手防御

    2024年02月06日
    浏览(45)
  • C++ 实现对战AI五子棋

     个人主页: 日刷百题 系列专栏 : 〖C/C++小游戏〗 〖Linux〗 〖数据结构〗   〖 C语言 〗 🌎 欢迎各位 → 点赞 👍+ 收藏 ⭐️+ 留言 📝  ​ ​      为了能够快速上手一门语言,我们往往在学习了基本语法后,采用写一个小项目的方式来加深理解语言的语法及运用,本文采

    2024年02月03日
    浏览(53)
  • 五子棋AI算法和开局定式(直指13式)破解

    五子棋AI算法和开局定式( 直指13式 )破解 先前发了几篇五子棋游戏程序设计的博文,设计了游戏程序,也设计了AI智能奕棋的算法,运行程序检测算法的可行性,完成人机模式游戏功能的设置。这还不够,还要提高算法的实战水平。 对于人机对战的电脑智能应子算法,参阅

    2024年02月20日
    浏览(38)
  • 基于C#的五子棋游戏设计

    目 录 一、 毕业设计内容 3 二、 毕业设计目的 3 三、 工具/准备工作 3 四、 设计步骤和方法 3 (一) 总体设计 3 1. 总体设计思路及设计图 3 2. 界面设计 4 3. 全局变量设计 4 (二) 详细设计 5 1. 刷新棋盘 5 2. 绘制棋盘 5 3. 分步计时 5 4. 显示光标 6 5. 判断胜负 8 6.

    2024年02月04日
    浏览(54)
  • 基于FPGA的五子棋游戏设计

    基于FPGA的五子棋游戏设计 本文基于FPGA设计五子棋游戏,使用按键输入,使用VGA接口输出。五子棋的棋具与围棋相同,棋子分为黑白两色,棋盘为10×10,棋子放置于棋盘线交叉点上。两人对局,各执一色,轮流下一子,先将横、竖或斜线的5个或5个以上同色棋子连成不间断的

    2024年02月05日
    浏览(45)
  • 基于Python的五子棋人机对战

    在之前的博文基于tkinter的五子棋游戏中使用tkinter做了一个简单的五子棋游戏,只能实现人人对战,后来想着加上人机对战的功能。 不过,最初想想还是挺麻烦的,计算机怎么评估当前的棋局,找到最佳或者较佳的落子点呢,脑子真是越来越不灵光了。站在巨人的肩膀上,科

    2024年02月04日
    浏览(41)
  • 基于Python的pygame库的五子棋游戏

    2024年04月09日
    浏览(41)
  • 基于Java的五子棋游戏的设计与实现

    基于 Java 的五子棋游戏的设计 摘  要 五子棋作为一个棋类竞技运动,在民间十分流行,为了熟悉五子棋规则及技巧,以及研究简单的人工智能,决定用Java开发五子棋游戏。主要完成了人机对战和玩家之间联网对战2个功能。网络连接部分为Socket编程应用,客户端和服务器端的

    2023年04月23日
    浏览(60)
  • 基于Android Studio的五子棋游戏的简单设计

    【摘要】: 随着时代的发展,现代科技的飞跃,我们的日常娱乐生活变得丰富多彩。而手机游戏被业内人士称为继通信之后的有一座“金矿”,手机休闲娱乐应用将成为PC休闲娱乐之后又一重要业务增长点。本文针对该趋势,从用户需求出发,基于Android对五子棋游戏进行设计

    2024年02月11日
    浏览(36)
  • 基于C#开发五子棋游戏 大作业 课程设计源码

    基于C#开发五子棋游戏(大作业/课程设计) 开发环境:  Windows操作系统 开发工具: Microsoft Visual Studio 运行效果图:    基于C#开发五子棋游戏(大作业/课程设计) 开发环境:  Windows操作系统 开发工具:Microsoft Visual Studio 基于C#开发五子棋游戏(大作业/课程设计) 开发环境

    2024年02月04日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包