OOP design to avoid object Another object in two directions
I am writing a Java chess game and am trying to get my head around design. Here's what I've done so far for the classes:
Game: consists of 2 game objects and a board object
Player:
Board: consists of an array of 2d (8 x 8) square objects, each of which may / may not have a piece on it
King, Queen, Rook, Bishop, Knight, Pledge:
Piece: Superclass of the above parts, general functionality goes here
Here's what I don't like: I have a field called "board" inside my square class so that I can refer to the board that this square belongs to. I don't like this design because it leads to inline cloning issues.
So, I want to rewrite some functionality in the pieces class without doing this kind of rollback. It's good for the board to be able to access each of its squares, but I don't want to have a getBoard () function for the Square class.
Here's an example of a function that I need to rewrite:
public Square getSquareOneMoveAway(Square start, int heightChange, int widthChange) {
Square candidateSquare = start.getBoard().getNearbySquare(start, heightChange, widthChange);
if (candidateSquare != null) {
if (candidateSquare.isEmpty()) {
return candidateSquare;
} else if (! candidateSquare.getPiece().getColor().equals(start.getPiece().getColor())) {
return candidateSquare;
}
else {
return null;
}
}
else {
return null;
}
}
Please note that in my Player class I have methods like:
canMovePiece (Square start, Square end, Board board), movePiece (Square start, Square end, Board board), etc.
Should I move this method to the Board class so that I can access the board object without having to go from the plaza to the board?
Any ideas highly appreciated bclayman
source to share
In my opinion, you are retraining the problem. Is there any advantage of presenting the squares of the board with another class? If not (and I don't think so), I would just get rid of the Square class .
class Board {
public static final int MAX_ROWS = 8;
public static final int MAX_COLS = 8;
private Piece[][] squares;
public Board() {
squares = new Piece[ MAX_ROWS ][ MAX_COLS ];
}
// ...
}
I would have a class Position , at least a couple of rows and a column.
Hope it helps.
source to share
The following definition is ChessBoard
used to store chunks, store their positions, and use this information to determine if a given move is actually valid.
class ChessBoard implements Board {
Piece[][] pieces; // null if vacant at that position
@Override
public boolean isValidMove(Player player, Square start, Square end) {
Piece pieceStart = pieces[start.row][start.col];
Piece pieceEnd = pieces[end.row][end.col];
return (
pieceStart != null &&
pieceStart.getColor() == player.getColor() &&
pieceStart.isValidTransition(start, end) &&
(pieceEnd == null || pieceStart.canDefeat(pieceEnd))
);
}
}
Note that the logic for whether the motion is valid is encapsulated in the moveable part.
class Pawn implements Piece {
@Override
public boolean isValidTransition(Square start, Square end) {
int dH = end.col - start.col;
int dW = end.row - start.row;
// return if is valid transition for a pawn in terms of dH and dW
}
@Override
public boolean canDefeat(Piece otherPiece) {
return (
this.getColor() != otherPiece.getColor() &&
this.getStrength() > otherPiece.getStrength()
);
}
@Override
public int getStrength() { ... }
@Override
public Color getColor() { ... }
}
A square class is just a 2-tuple containing a row and a column.
class Square {
int row, col;
}
source to share
I'm a pragmatist, so I wouldn't have items as classes, just enums. So:
enum Pieces
{
Pawn,
Rook,
Knight
// etc
};
Then I would create an interface called "Rule", for example:
interface Rule
{
void addRule(Pieces p);
};
In this case, if the class implements the rule, I can decide how the units interact in the game (or preferably in it). This class will be PawnRule, QueenRule, etc. Thus, it will be possible to add as many rules to the game as possible and use them. This not only promotes expansion, but also creates a viable foundation for the game itself.
class PawnRule implements Rule
{
private boolean pFirstMove = true;
// etc
void addRule(Pieces p)
{
if (Square.hasSpace(Space.FRONT) * 2 && pFirstMove)
{
// where renderer holds 2D/3D data pertaining to the piece
rendrerer.getModel("Pawn").moveByTwo(); // somehow
}
}
}
There is a lot more to consider when it comes to design; and maybe listing is not what you are looking for. We also don't know if the game is text-based, 2D or 3D. It is generally easier to implement this material if it is text-based, but more complex when it is 3D. I recommend making a class diagram and even a communication diagram so that you know how the classes / enums / interfaces in your chess game interact with each other.
source to share