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