我正在写一个Connect Four游戏引擎。目前我正在使用Zobrist hashing为不同的Connect Four板位置生成散列键(为了不做同样的事情两次,评估的板位置存储在散列表中)。评估的板位置(极小极大树中的节点)始终彼此靠近。不幸的是,关闭板位置被映射到均匀分布的哈希键,导致大量的cpu缓存未命中。
是否可以构建一个哈希函数,将关闭的板位置映射到关闭哈希键?
一名球员的棋盘位置由以下结构的位板表示:
. . . . . . . TOP
5 12 19 26 33 40 47
4 11 18 25 32 39 46
3 10 17 24 31 38 45
2 9 16 23 30 37 44
1 8 15 22 29 36 43
0 7 14 21 28 35 42
我不知道是否有可能。 谢谢你的帮助!
答案 0 :(得分:1)
我不认为这是可能的。一个好的散列键(如用于棋盘游戏的zobrist散列)很可能具有伪随机属性,以在转置表中实现键的均匀分布。在表格中将“靠近”位置的键彼此靠近是矛盾的。
考虑一下:即使您将电路板位置一对一映射到具有(2 ^ 7-1)^ 7个位置的表格,您也无法将“关闭”电路板位置映射到关闭存储位置:如果是在低指数变化的情况下,位置将接近,但是单位指数越高,每次的位置差异加倍,而高位数将相差多个太字节; - )
作为国际象棋引擎的作者,我知道这个问题。 AFAIK还没有人解决这个问题,每个人都使用zobrist散列,可能会进行一些小修改。
无论如何,祝你好运解决Connect-4 ...我知道它以前已经完成了,但自己做得更令人满意; - )
答案 1 :(得分:1)
以下是如何修改你可能几乎均匀随机的哈希函数,以便在相似的板位置有可能发生在附近的哈希值的方式偏向它。
让哈希(gamestate)成为你现有的功能。我们将创建一个newhash(gamestate),它使用hash作为随机行为,但是对于密切相关的游戏状态,它们产生的哈希值相当接近。
让棋盘状态的'颜色'成为下一个移动的球员。如果想要找到白色播放器的哈希键,请使用newhash(board)= hash(board)。如果要查找黑色位置的哈希值,请根据您的订单找到具有最大数量的黑色部分,例如,在位置i处。从游戏状态中删除棋子i并调用修改后的状态probableparent然后使用newhash(board)= hash(probableparent)+ i。如果您按照可能的下单顺序订购头寸(更高的东西后来作为第一顺序标准,可能中间位置更早作为第二个标准?我真的不知道对于connect4的良好策略),那么它有点可能在在黑色转弯之前的白色转弯处于可能的状态,因此很好地在你的缓存中,因此我就在附近。此外,8个可能的黑色移动可能会共享相同的prev_board状态,因此靠近散列位置。
您可以将此想法扩展为一次回滚多个层。假设当前转弯%3 == 2,移除板位置i和j的最大两次移动,然后使用newhash(board)= hash(board-two-removals-ago)+ i * 48 + j。