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

+3


source to share


3 answers


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.

+2


source


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;
}

      

+1


source


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.

0


source







All Articles