您将使用哪些数据结构来表示计算机国际象棋程序的棋盘?
最初,使用8*8整数数组来表示国际象棋棋盘.
您可以使用此表示法开始编程.给出碎片的点值.例如:
**White** 9 = white queen 5 = white rook 3 = bishop 3 = knight 1 = pawn **black** -9 = white queen -5 = white rook -3 = bishop -3 = knight -1 = pawn White King: very large positive number Black King: very large negative number
(请注意,上面给出的分数是每个棋子交易能力的近似值)
在开发应用程序的基本主干并清楚地了解所使用的算法的工作原理之后,尝试使用位板来提高性能.
在位板中,您使用8个8位字来表示电路板.这种表示需要每个棋子的棋盘.在一个比特板中你将存储车的位置,而在另一个比特板中你将存储骑士的位置......等等
位板可以非常好地提高应用程序的性能,因为使用位板操作这些部件非常容易和快速.
正如你所指出的,
今天的大多数国际象棋程序,特别是那些在64位CPU上运行的国际象棋程序,使用位图方法来表示棋盘并生成移动.x88是没有64位CPU的机器的备用板模型.
对于严肃的国际象棋引擎,使用位板是在内存中表示国际象棋棋盘的有效方式.位板比任何基于阵列的表示都要快,特别是在64位架构中,位板可以放在单个CPU寄存器中.
位棋盘
位板的基本思想是以64位表示每个棋子类型.在C++/C#中它将是ulong/UInt64
.因此,您将保留12个UInt64
变量来代表您的棋盘:每个棋子类型有两个(一个黑色和一个白色),即典当,车,骑士,主教,女王和国王.a中的每一位UInt64
都对应棋盘上的方块.通常,最低有效位将是a1平方,下一个b1,然后是c1,依此类推行.与棋盘上棋子位置对应的位将设置为1,其他所有位置都设置为0.例如,如果你在a2和h1上有两个白车,那么白车的位置将如下所示:
0000000000000000000000000000000000000000000000000000000110000000
现在,例如,如果您想在上面的示例中将您的车从a2移动到g2,那么您需要做的就是使用以下方法对您进行XOR操作:
0000000000000000000000000000000000000000000000000100000100000000
在移动生成方面,位板具有性能优势.还有其他性能优势,弹簧自然地来自位板表示.例如,您可以使用无锁哈希表,这在并行化搜索算法时是一个巨大的优势.
进一步阅读
国际象棋程序开发的最终资源是国际象棋编程维基.我最近写了这个用C#实现位板的国际象棋引擎.一个更好的开源象棋引擎是StockFish,它也在C++中实现了位板.
简单的方法是使用8x8整数数组.将0用于空方块并为各个部分指定值:
1 white pawns 2 white knights 3 white bishops 4 white rooks 5 white queens 6 white king Black pieces use negative values -1 black pawn -2 black knight etc 8| -4 -2 -3 -5 -6 -3 -2 -4 7| -1 -1 -1 -1 -1 -1 -1 -1 6| 0 0 0 0 0 0 0 0 5| 0 0 0 0 0 0 0 0 4| 0 0 0 0 0 0 0 0 3| 0 0 0 0 0 0 0 0 2| 1 1 1 1 1 1 1 1 1| 4 2 3 5 6 3 2 4 ------------------------- 1 2 3 4 5 6 7 8
可以使用数组索引计算片段移动.例如,白色棋子通过将行索引增加1来移动,或者如果它是棋子的第一个移动则移动2.所以[2] [1]上的白棋子可以移动到[3] [1]或[4] [1].
然而,这个具有棋盘的简单8x8阵列表示有几个问题.最值得注意的是,当你像车,主教和女王一样移动'滑动'时,你需要经常检查指数,看看这件作品是否已经从板上移开.
今天的大多数国际象棋程序,特别是那些在64位CPU上运行的国际象棋程序,使用位图方法来表示棋盘并生成移动.x88是没有64位CPU的机器的备用板模型.