Hash 正确实现Zobrist哈希

Hash 正确实现Zobrist哈希,hash,chess,Hash,Chess,我目前正在我的国际象棋引擎中添加换位表,我在增量更新Zobrist键方面遇到了问题。我尝试并实现了基本的想法,但它的表现并不像我预期的那样。我遇到的问题是,等效板位置并不总是具有相同的键。例如,在起始位置,如果两名玩家只是移动一名骑士,然后将其移回,则关键点将不同于起始位置的关键点。但是,再次执行此操作(移动骑士)并返回起始位置将产生原始关键点。因此,似乎这样的序列的周期是每个玩家4步,而应该是2步 有没有人遇到过这样的问题或能想出解决办法?我已经包括了make/unmake方法的相关部分。我不

我目前正在我的国际象棋引擎中添加换位表,我在增量更新Zobrist键方面遇到了问题。我尝试并实现了基本的想法,但它的表现并不像我预期的那样。我遇到的问题是,等效板位置并不总是具有相同的键。例如,在起始位置,如果两名玩家只是移动一名骑士,然后将其移回,则关键点将不同于起始位置的关键点。但是,再次执行此操作(移动骑士)并返回起始位置将产生原始关键点。因此,似乎这样的序列的周期是每个玩家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
}
投掷可以看作是两个移动的总和(显然没有捕获)


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

通常制作和取消制作应相同。(XOR是对称的)散列不应反映移动,而应反映板上的片段。捕获片段:=从散列中删除其值。移动工件:=从哈希中删除上一个位置+将新位置添加到哈希中。(城堡和中途状态有点不同)是的,我相信我的代码就是这样做的。还有其他的生成/取消生成代码需要考虑,这就是为什么“to”和“from”方块会改变的原因;make方法中位于“from”的片段显然不再存在于unmake方法中。不,make()代码应该只有两个组件:一个用于从旧位置删除片段,另一个用于将其添加到新位置。(可能还有一个额外的组件来移除捕获的片段)我有一个“空”片段类型,所以我假设我不需要检查捕获的片段。我不认为这会造成任何问题,但检查一下是个好主意。嗯,我错了。包括“空”的那块,把事情搞砸了。谢谢你的帮助;如果你回答的话,我会接受你的回答:)。
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];
    }