我正在研究国际象棋引擎,目前我正在实施转位表(一组已经评估过的棋盘位置)。总的想法是,当做出移动时,我检查换位表的匹配位置。如果存在,我跳过昂贵的评估过程,只需从转置表中提取以前计算的结果。如果它不存在,我会进行所需的计算,然后将其添加到转位表中以备将来参考。如何引用引用类型字典键的属性?
对我来说,这听起来像一个哈希集或字典的工作。我决定了字典。我希望关键是成为代表我的董事会的班级,并且该值应该是遇到位置次数的整数。计数的原因是能够检测到三次重复绘制。如果同一位置已经遇到过三次或更多次,玩家可以选择打平。使用字典而不是哈希集合,通过将它与转置表相结合,可以大大简化对三次重复绘制的检测。
为了做到这一点,我已经让表示电路板状态的类覆盖了Equals()和GetHashCode()。它工作得很好,现在我能够跟踪以前遇到的所有历史状态。
我的问题是我需要能够访问字典中的键对象的属性。我可以通过使用.ContainsKey(...)方法和我的Equals()/ GetHashCode()逻辑)查看是否存在匹配,但现在我需要提取前面提到的计算值(作为我的板的公共属性存储状态对象)。
我能想出:
BoardState board = TranspositionTable.Keys.FirstOrDefault(tt => tt.GetHashCode() == this.GetHashCode());
这工作,但感觉笨重给我。换位表的全部内容是加速对数百万连续棋盘状态的递归搜索。查询每场比赛的字典听起来都是违反直觉的。有一个更好的方法吗?
编辑:
由于它已经指出的那样,我的哈希不能是完美的,由于有效的板状态的数量巨大。 My Equals()覆盖会检查第二个备选生成的散列,以减少冲突的可能性。我上面的'解决方案'是有缺陷的,因为它依赖于不完美的哈希。我应该使用:
BoardState board = TranspositionTable.Keys.FirstOrDefault(tt => tt.Equals(this));
我的一个愚蠢的疏忽。不过,我不是一个查询字典的粉丝。
字典中的关键字究竟是什么?可以使'GetHashCode()'的结果成为关键吗?如果是这样,那么这变得更加“自然”来处理...... – Yahia 2013-02-11 17:52:18
@Yahia哈希代码,由于其本质,不是唯一的,所以你需要支持一个对象列表作为值并使用'Equals'用该散列码查找*真*相等的对象。 – Servy 2013-02-11 17:53:10
@Servy,这是真的......但OP似乎很满意匹配散列码的任何结果(根据显示的代码)... – Yahia 2013-02-11 17:54:33