优化寻找残局

时间:2014-01-24 15:51:47

标签: algorithm

我正在实施一款名为Neutreeko的游戏(5x5棋盘,每个玩家有三个爪子,当其中一个形成连接的正交或对角线时游戏结束)我正在考虑检查游戏是否有最佳方式结束。我将电路板的状态存储在一维数组中,我只计算了蛮力方法,我只检查每行,每列和每条对角线的长度为3和5,直到找到命中。在这种情况下,有没有更好的方法来找到游戏结束?

3 个答案:

答案 0 :(得分:4)

如果将电路板存储为位图(位置i,j存储在位i + j * 5中),则可以快速进行检查。

例如,

x & (x >> 1) & (x >> 2) & 0x739ce7
如果水平行为3,则

为非零。

x & (x >> 5) & (x >> 10)
如果有一个垂直行,则

为非零。

x & (x >> 6) & (x >> 12) & 0x1ce7
如果对角线为三行(在(0,0),(1,1),(2,2)之类的对角线上),则

为非零。

x & (x >> 4) & (x >> 8) & 0x739c
如果对角线为三行(在(2,0),(1,1),(0,2)等对角线上),

为非零。

这种位掩码检查在桌面游戏位置评估中非常常见。

答案 1 :(得分:1)

我想首先说一下易于阅读的内容,而不是在运行时不会注意到的微观优化。

那就是说,我就是这样做的:

最好检查其他棋子相对于第一个棋子的位置,而不是粗暴地强迫整个棋盘。

此外,由于棋盘是方形的,你可以根据游戏板的元素更容易地计算位置,因为线条由+ 1s,+ 4s,+ 5s和+6s组成。 没有任何减少,因为我们发现在击中前没有棋子。

[ 0][ 1][ 2][ 3][ 4]
[ 5][ 6][ 7][ 8][ 9]
[10][11][12][13][14]
[15][16][17][18][19]
[20][21][22][23][24]

说第一个棋子是12。 你只需要检查13,16,17,18。 为什么不是6?既然你已经证明在0或6上没有pawn,那么检查就没有意义了。

毕竟,如果你击中一个棋子然后失败了,你可以跳过该玩家的剩余空间,因为他们没有一条线!

下一个pawn命中,然后识别你匹配的是哪一行,并查看该行是否继续到唯一可用的位置(分别为14,20,22,24)。

在制作无效行时可以进一步优化,从最后一列检查除+4或+5以外的任何东西是没有意义的。

答案 2 :(得分:0)

虽然不如Anonymous的回答那么优雅或高效,但也可以使用这样的位板:

/*
parseInt("111",2) == 7

parseInt("1"
   + "00001"
   + "00001",2)   == 1057

parseInt("1"
   + "00010"
   + "00100",2)   == 1092

parseInt("100"
     + "00010"
     + "00001",2) == 4161

To win, a player's bit-board must represent a multiple of one of the masks; 
the multiple must be a power of two; and the mask cannot straddle both sides 
of the bit-board:
*/

function testWinner(board){
    var i = 0,
        masks = [7,1057,1092,4161],
        winner = false

    while (!winner && masks[i]){
        winner = board % masks[i] == 0 
              && !(board / masks[i] & (board / masks[i] - 1)) 
              && !(board & 17318416 && board & 1082401)
        i++
    }
    return winner
}