转眼间快到了五月,帝都的天气也变的非常梦幻。 时而酷暑炎热,时而狂风席卷。
而不管外面如何,我们也只能在办公室里茕茕无依的撸着代码,无可奈何的负着韶华。
世界是寂寞的,寂寞到不只是寂寞,而是死一般的寂寞。
或许AI就是因此而生吧,因为到了最后,能一直陪伴我们走下去的,或许也就只有程序了。
好吧不装逼了,近期在研究skynet服务器框架,里面有斗地主的demo,于是想做一个嵌入式的AI逻辑,目前的计划只用于托管处理业务。当然也有做机器人调度服务的想法,前期也算是把网上好找的相关文章看了个遍,收获还是蛮多的,这里就不一一致谢了。
下面步入正题
——————————————————————
相信大家已经对斗地主游戏及其玩法不陌生了。对于玩家而言,我们所做出的操作也就只有三种,分别是:叫地主,主动出牌,被动出牌。之所以把主动出牌和被动出牌分开讲,因为从逻辑方面两者差别还是蛮大的。主动出牌没有牌型限制,而被动出牌则必须出指定的一种牌型或炸弹、王炸。显然,当你处于被动出牌的阶段时,可供你选择的操作本身就很少,就算你枚举出所有情况也是可以的,而主动出牌一般就不能这么搞了,这点从各大斗地主游戏平台提供的提示策略也能看出来。
所以从业务的角度来说,我们主要需要完成叫地主,主动出牌,被动出牌这三种处理逻辑。
再分别看这三种处理:
叫地主:叫地主还算比较简单,无非就是通过一系列的计算,得出手牌的一个价值,我们先简称这个计算函数为F,即根据F(手牌)返回的这个价值分一下区间,然后返回一个叫分值(1分2分3分)
主动出牌:主动出牌所做的工作是筛选出当前形势最佳的出牌决策,显然,这个筛选的标准就是如何打出一手牌使得接下来手牌的价值最高,我们可以认为主动出牌的逻辑为:先列举了N种出牌策略,然后通过计算F(剩余手牌),选择返回值最高的一种策略。另外,若只剩一手牌,那么即可直接打出获胜。
被动出牌:被动出牌第一步便是排除多个不合法的出牌类型,可想而知,排除之后可供参考的选择回变的非常少,然后接下来便和主动出牌类似,选择打出一手牌使得剩余价值最高,与主动出牌不同的是,被动出牌可以选择不出牌,比如,34567789,当你可以打对7的时候你不一定要打,因为打了之后接下来的手牌会变的更难出。所以需要对比考虑一下出牌的收益,对比的方法也是看看原手牌的价值与出牌后的价值关系。
通过上述逻辑,我们可以整理出整体的业务流程
那么现在大体的解决方案框架我们已经确定了,重点的问题就是这个手牌价值如何计算。
第一,不同的牌根据其点数首先就要有一定的价值区分,王和3的价值肯定是不一样的,比如说大王的价值是+10分,3的价值是-10分等等。
第二,斗地主存在很多牌型,且三牌四牌还可以带出其他的牌,炸弹王炸又可以通管,所以不同的牌型要有自己的价值体系
第三,一手牌也很有可能拆分成两手,举个例子,当你就剩四张牌时,你认为QQQ3和QQQ2的价值是否相等呢?
这三个问题实际上反映的就是【单牌】【组合牌】【整手牌】三者之间的关系。
由上可知:①每个单牌都有一个基础价值②组合牌型的整体价值与这个基础价值有关,但显然计算规则不完全一样。③整手牌可以分成若干个组合牌,但分法不唯一。
那么如何解决这三个问题呢?首先①和②我们大概可以想到,可以直接去定义。③就比较复杂,因为拆分的方法不唯一,所以需要筛选出一个最优解,这个最优解如何得到呢?
一定是这些拆分出来的组合牌的总和。也就是,当我们只剩一手牌的时候,我们可以通过组合牌的价值定义直接赋予他价值。若非一手牌,则打出一手牌然后继续计算。
不难看出,这是一个递归,递归的出口即只剩一手牌的时候。再看,打出一手牌这一步,是不是和主动出牌的计算最佳决策类似?那么我们现在可以确立这个解决方式。
假设:F()为计算当前手牌的价值 G()为主动出一手牌使接下来的牌价值最大
G()的实现方法是选出若干个F(剩余牌)返回值最优的那个
F()的实现方法是若剩余牌可以一手打出,返回其组合牌价值,否则 F(手牌)=F(G())+F(手牌-G())
以上就是针对斗地主AI实现方法的基本概念,业务逻辑确立之后,我们便可以进行开发了。
敬请关注下一章:斗地主AI算法——第二章の数据结构