我正在使用标准alpha beta修剪搜索算法构建一个Reversi播放器。我正在尝试添加转换表以在搜索树中存储先前计算的节点。所以我需要对表示游戏板(状态)的二维数组进行哈希处理并存储一个值。
我无法想出任何比循环遍历我的数组并将所有值相乘的所有值更好的方法,将它们与偏移相乘以获得唯一的哈希值。
@Override
public int hashCode() {
if (dirtyHash) {
int hash = 0;
for (int i = 0; i < Board.SIZEX; i++)
for (int j = 0; j < Board.SIZEY; j++)
hash += board[i][j] * (i + Board.SIZEY * j);
hashValue = hash;
dirtyHash = false;
}
return hashValue;
}
我怀疑必须有一个更聪明的方法来做到这一点?有人有任何想法吗?
答案 0 :(得分:10)
我会首先尝试使用java标准库:
int hash = java.util.Arrays.deepHashCode( board );
一旦一切正常,请分析整个应用,检查哈希码计算是否真的是性能瓶颈。
答案 1 :(得分:6)
如果你想自己处理这个问题,你可以采用这种方式。
电路板上的每个电池有三个值:空白,黑色,白色。这意味着您可以在电路板上每个单元使用两位。由于电路板是8x8或64个单元,因此您可以使用两个long
原语对电路板进行编码。也许其中一个人告诉你特定的细胞是否为空,如果不是,则另一个告诉你它的颜色。
您甚至不需要将此表示转换为2D数组。您可以直接在方法中使用long
上的按位运算符来使用该板。
哈希值可能是两个long
的XOR,或类似的东西。
答案 2 :(得分:2)
我建议关注:
public int hashCode() {
int hash = 0;
for (int i = 0; i < Board.SIZEX; i++)
for (int j = 0; j < Board.SIZEY; j++)
hash = (hash) ^ ( (Math.pow(p,i)+Math.pow(p,j))* board[i][j]
return hashValue;
}
对于p和q大32素数。
为什么这么快? 计算板的计算非常简单:新的可以用旧的哈希=(哈希)计算^((Math.pow(p,i)+ Math.pow(p,j))* board [i] [j ],迭代不是整个棋盘,而只是更改石头。(如果你用黑色石头的哈希添加黑色一次,如果你用黑色石头改为黑色到白色一次将其从哈希中删除并再次使用白色将其添加)
答案 3 :(得分:2)
你应该使用Zobrist哈希。它非常适合棋盘游戏。它也可以在电路板更改时逐步更新,而不是每次都从头开始重新计算。这使它非常有效。