What data structures would you use to represent a chessboard for a computer chess program?
Well, not sure if this helps, but Deep Blue used a single 6-bit number to represent a specific position on the board. This helped it save footprint on-chip in comparison to it's competitor, which used a 64-bit bitboard.
This might not be relevant, since chances are, you might have 64 bit registers on your target hardware, already.
I know this is a very old post which I have stumbled across a few times when googling chess programming, yet I feel I must mention it is perfectly feasible to model a chessboard with a 1D array e.g. chessboard[64];
I would say this is the simplest approach to chessboard representation...but of course it is a basic approach.
Is a 1D chessboard array structure more efficient than a 2D array (which needs a nested for loop to access and manipulate the indices)?
It is also possible to use a 1D array with more than 64 squares to represent OffBoard squares also e.g. chessboard[120]; (with the array sentinel and board playing squares correctly initialised).
Finally and again for completeness for this post I feel I must mention the 0x88 board array representation. This is quite a popular way to represent a chessboard which also accounts for offboard squares.
For a serious chess engine, using bitboards is an efficient way to represent a chess board in memory. Bitboards are faster than any array based representation, specially in 64-bit architectures where a bitboard can fit inside a single CPU register.
Bitboards
Basic idea of bitboards is to represent every chess piece type in 64 bits. In C++/C# it will be ulong/UInt64
. So you'll maintain 12 UInt64
variables to represent your chess board: two (one black and one white) for each piece type, namely, pawn, rook, knight, bishop, queen and king. Every bit in a UInt64
will correspond to a square on chessboard. Typically, the least significant bit will be a1 square, the next b1, then c1 and so on in a row-major fashion. The bit corresponding to a piece's location on chess board will be set to 1, all others will be set to 0. For example, if you have two white rooks on a2 and h1 then the white rooks bitboard will look like this:
0000000000000000000000000000000000000000000000000000000110000000
Now for example, if you wanted to move your rook from a2 to g2 in the above example, all you need to do is XOR you bitboard with:
0000000000000000000000000000000000000000000000000100000100000000
Bitboards have a performance advantage when it comes to move generation. There are other performance advantages too that spring naturally from bitboards representation. For example you could use lockless hash tables which are an immense advantage when parallelising your search algorithm.
Further Reading
The ultimate resource for chess engine development is the Chess Programming Wiki. I've recently written this chess engine which implements bitboards in C#. An even better open source chess engine is StockFish which also implements bitboards but in C++.
The simple approach is to use an 8x8 integer array. Use 0 for empty squares and assign values for the pieces:
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
Piece moves can be calculated by using the array indexes. For example the white pawns move by increasing the row index by 1, or by 2 if it's the pawn's first move. So the white pawn on [2][1] could move to [3][1] or [4][1].
However this simple 8x8 array representation of has chessboard has several problems. Most notably when you're moving 'sliding' pieces like rooks, bishops and queens you need to constantly be checking the indexes to see if the piece has moved off the board.
Most chessprograms today, especially those that run on a 64 bit CPU, use a bitmapped approach to represent a chessboard and generate moves. x88 is an alternate board model for machines without 64 bit CPUs.
There are of course a number of different ways to represent a chessboard, and the best way will depend on what is most important to you.
Your two main choices are between speed and code clarity.
If speed is your priority then you must use a 64 bit data type for each set of pieces on the board (e.g. white pawns, black queens, en passant pawns). You can then take advantage of native bitwise operations when generating moves and testing move legality.
If clarity of code is priority then forget bit shuffling and go for nicely abstracted data types like others have already suggested. Just remember that if you go this way you will probably hit a performance ceiling sooner.
To start you off, look at the code for Crafty (C) and SharpChess (C#).
Array of 120 bytes.
This is a chessboard of 8x8 surrounded by sentinel squares (e.g. a 255 to indicate that a piece can't move to this square). The sentinels have a depth of two so that a knight can't jump over.
To move right add 1. To move left add -1. Up 10, down -10, up and right diagonal 11 etc. Square A1 is index 21. H1 is index 29. H8 is index 99.
All designed for simplicity. But it's never going to be as fast as bitboards.