中国象棋AI实现——alpha-beta剪枝

一、简介

这是基于alpha-bata剪枝算法实现的一个中国象棋博弈程序,可以实现人机交互,AI具有初级的智能,可以应对一般的象棋新手。
界面用最基本的html+css+js实现,参考自中国象棋界面素材

AI逻辑同样用js实现,项目地址。

二、算法实现

在让AI自动做出落子决定前,必须提供一个方法让其判断哪种走法较优,也即需要一个局面评估函数,能够返回一个表示局面好坏的分数,对于AI方,这个分数越大越好。

//有一点需要强调:alpha-beta剪枝过程中走棋的双方可能会变化,但估分的标准一直是以黑方即AI方为准,黑方希望估值最大,红方希望估值最小。
function evaluate() {var score = 0;score += SingleChessScore();score += ChouJu();score += ShuangPao();return score;
}

目前的局面评估只包括一个主要部分和两个分支部分,分别为单棋子棋力判断、抽车将军判断和双炮将军判断,后续可能会在github仓库上更新更多的局面评估方法。
主要部分SingleChessScore依次考虑棋面上每个单独的子,由它们本身的属性和所在位置决定它们的分数,黑方取正值,红方取负值,并累加起来。

棋力表部分参考自eleeye。
以马的分数表为例,马的分数表如下:

var Ma = [[90, 90, 90, 96, 90, 96, 90, 90, 90],[90, 96,103, 97, 94, 97,103, 96, 90],[92, 98, 99,103, 99,103, 99, 98, 92],[93,108,100,107,100,107,100,108, 93],[90,100, 99,103,104,103, 99,100, 90],[90, 98,101,102,103,102,101, 98, 90],[92, 94, 98, 95, 98, 95, 98, 94, 92],[93, 92, 94, 95, 92, 95, 94, 92, 93],[85, 90, 92, 93, 78, 93, 92, 90, 85],[88, 50, 90, 88, 90, 88, 90, 50, 88]//马的两个初始位置权值设小一点,防止AI的炮“盲目攻击马”
];

有了棋面评估函数,AI现在可以遍历每一个己方棋子的每一种走法,并判断该走法的分数,基于这个,已经可以实现一个贪心算法,该算法只考虑当前的一步,并选择对自己最有利的走法。

