I am creating a chess engine. I have Piece interface, Rook, Bishop etc. implements this class. My board is Piece[][] array. Let's say white player wants to move his bishop. I pass coordinate of a destination and a board reference to the bishop. Bishop checks, if destination is on the same diagonal, then it asks the board if there are no any pieces between his position and destination square. Is it ok from OOP point of view to do so? Thank you
It's a bit delicate.
From an OOP point of view, one could question whether the Board should be a Piece[][]
array in the first place. A nice, clean, object-oriented design here would probably involve something like an
interface Board {
Piece get(int r, int c);
// Should this be here? See below...
void set(int r, int c, Piece p);
}
And then, one crucial question is: Will the Bishop place "itself" on the target position of the given board? Or, focussing on the OOP point: Is the board that is given to the piece mutable or is it "read-only"? One could imagine a MaliciousBishop
class that, when it is given the Board
, assassinates the opponent's King, by placing itself on the king's position.
From a very high-level, abstract OOP point of view, one could question whether a Piece
should have any intelligence at all. A Piece
is a dumb piece of plastic. It does not know anything about chess rules. You (the player) can place that piece anywhere, either obeying or ignoring the chess rules. So it's certainly not the job of the piece to obey or even check any rules. One could say that obeying the rules is what is expected from the player, and enforcing that the rules are obeyed is the job of a superordinate intelligence (some "ChessGameManager" class, maybe).
A simple approach that seems to (!) lend itself for an OO chess implementation is to have classes like
abstract class Piece {
Color getColor() { ... }
Point getPosition() { ... }
abstract void doMove(...) { ... }
}
class Bishop extends Piece {
void doMove(....) { ... }
}
// + other classes extending "Piece"
But note that this may not always be the best approach, and maybe not always sufficient. Particularly, you should have a very clear idea about how your Engine
, your Board
, your Piece
and your Player
classes interact and what their responsibilities are. (After thinking about this for a while, you'll likely come to the conclusion that you'll also want a Move
class...). In general, checking whether a move is valid is far more complex than it looks at the first glance. You mentioned that, for the Bishop move, you check whether the target position is valid and that there are no other pieces are in-between. But the move is still invalid if the move causes the own king to be left in check. This can only be checked by the "engine", and hardly by the piece itself. Other things that people tend to forget (and that involve information about the whole game state, and can thus hardly be handled by a single Piece) are Castling or En passant moves.
For a chess engine, there are several requirements that make a nice, object oriented approach particularly hard. If your intention is to write an efficient chess engine, then your board will most likely be an array of long
values that are manipulated with bitwise operations....
(A side note: If you had designed your Board
class as an interface, as suggested above, then you could still keep a nice, high-level, object oriented view on this highly performance-optimized representation that is used for the engine itself. My rule of thumb: Always model everything as an interface in the beginning. It's easy to make it more concrete afterwards)
So depending on whether you want to write
you might want to tackle some parts of the game design differently.
EDIT: You'll certainly stumble on this when you are looking for information about chess (engine) programming, but I'd like to point out that https://www.chessprogramming.org/Main_Page offers a lot of background information. Again: This is not really about the OO design, but more about the nitty gritty bits of chess engines.