hash - 正确实现 Zobrist 哈希

标签 hash chess

我目前正在我的国际象棋引擎中添加换位表,并且在逐步更新 Zobrist key 时遇到问题。我did some research并实现了基本想法,但它的行为并不像我预期的那样。我遇到的问题是等效的棋盘位置并不总是具有相同的键。例如,在起始位置,如果两个玩家都只是移动了一个骑士,然后再将其移回,则 key 将与起始位置的键不同。但是,再次执行此操作(移动骑士)并返回到起始位置将产生原始键。因此,对于每个玩家来说,这种序列的周期似乎是 4 步,而实际上应该是 2 步。

有没有人遇到过这样的问题或能想到解决方案?我已经包含了我的 make/unmake 方法的相关部分。我不包括边移动,城堡权等;他们不应该影响我提出的特定案件。 HashValue 存储随机值,第一个索引是片类型,第二个是正方形。

void Make(Move m) {
    ZobristKey ^= HashValue[Piece[m.From].Type][m.From];
    ZobristKey ^= HashValue[Piece[m.From].Type][m.To];
    ZobristKey ^= HashValue[Piece[m.To].Type][m.To];
    //rest of make move
}

void Unmake(Move m) {
    ZobristKey ^= HashValue[m.Captured.Type][m.To];
    ZobristKey ^= HashValue[Element[m.To].Type][m.To];
    ZobristKey ^= HashValue[Element[m.To].Type][m.From];
    //rest of unmake
}

最佳答案

Make_a_move() {
    hashval ^= Zobrist_array[oldpos][piece];
    hashval ^= Zobrist_array[newpos][piece];
    /* if there is a capture */
    hashval ^= Zobrist_array[otherpos][otherpiece];
    }

Undo_a_move() {
    hashval ^= Zobrist_array[oldpos][piece];
    hashval ^= Zobrist_array[newpos][piece];
    /* if there was a capture */
    hashval ^= Zobrist_array[otherpos][otherpiece];
    }

CaSTLing可以看作是两个 Action 的总和(显然没有捕获)

提升可以被视为从棋盘上移除一个棋子(从 2 或 7 位置)并添加新棋子(在 1 或 8 位置)

关于hash - 正确实现 Zobrist 哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10067514/

相关文章:

java - 时间用完时中断java中的递归

Java-语义分析: Implementing a hash table with a key and multiple value

security - 使用哈希验证用户的密码?

java - 在 JPanel 中运行 Java 程序

functional-programming - 如何在 F# 递归算法中正确返回生成的序列

python - 如何在保留python国际象棋中的移动堆栈的同时翻转棋盘?

C 用 T 和 H 填充棋盘,不知何故有间隙,只有 7 行而不是 8 行

具有重复值的数组的 ruby​​ 数组到散列的散列

java - 使用 SHA1 进行哈希处理

c# - System.Collections.Generic.Dictionary = 终极性能?