>>井字棋
先来玩一玩吧
flash版(鼠标点一点吧,发现bug截图发给作者)
>>说明
游戏逻辑实现比较简单,两个角色轮流落子,直到一方获胜或者棋盘填满结束。
具体说一下AI的实现。
这篇文章http://blog.jobbole.com/24719/里边介绍了一种方法,挺有意思。但是我没有按照文章中介绍的方法来做,因为玩井字棋游戏,如果双方都不失误的话,会一直以平局结束,而文章中介绍的方法,是最优策略,且不方便调整AI的强弱。因此,最终还是决定用评分表的方式实现。
棋盘上可以连出8条线。
如果棋盘上的9个位置坐标设定为:
[0, 1, 2] [3, 4, 5] [6, 7, 8]
8条线分别是(3条横线,3条竖线,2条斜线):
[0, 1, 2] [3, 4, 5] [6, 7, 8] [0, 3, 6] [1, 4, 7] [2, 5, 8] [0, 4, 8] [2, 4, 6]
每一条线都有3个位置组成,每个位置可能有3种状态(0:空,1:用户的子,2:ai的子),3个位置共有27种组合方式。虽然有27种组合方式,但是很多是相似的,归纳一下,总共只有6种状态。我们可以定义每种状态的得分。(假设AI落子位置为2,用户落子位置为1,空位为0)
var s1:int = 70, //000 全部为空 s2:int = 1000, //002 已经有一颗AI的子(也可以是020,200,不一一列举,下同) s3:int = 100000, //022 已经有两颗AI的子 s4:int = 80, //001 已经有一颗用户的子 s5:int = 8000, //011 已经有两颗用户的子 s6:int = 1; //012 用户的子和AI的子各一颗
27种状态,如果用3进制表示,刚好是000-222。因此,我们可以创建一个长度为27的评分索引表(scoreTable),对应27种状态,而评分表中每个位置的值,就是该处索引值对应的3进制数的评分值。如4对应的3进制数是011,而011的评分是s5=8000,所以scoreTable[4]=s5=8000 。
创建好的评分索引表为:
var scoreTable:Array = [ // 000 001 002 010 011 012 020 021 022 s1, s4, s2, s4, s5, s6, s2, s6, s3, // 100 101 102 110 111 112 120 121 122 s4, s5, s6, s5, s0, s0, s6, s0, s0, // 200 201 202 210 200 212 220 221 222 s2, s6, s3, s6, s2, s0, s3, s0, s0 ]
创建好评分索引表之后,我们就可以开始计算每个位置的实际得分了。
首先,创建一个长度为9的评分表scores,初始值为0 。遍历8条线,计算每条线对应的位置当前状态下的分值。比如线[0, 1, 2],假设当前0的位置上有一个用户的子,其余位置为空,则这条线的状态为 100 ,3进制数100的值为1*9+0*3+0=9,通过查表scoreTable[9]=80,所以给这条线上的每个空位的分值加80。
计算完所有的得分之后,从评分表scores中取出得分最高的位置,该位置就是AI的落子点。如果得分最高的位置不知一个,从里边随机取一个就可以了。
要调整AI的棋力是非常简单的,只要设定一个值,让AI有一定的概率随机乱落子即可。