2012-03-09 28 views
1

我的问题是:如何在VB.NET中实现Bitboard?

  1. 是有可能实现在vb.net一个bitboard
  2. 任何教程/参考VB中做位板?

C#答案是可以接受的,因为它不是很难翻译。

+0

这是对一盘棋? – GrandMasterFlush 2012-03-09 14:10:40

+1

嗯,很好。不知道他们。但是,根据维基百科页面上的描述,实现一个实现并不困难。 – Joey 2012-03-09 14:11:33

+0

是的,这是一个国际象棋游戏。 – jasperagrante 2012-03-09 14:14:08

回答

3

从维基百科文章中,一个位板似乎是一个简单的位数组。 .NET中有一个名为BitArray的类,它具有执行按位操作的方法。

例如,对于白色车位置的棋盘可以声明如下:

'Create bit array to store white rooks 
Dim whiteRooks As New BitArray(64) 

'Set white rooks at initial position 
whiteRooks(0) = True 'Corresponds to A1 on chess board 
whiteRooks(56) = True 'Corresponds to H1 on chess board 
+1

国际象棋中棋盘的全部重点是某些操作的可用性和速度。对于这两个方面来说,BitArray比简单的UInt64差得多。我将很快用一些例子添加一个答案。 – RoadWarrior 2012-03-16 11:16:21

+0

同意上面的RoadWarrior。 BitArray可能是不适用于国际象棋的可扩展性原因的一个好选择,因为总是有64个方格。但更重要的是,大多数涉及UInt64的二进制操作都将在x64架构的单CPU周期中完成,这是我怀疑BitArray保证的。 – bytefire 2013-05-31 13:28:01

0

......怎么

Dim mArray(8,8) As Boolean 

替代Boolean为自己的类或结构和functionalty扩展到您的要求。

0

另一种选择,如果你不想使用数组,是简单地创建一个类/结构包含董事会或州在你想指定的很多“行业”。例如,您可以指定4个long来表示128x128板,每个long代表一个“扇区”(假设为32位处理器)。然后,您只需重写Equals方法(或==运算符)以运行直接比较来检查每个“部分”是否相等,即IE this.Quadrant1 == that.Quadrant1。最终,一个位板的整个概念是,你使用数据类型本身的位来表示你的环境的位置/状态(int = 32bits = 32个位置,long = 64bits = 64个位置等)。对于数值类型,这意味着您可以轻松进行直接相等比较(x == y)以查看比特是否相等。这也使得检查有效移动非常容易,因为它只需要移动位X的位置来表示移动,并且对对手棋盘进行按位&。例如,棋子可以向上移动一个空间(相对于他们的棋盘),如果他们还没有移动,或者可以捕捉,则棋子移动两个。所以为了检查有效的移动,你需要移动小兵位置8(一个空格),16(两个空格,检查是否还没有移动)或者7/9(捕捉)。对于一次或两次空间移动,您必须在棋盘和对手棋盘上为新“位置”执行一次按位&,并检查它是否大于0(表示某人占据空间,因此无效移动)。对于捕捉移动,你只能检查你的对手棋盘,并且只有在结果&大于0时才允许移动。对于两个空格,首先必须对初始棋子“行”进行按位比较(255 < < < 8代表白色,255代表< < 48代表黑色)与有问题的棋子一起看看是否可能。如果你为每一个棋子创建对象,你可以简单地检查一下Pawn对象本身的布尔值,指出它是否已经移动。

使用位板时要考虑的最后一件事是您是否使用带符号的值(至少在.NET中)。这一点很重要,因为如果负数位被设置为有符号值,则该负数位将传播到右移位(意味着它将引入与移位数相同数量的1)。在这种情况下绝对考虑使用无符号值类型,否则你会得到一些时髦的结果。

8