V1.0 贪心算法,AI是黑方
function AImove() {var max_score = -100000000;var from = [];var to = [];var can_eat = false;for (var j = 0; j < 10; ++j) {for (var i = 0; i < 9; ++i) {if (map[j][i] < 0) {var t = WhatSpace(j, i);//返回棋子的属性var tmap = WhereCan(j,i,t);//返回能走的位置,分为能吃和不能吃(即目的棋子或空)if(tmap!=null && tmap.length>0) {for(var q=0;q<tmap.length;q++){var dest = tmap[q];var tmp = map[dest[0]][dest[1]];map[dest[0]][dest[1]] = map[j][i];map[j][i] = 0;var score = evaluate(map);if (score > max_score) {from[0] = j;from[1] = i;to[0] = dest[0];to[1] = dest[1];max_score = score;can_eat = tmp == 0 ? false : true;}map[j][i] = map[dest[0]][dest[1]];map[dest[0]][dest[1]] = tmp;}}}}}console.log("now best: " + max_score);if (can_eat) {eat(from[0], from[1], to[0], to[1]);}else {move(from[0], from[1], to[0], to[1]);}}

显然,这样的AI智能还不够,所以下一步我们用alpha-beta对其进行优化,使其能考虑接下来几步内的较优走法。

算法框架如下:

function alpha-beta(depth, alpha, beta) {对于每一个棋子的每一种走法修改局面为该走法落子后的局面ret = alpha-beta(depth + 1, alpha, beta)修改局面回落子前的局面if 在MAX层, alpha = max(alpha, ret)else if 在MIN层, beta = min(beta, ret)if beta <= alpha return (在MAX层 ? alpha : beta)return (在MAX层 ? alpha : beta)
}

具体代码如下:

//V2.0 alpha-beta算法,仍然假设AI是黑方
function AImove() {console.log("best: " + alpha_beta(1, -1e9, 1e9));if (AIcan_eat) {eat(AIfrom[0], AIfrom[1], AIto[0], AIto[1]);}else {move(AIfrom[0], AIfrom[1], AIto[0], AIto[1]);}}
var AIfrom = [];
var AIto = [];
var AIcan_eat = false;
function alpha_beta(depth, alpha, beta) {if (depth >= 5) return evaluate(map);for (var j = 0; j < 10; ++j) {for (var i = 0; i < 9; ++i) {if ((depth & 1) == 1 && map[j][i] < 0 || (depth & 1) == 0 && map[j][i] > 0) {//哪些棋子能走var t = WhatSpace(j, i);//返回棋子的属性var tmap = WhereCan(j,i,t);//返回能走的位置,分为能吃和不能吃(即目的棋子或空)if(tmap!=null && tmap.length>0) {for(var q=0;q<tmap.length;q++){var dest = tmap[q];var tmp = map[dest[0]][dest[1]];map[dest[0]][dest[1]] = map[j][i];map[j][i] = 0;ret = alpha_beta(depth + 1, alpha, beta);if (depth & 1 == 1) {if (ret > alpha) {alpha = ret;if (depth == 1) {AIfrom[0] = j;AIfrom[1] = i;AIto[0] = dest[0];AIto[1] = dest[1];AIcan_eat = !(tmp == 0);}}}else {beta = Math.min(beta, ret);}map[j][i] = map[dest[0]][dest[1]];map[dest[0]][dest[1]] = tmp;if (beta <= alpha) return (depth & 1 == 1 ? alpha : beta);     }}}}}return (depth & 1 == 1 ? alpha : beta);}

可能每次都走同一种走法会使AI显得过于死板,所以在返回到第一层的所有结果中加入一点随机性

if (depth & 1 == 1) {if (ret > alpha) {if (depth == 1) {console.log(j + '-' + i + getCText(dest[0],dest[1])[0] + "移动到 " + dest[0] + '-' + dest[1])//如果新的最好结果比原最好结果只大了5分以内,以某种概率保持原最好结果,以提高随机性if (ret - alpha < 5 && Math.random() > 0.8) {console.log("跨过最优解法");map[j][i] = map[dest[0]][dest[1]];map[dest[0]][dest[1]] = tmp;continue;}AIfrom[0] = j;AIfrom[1] = i;AIto[0] = dest[0];AIto[1] = dest[1];AIcan_eat = !(tmp == 0);}alpha = ret;}//console.log(j + " " + i + " " + "alpha: " + alpha);
}

为了提高玩家体验,增加了悔棋功能。
用一个栈保存之前走过的所有步数,每次悔棋从栈中弹出并恢复。

三、结果分析

alpha-beta剪枝层数大于4时,AI表现出较好的智能,能够与普通人类进行对战且有较大的胜算。由于象棋游戏本身有较大的不确定性,因此以下结果仅供参考。

对战局数 AI获胜局数 胜率
10 8 80%
搜索深度 每步用时
4 <0.1s
5 <0.5s
6 1~3s

AI程序与成熟的象棋AI程序相比仍然有很多不足,主要体现在以下方面:

  • 搜索层数过低
    成熟的象棋程序中的AI算法一般能搜索到数十层的深度,这是我的算法和硬件设备所远远达不到的。
  • 套路不足
    尽管我已经为重炮将军和将军抽车这些套路加到棋力评估当中,仍然有很多危险的套路是AI所不能识别和避免的。
  • 多棋子联动性差
    棋面评估目前只限制在单子棋力评估,所以不能很好地联动多个棋子,造成较大的杀伤。但由于alpha-beta剪枝本身的特性,即使专门写两个或两个以上棋子的联动也不能有很大的改进,所以我放弃了优化这个方向。

一些可能起到优化作用的改进:

  • 完善棋力表
    在目前的程序中自始至终每个棋子都只有一个表,但一个表只能提供最粗略的估计,显然适应不了变化莫测的局面。为了提供更详细可靠的评估标准,可以将棋局分为三个阶段:开局、中局和残局,每个局面对应一个棋力评估表。
  • 增加搜索深度
  • 历史记录
    很多同学都有提到这个点,不过我很好奇他们是怎么实现的。记住一个好的走法是需要记住整个局面吗,这样的代价似乎有点大,一局下来也不一定能遇到几次重复的局面,而你还要从出现过这个局面的历史记录里找出分数最高的走法,听起来很好,但我认为很难实现。如果不记住整个局面而记下局部区域的局面,那开销可能小一点,重复出现该局面的可能性也比较高,但算法就更复杂了。

中国象棋AI实现——alpha-beta剪枝相关推荐

  1. 五子棋AI算法-Alpha Beta剪枝

    上一篇讲了极大极小值搜索,其实单纯的极大极小值搜索算法并没有实际意义. 可以做一个简单的计算,平均一步考虑 50 种可能性的话,思考到第四层,那么搜索的节点数就是 50^4 = 6250000,在我的 ...

  2. 基于python的AI五子棋实现(极大极小值搜索和alpha beta剪枝)

    1.极大极小值搜索介绍 人机博弈是人工智能的重要分支,人们在这一领域探索的过程中产生了大量的研究成果,而极小化极大算法(minimax)是其中最基础的算法,它由Shannon在1950年正式提出. M ...

  3. 五子棋AI算法第三篇-Alpha Beta剪枝

    剪枝是必须的 五子棋AI教程第二版发布啦,地址:https://github.com/lihongxun945/myblog/labels/%E4%BA%94%E5%AD%90%E6%A3%8BAI% ...

  4. alpha-beta剪枝五子棋c语言,五子棋AI算法第三篇-Alpha Beta剪枝

    剪枝是必须的 上一篇讲了极大极小值搜索,其实单纯的极大极小值搜索算法并没有实际意义. 可以做一个简单的计算,平均一步考虑 50 种可能性的话,思考到第四层,那么搜索的节点数就是 50^4 = 6250 ...

  5. 教你怎么用Python和Qt5编写中国象棋AI版——规则模块

    提示:该模块用于实现规则模块 教你怎么用Python和Qt5编写中国象棋AI版--规则模块 前言 一.中国象棋大致规则? 二.各棋子规则实现思路 1.兵 注意事项 过河兵合法偏移 未过河兵合法偏移 2 ...

  6. 中国象棋AI库AlphaZero_ChineseChess

    AlphaZero_ChineseChess是一个基于AlphaZero算法的中国象棋AI库,它是开源的,使用Python语言编写,托管在GitHub上.以下是对AlphaZero_ChineseCh ...

  7. 教你怎么用Python和Qt5编写中国象棋AI版——简明易懂版

    教你怎么用Python和Qt5编写中国象棋AI版--简明易懂版 一.前言 二.中国象棋的几个模块--作者认为的 三.各模块大致实现思路 四.最后 一.前言 大家学习Python是否有过编写一个稍微大型 ...

  8. alpha,beta剪枝详解

    α,β剪枝详解\alpha,\beta剪枝详解α,β剪枝详解 示例图 步骤详解 基础原理 这里我们先要理解什么是α,β\alpha,\betaα,β剪枝:α\alphaα是下界,β\betaβ是上界. ...

  9. 中国象棋AI实现01

    本学期开了一门课叫软件工程实践,在制作个人项目之后,我抽到了同学做的中国象棋,将在团队项目中,实现中国象棋的AI,第一次接触这方面的知识,在查阅了相关资料之后,给自己准备了一些网站和书本. 网站 象棋 ...

  10. c语言中国象棋ai算法,【中国象棋】AI算法中的棋子价值是怎么衡定的?

    棋子价值 在对弈时,双方都要进行不可避免的兑子[帅(将)是唯一不可兑换的棋子,下列子的价值如下(以车9分为例,帅(将)除外] 车--9分 战斗力最强大的棋子,是作战主力的第一位.车的价值最大,用分值来 ...

最新文章

  1. AtCoder Beginner Contest 198 (A ~ F)题解
  2. Warning message:NAs introduced by coercion
  3. Oracle 分区表的新增、修改、删除、合并。普通表转分区表方法
  4. NodeJS http服务端获取POST请求数据
  5. golan web扫雷
  6. 推荐一个Windows下好用的终端程序:ConEmu
  7. 留个HelpAssistant用户后门,呵呵。
  8. 是vans_终于在中国发力的 Vans
  9. cacti安装FAQ
  10. 网页开发部署-开发工具MyEclips+Tomcat+mysql
  11. 服务器c盘显示0字节可用,c盘0字节可用怎么解决 c盘0字节可用处理方法
  12. 马斯克澄清“我不是中本聪”,比特币创始人究竟是谁?
  13. Aliyun上Linux服务器挂载数据盘及速度测试
  14. 优化数据库方法 php,PHP优化MYSQL数据库的方法有哪些
  15. ffmpeg 转码及多线程处理
  16. 视频教程 C语言全套视频教程(已更新完毕
  17. jenkins调用VS201X
  18. 简单动态网站的搭建流程
  19. DTD-文档类型定义(Document Type Definition)
  20. 优化vue项目打包的chunk.js 和 chunk-vonder.js

热门文章

  1. 设计模式——工厂模式(包含:简单工厂模式、工厂方法模式、抽象工厂模式)
  2. maya python 游戏与影视编程指南pdf_《Maya Python游戏与影视编程指南》.( [美]Adam Mechtley).[PDF]...
  3. 视频教程 | 3D 跑酷小游戏实战开发(上)
  4. RTMP网页视频抓取
  5. 中国石油大学《安全管理学》第二阶段在线作业
  6. 软件测试功能测试全套常见面试题【功能测试】面试总结4-2
  7. 怎么用SQL sever打开mdf
  8. 你晓得什么叫风华绝代
  9. 第七届DAMS中国数据智能管理峰会(上海站) - 文末俩惊喜
  10. 虚幻4引擎开发的手游_掌上视觉进化,盘点近年虚幻4引擎开发的手游大作