Object orientated design for chess engine
I've wanted to design a chess engine using object oriented ideas as an exercise. Currently my chess engine is written mostly procedurally and I'm having a hard time thinking about a chess engine in terms of objects (the process of deciding which move to make next doesn't seem to be based on the idea of 'real life objects' as many examples are) currently what I've had in mind for a design was:
in order to decide on a move, the engine will need a position, its legal moves and be able to make moves to analyse future permutations. So
the position has a collection of legal moves and a score based on the position
the AI 'brain' gets access to a position and is able to make theoretical moves on its position
the computer player which has a position as well as a 'brain' which decides the best move
Am I going along the right tracks? How would one design something similar to a chess engine, in general, in an object oriented way?
I was not entirely sure of your question, but hopefully this can give you a push in the right direction.
What you need is:
You can represent your board as a two dimensional array, which makes for easy coordinate reading, but terrible performance. A one dimensional array is a more efficient alternative if you still want it to be easy for the eyes. Example given below:
public class Board
{
///<summary>Chess board</summary>
/// 0 1 2 3 4 5 6 7
/// 8 9 10 11 12 13 14 15
/// 16 17 18 19 20 21 22 23
/// 24 25 26 27 28 29 30 31
/// 32 33 34 35 36 37 38 39
/// 40 41 42 43 44 45 46 47
/// 48 49 50 51 52 53 54 55
/// 56 57 58 59 60 61 62 63
public Piece[] Pieces;
//Is it white or blacks turn?
public bool IsWhiteTurn { get; set; }
public Piece GetField(int index)
{
return Pieces[index];
}
public Board CopyBoardAndDoMove(Move m)
{
//todo
}
}
Pieces could be represented like this:
public enum Piece
{
Empty =0,
WhitePawn = 1,
WhiteRook = 2,
WhiteKnight = 3,
WhiteBishop = 4,
WhiteQueen = 5,
WhiteKing =6,
BlackPawn = -1,
BlackRook = -2,
BlackKnight = -3,
BlackBishop = -4,
BlackQueen = -5,
BlackKing = -6
}
Moves can be represented like this:
public class SimpleMoveType
{
public SimpleMoveType(Piece chessPiece, Piece content, int oldField, int newField, SpecialMoves special = SpecialMoves.None)
{
ChessPiece = chessPiece;
Content = content;
NewField = newField;
OldField = oldField;
Special = special;
}
//The Piece to move
public Piece ChessPiece { get; set; }
//The Piece in the new field, if any.
public Piece Content { get; set; }
//index of new field
public int NewField { get; set; }
//index of old field
public int OldField { get; set; }
//Special move like promotion, castling effects the Piece or other pieces
//In case it's a special move, we need this info to apply the move to the Board.
public SpecialMoves Special { get; set; }
}
public enum SpecialMoves
{
None = 0,
EnPassant,
PawnTwoStepStart, //When a pawn makes its fist move it can move to fields forward
Promotion,
CastlingKingSide,
CastlingQueenSide,
PromotionKnight,
PromotionBishop,
PromotionRook
}
Then you will need a move generator. Before you go any futher you will have to decide if you want to go legal or sudo legal moves. Legal moves are a pain to implement, but sodu legal moves can be really hard to debug and find the issue. And belive me it's not going to be perfect in the first 10 tries.
The move generator should be something like:
public class MoveGenerator : IMoveGenerator
{
private readonly IMoveContainer _moveContainer;
public MoveGenerator(IMoveContainer moveContainer)
{
_moveContainer = moveContainer;
}
public List<SimpleMoveType> GetPsoudoLegalMoves(SimpleBoard b)
{
var moves = new List<SimpleMoveType>();
var white = b.White;
for (int i = 0; i < 64; i++)
{
moves.AddRange(GetMoves(i, b, white);
}
return moves;
}
private List<SimpleMoveType> GetMove(int indexBoardPosition, Board b, bool isWhiteTurn)
{
//TODO
}
}
Now for the game logic (the "brain"). The AI should be a min-max or alpha beta search tree implementation. The leafs are the boards. Each possible move will generate a new leaf (board). The value of the boards should be calculated, with regard to player (black or white) that is supposed to do the next move.
The static value can be calculated in multiple ways. A simple way is to give your pieces point for position on the board, and give the pieces a value. If a piece is lost, the value of the board will decrease. Is a opponents Piece captured, your board will gain value.
Example of value of the pieces:
King 10.000 (higher then anything on the board combined, if lost game over)
Queen 900
Tower 500
Bishop 300
Knight 300
Pawn 100
The value of the position could be calculated from these tables by Kaare Danielsen:
Chess programming is a big project, so I'll recommend taking a look at this wiki. I recommend adding some good unittesting to your move generator. This is the number one cause of bugs in the first stages of your project. I implemented a lot of tests based on the perft results, and that caught a lot of bugs for me.
Have fun :)
The position seems more like the state of a player. I would have a board object whose state is the placement of the pieces, and with methods to allow only valid moves. Both player objects have access to the board and can evaluate their position and moves. A player's controller can then be an AI brain or a GUI for user input.
链接地址: http://www.djcxy.com/p/84654.html下一篇: 面向对象设计的国际象棋引擎