要在VB(或C#)中实现位板,请使用System.UInt64。这可以容纳64位,棋盘的每个方格都有1位。该值类型适用于许多快速按位操作。我不建议使用另一张海报推荐的BitArray,因为它太慢了。任何像样的象棋引擎的基本要求之一就是速度。

要回答你的第二个问题,这是一个good bitboard tutorial

下面是我自己的C#象棋引擎的一些例子。从代码中可以看到,使用位板可能需要一段时间,但它们通常非常快,特别是对于位置评估。

实施例1 - 棋盘定义:

internal UInt64 WhiteKing; 
internal UInt64 WhiteQueens; 
internal UInt64 WhiteRooks; 
internal UInt64 WhiteBishops; 
internal UInt64 WhiteKnights; 
internal UInt64 WhitePawns; 
internal UInt64 WhitePieces; 

实施例2 - 棋盘初始化:

// Initialise piece bitboards using square contents. 
private void InitPieceBitboards() 
{ 
    this.WhiteKing = 0; 
    this.WhiteQueens = 0; 
    this.WhiteRooks = 0; 
    this.WhiteBishops = 0; 
    this.WhiteKnights = 0; 
    this.WhitePawns = 0; 

    for (Int16 i = 0; i < 64; i++) 
    { 
     if (this.Squares[i] == Constants.WHITE_KING) 
     { 
      this.WhiteKing = this.WhiteKing | Constants.BITSET[i]; 
     } 
     if (this.Squares[i] == Constants.WHITE_QUEEN) 
     { 
      this.WhiteQueens = this.WhiteQueens | Constants.BITSET[i]; 
     } 
     if (this.Squares[i] == Constants.WHITE_ROOK) 
     { 
      this.WhiteRooks = this.WhiteRooks | Constants.BITSET[i]; 
     } 
     if (this.Squares[i] == Constants.WHITE_BISHOP) 
     { 
      this.WhiteBishops = this.WhiteBishops | Constants.BITSET[i]; 
     } 
     if (this.Squares[i] == Constants.WHITE_KNIGHT) 
     { 
      this.WhiteKnights = this.WhiteKnights | Constants.BITSET[i]; 
     } 
     if (this.Squares[i] == Constants.WHITE_PAWN) 
     { 
      this.WhitePawns = this.WhitePawns | Constants.BITSET[i]; 
     } 

     this.WhitePieces = this.WhiteKing | this.WhiteQueens | 
          this.WhiteRooks | this.WhiteBishops | 
          this.WhiteKnights | this.WhitePawns; 
     this.BlackPieces = this.BlackKing | this.BlackQueens | 
          this.BlackRooks | this.BlackBishops | 
          this.BlackKnights | this.BlackPawns; 
     this.SquaresOccupied = this.WhitePieces | this.BlackPieces; 
    } 
} 

实施例3 - 移动代:

// We can't capture one of our own pieces. 
eligibleSquares = ~this.WhitePieces; 

// Generate moves for white knights. 
remainingKnights = this.WhiteKnights; 

// Generate the moves for each knight... 
while (remainingKnights != 0) 
{ 
    squareFrom = BitOps.BitScanForward(remainingKnights); 
    generatedMoves = Constants.ATTACKS_KNIGHT[squareFrom] & eligibleSquares; 
    while (generatedMoves != 0) 
    { 
     squareTo = BitOps.BitScanForward(generatedMoves); 
     moveList.Add(new Move(squareFrom, squareTo, Constants.WHITE_KNIGHT, 
           this.Squares[squareTo], Constants.EMPTY)); 
     generatedMoves ^= Constants.BITSET[squareTo]; 
    } 
    // Finished with this knight - move on to the next one. 
    remainingKnights ^= Constants.BITSET[squareFrom]; 
}  

实施例4 - 计算材料的分数:

// Material score from scratch, in centipawns from White's perspective. 
internal static Int32 ScoreMaterial(Board position) 
{ 
    return BitOps.BitCountWegner(position.WhitePawns) * Constants.VALUE_PAWN + 
      BitOps.BitCountWegner(position.WhiteKnights) * Constants.VALUE_KNIGHT + 
      BitOps.BitCountWegner(position.WhiteBishops) * Constants.VALUE_BISHOP + 
      BitOps.BitCountWegner(position.WhiteRooks) * Constants.VALUE_ROOK + 
      BitOps.BitCountWegner(position.WhiteQueens) * Constants.VALUE_QUEEN - 
      BitOps.BitCountWegner(position.BlackPawns) * Constants.VALUE_PAWN - 
      BitOps.BitCountWegner(position.BlackKnights) * Constants.VALUE_KNIGHT - 
      BitOps.BitCountWegner(position.BlackBishops) * Constants.VALUE_BISHOP - 
      BitOps.BitCountWegner(position.BlackRooks) * Constants.VALUE_ROOK - 
      BitOps.BitCountWegner(position.BlackQueens) * Constants.VALUE_QUEEN; 
} 

例5 - 计算一块流动性:

// Calculate mobility score for white knights. 
remainingPieces = position.WhiteKnights; 
while (remainingPieces != 0) 
{ 
    squareFrom = BitOps.BitScanForward(remainingPieces); 
    mobilityKnight += BitOps.BitCountWegner(Constants.ATTACKS_KNIGHT[squareFrom] 
              & unoccupiedSquares); 
    remainingPieces ^= Constants.BITSET[squareFrom]; 
} 
+0

嘿@RoadWarrior,这是你发布的一段非常有趣的代码,你有没有在任何地方发布完整的源代码? – Lu4 2013-08-29 13:21:32

+0

@ Lu4:Amaia目前是一个私人国际象棋程序,所以完整的源代码不可用。 – RoadWarrior 2013-08-29 16:41:28

+0

我明白了,谢谢... – Lu4 2013-08-29 18:16:46