How can you design a java chess game using object oriented principles?

3.4K    Asked by prachiPandey in Java , Asked on Oct 13, 2022

 I would like to know if my approach is correct and how it could be improved? Also, is there a way to get rid of the relation between the Piece and the Board? At the moment, I am storing the position of the piece both in the piece and on the board. Is there some way to change that?


I have considered a Game to contain an instance of the Board and the two Players (one black, one white). The pieces contain a connection to the Board, because in order to determine if they are valid, we need to know the relationship to other pieces.


Could I use design patterns for this? Should I use interfaces instead of the super class?
Game.java
public class Game {
    private Board board = new Board();
    private Player white;
    private Player black;
    public Game() {
        super();
    }
    public void setColorWhite(Player player) {
        this.white = player;
    }
    public void setColorBlack(Player player) {
        this.black = player;
    }
    public Board getBoard() {
        return board;
    }
    public void setBoard(Board board) {
        this.board = board;
    }
    public Player getWhite() {
        return white;
    }
    public void setWhite(Player white) {
        this.white = white;
    }
    public Player getBlack() {
        return black;
    }
    public void setBlack(Player black) {
        this.black = black;
    }
    public boolean initializeBoardGivenPlayers() {
        if(this.black == null || this.white == null)
            return false;
        this.board = new Board();
        for(int i=0; i            board.getSpot(black.getPieces().get(i).getX(), black.getPieces().get(i).getY()).occupySpot(black.getPieces().get(i));
        }
        return true;
    }
}
Player.java
public class Player {
    public final int PAWNS = 8;
    public final int BISHOPS = 2;
    public final int ROOKS = 2;
    public boolean white;
    private List pieces = new ArrayList<>();
    public Player(boolean white) {
        super();
        this.white = white;
    }
    public List getPieces() {
        return pieces;
    }


    public void initializePieces(){
        if(this.white == true){
            for(int i=0; i                pieces.add(new Pawn(true,i,2));
            }
            pieces.add(new Rook(true, 0, 0));
            pieces.add(new Rook(true, 7, 0));
            pieces.add(new Bishop(true, 2, 0));
            pieces.add(new Bishop(true, 5, 0));
            pieces.add(new Knight(true, 1, 0));
            pieces.add(new Knight(true, 6, 0));
            pieces.add(new Queen(true, 3, 0));
            pieces.add(new King(true, 4, 0));
        }
        else{
            for(int i=0; i                pieces.add(new Pawn(true,i,6));
            }
            pieces.add(new Rook(true, 0, 7));
            pieces.add(new Rook(true, 7, 7));
            pieces.add(new Bishop(true, 2, 7));
            pieces.add(new Bishop(true, 5, 7));
            pieces.add(new Knight(true, 1, 7));
            pieces.add(new Knight(true, 6, 7));
            pieces.add(new Queen(true, 3, 7));
            pieces.add(new King(true, 4, 7));
        }
    }
}
Board.java
public class Board {
    private Spot[][] spots = new Spot[8][8];
    public Board() {
        super();
        for(int i=0; i            for(int j=0; j                this.spots[i][j] = new Spot(i, j);
            }
        }
    }
public Spot getSpot(int x, int y) {
        return spots[x][y];
    }
}
Spot.java
public class Spot {
    int x;
    int y;
    Piece piece;
    public Spot(int x, int y) {
        super();
        this.x = x;
        this.y = y;
        piece = null;
    }
    public void occupySpot(Piece piece){
        //if piece already here, delete it, i. e. set it dead
        if(this.piece != null)
            this.piece.setAvailable(false);
        //place piece here
        this.piece = piece;
    }
    public boolean isOccupied() {
        if(piece != null)
            return true;
        return false;
    }
    public Piece releaseSpot() {
        Piece releasedPiece = this.piece;
        this.piece = null;
        return releasedPiece;
    }
}
Piece.java
public class Piece {
    private boolean available;
    private int x;
    private int y;
    public Piece(boolean available, int x, int y) {
        super();
        this.available = available;
        this.x = x;
        this.y = y;
    }


    public boolean isAvailable() {

        return available;

    }

    public void setAvailable(boolean available) {

        this.available = available;

    }

    public int getX() {

        return x;

    }

    public void setX(int x) {

        this.x = x;

    }

    public int getY() {

        return y;

    }

    public void setY(int y) {

        this.y = y;

    }


    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY){

        if(toX == fromX && toY == fromY)

            return false; //cannot move nothing

        if(toX < 0> 7 || fromX < 0> 7 || toY < 0> 7 || fromY <0> 7)

            return false;

        return true;

    }


}

King.java

public class King extends Piece{


    public King(boolean available, int x, int y) {

        super(available, x, y);

        // TODO Auto-generated constructor stub

    }


    @Override

    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {

        if(super.isValid(board, fromX, fromY, toX, toY) == false)

            return false;

        if(Math.sqrt(Math.pow(Math.abs((toX - fromX)),2)) + Math.pow(Math.abs((toY - fromY)), 2) != Math.sqrt(2)){

            return false;

        }

        return false;

    }


}

Knight.java

public class Knight extends Piece{


    public Knight(boolean available, int x, int y) {

        super(available, x, y);

    }

@Override

    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {

        if(super.isValid(board, fromX, fromY, toX, toY) == false)

            return false;


        if(toX != fromX - 1 && toX != fromX + 1 && toX != fromX + 2 && toX != fromX - 2)

            return false;

        if(toY != fromY - 2 && toY != fromY + 2 && toY != fromY - 1 && toY != fromY + 1)

            return false;


        return true;

    }


}

Bishop.java

public class Bishop extends Piece{


    public Bishop(boolean available, int x, int y) {

        super(available, x, y);

        // TODO Auto-generated constructor stub

    }


    @Override

    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {

        if(super.isValid(board, fromX, fromY, toX, toY) == false)

            return false;


        if(toX - fromX == toY - fromY)

            return true;


        return false;

    }


}

Rook.java

public class Rook extends Piece{


    public Rook(boolean available, int x, int y) {

        super(available, x, y);

        // TODO Auto-generated constructor stub

    }


@Override

    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {

        if(super.isValid(board, fromX, fromY, toX, toY) == false)

            return false;

        if(toX == fromX)

            return true;

        if(toY == fromY)

            return true;

        return false;

    }

}

Queen.java

public class Queen extends Piece{


    public Queen(boolean available, int x, int y) {

        super(available, x, y);

    }


    @Override

    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {

        if(super.isValid(board, fromX, fromY, toX, toY) == false)

            return false;

        //diagonal

        if(toX - fromX == toY - fromY)

            return true;

        if(toX == fromX)

            return true;

        if(toY == fromY)

            return true;


        return false;

    }


}

Without offering a deep code review (as I don't have a lot of specific Java knowledge), let's look at what a full "move" entails in java chess game:


Player chooses piece to move.

Piece makes legal move according to its own move rules.

In addition to purely move-based rules, there's also capture logic, so a bishop cannot move from a1-h8 if there's a piece sitting on c3.

If the player was previous under check and the move does not remove the check, it must be undone.

If the move exposes a check, it must be undone / disallowed.

If a player captures a piece, remove the piece (including en passant!)

If the piece is a pawn reaching the back rank, promote it.

If the move is a castling, set the new position of the rook accordingly. But a king and rook can only castle if they haven't moved, so you need to keep track of that. And if the king moves through a check to the castle, that's disallowed, too.

If the move results in a stalemate or checkmate, the game is over.

There may be more even (?). This is a complicated step, more than just counting and subsequently occupying spaces.

So my general intuition would be to just call:

Code Review

Design a chess game using object-oriented principles

Asked 7 years, 3 months ago

Modified 3 years, 6 months ago

Viewed 222k times

76

47

I would like to know if my approach is correct and how it could be improved? Also, is there a way to get rid of the relation between the Piece and the Board? At the moment, I am storing the position of the piece both in the piece and on the board. Is there some way to change that?

I have considered a Game to contain an instance of the Board and the two Players (one black, one white). The pieces contain a connection to the Board, because in order to determine if they are valid, we need to know the relationship to other pieces.

Could I use design patterns for this? Should I use interfaces instead of the super class?

Game.java

public class Game {

    private Board board = new Board();

    private Player white;

    private Player black;

    public Game() {

        super();

    }

    public void setColorWhite(Player player) {

        this.white = player;
    }
    public void setColorBlack(Player player) {
        this.black = player;
    }
    public Board getBoard() {
        return board;
    }
    public void setBoard(Board board) {
        this.board = board;
    }
    public Player getWhite() {
        return white;
    }
    public void setWhite(Player white) {
        this.white = white;
    }
    public Player getBlack() {
        return black;
    }
    public void setBlack(Player black) {
        this.black = black;
    }
    public boolean initializeBoardGivenPlayers() {
        if(this.black == null || this.white == null)
            return false;
        this.board = new Board();
        for(int i=0; i pieces = new ArrayList<>();
    public Player(boolean white) {
        super();
        this.white = white;
    }
    public List getPieces() {
        return pieces;
    }
    public void initializePieces(){
        if(this.white == true){
            for(int i=0; i 7 || fromX < 0> 7 || toY < 0> 7 || fromY 7)
            return false;
        return true;
    }
}
King.java
public class King extends Piece{
    public King(boolean available, int x, int y) {
        super(available, x, y);
        // TODO Auto-generated constructor stub
    }
    @Override
    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {
        if(super.isValid(board, fromX, fromY, toX, toY) == false)
            return false;
        if(Math.sqrt(Math.pow(Math.abs((toX - fromX)),2)) + Math.pow(Math.abs((toY - fromY)), 2) != Math.sqrt(2)){
            return false;
        }
        return false;
    }
}
Knight.java
public class Knight extends Piece{
    public Knight(boolean available, int x, int y) {
        super(available, x, y);
    }
    @Override
    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {
        if(super.isValid(board, fromX, fromY, toX, toY) == false)
            return false;
        if(toX != fromX - 1 && toX != fromX + 1 && toX != fromX + 2 && toX != fromX - 2)
            return false;
        if(toY != fromY - 2 && toY != fromY + 2 && toY != fromY - 1 && toY != fromY + 1)
            return false;
        return true;
    }
}
Bishop.java
public class Bishop extends Piece{
    public Bishop(boolean available, int x, int y) {
        super(available, x, y);
        // TODO Auto-generated constructor stub
    }
    @Override
    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {
        if(super.isValid(board, fromX, fromY, toX, toY) == false)
            return false;
        if(toX - fromX == toY - fromY)
            return true;
        return false;
    }
}
Rook.java
public class Rook extends Piece{
    public Rook(boolean available, int x, int y) {
        super(available, x, y);
        // TODO Auto-generated constructor stub
    }
    @Override
    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {
        if(super.isValid(board, fromX, fromY, toX, toY) == false)
            return false;
        if(toX == fromX)
            return true;
        if(toY == fromY)
            return true;
        return false;
    }
}
Queen.java
public class Queen extends Piece{
    public Queen(boolean available, int x, int y) {
        super(available, x, y);
    }
    @Override
    public boolean isValid(Board board, int fromX, int fromY, int toX, int toY) {
        if(super.isValid(board, fromX, fromY, toX, toY) == false)
            return false;
        //diagonal
        if(toX - fromX == toY - fromY)
            return true;
        if(toX == fromX)
            return true;
        if(toY == fromY)
            return true;
        return false;
    }
}

java

object-oriented

design-patterns

game

chess

Share

Improve this question

Follow

edited Dec 5, 2014 at 20:32

200_success

141k2121 gold badges183183 silver badges466466 bronze badges

asked Dec 5, 2014 at 18:05

SummerCode

86311 gold badge99 silver badges88 bronze badges

Where is the Pawn.java file ? I did not find that. –

user92331

 Dec 15, 2015 at 12:36

1

@Nitin Kumar i have indeed forgotten to write it down apparently, but i no longer have the project due to some hardware issues... –

SummerCode

 Dec 15, 2015 at 13:15

1

bishop moves only in diagonal shape if it is in white place means its only moves in white diagonally otherwise moves in black –

user115324

 Aug 18, 2016 at 9:56

Add a comment

6 Answers

31

Without offering a deep code review (as I don't have a lot of specific Java knowledge), let's look at what a full "move" entails in chess:

Player chooses a piece to move.

Piece makes legal moves according to its own move rules.

In addition to purely move-based rules, there's also capture logic, so a bishop cannot move from a1-h8 if there's a piece sitting on c3.

If the player was previous under check and the move does not remove the check, it must be undone.

If the move exposes a check, it must be undone / disallowed.

If a player captures a piece, remove the piece (including en passant!)

If the piece is a pawn reaching the back rank, promote it.

If the move is a castling, set the new position of the rook accordingly. But a king and rook can only castle if they haven't moved, so you need to keep track of that. And if the king moves through a check to the castle, that's disallowed, too.

If the move results in a stalemate or checkmate, the game is over.

There may be more even (?). This is a complicated step, more than just counting and subsequently occupying spaces.

So my general intuition would be to just call:

Game.move(currentSpot, NewSpot);

And the move method would contain all the code to validate the steps above:

Check Piece.isValidMove(currentSpot, newSpot); - probably need castling logic here since king moves more than 1 space and rook jumps the king)

Check Player.isChecked() (which is just sugar for Player.Pieces["King"].CanBeCaptured() - more fun logic here!)

Check if newSpot contains a piece and if so, newSpot.Piece.Remove();

Build some logic to call Piece.CheckEnPassant() (Piece is pawn, first move, 2 steps, past an enemy pawn who moved into capturing position on previous move - have fun with that!)

Piece.CheckPromote() (Piece is pawn, move ends on opposing player's back rank)

Check if Game.isOver(), which checks Game.isStaleMate() and Game.isCheckMate().

Your Board class is highly anemic, you're only using it in your code as a proxy object for the array of spots. You might as well just create a Board as an array of Spots in Game. In either case, you can already remove it from all your piece logic since all your logic is entirely predicated on the Xs and Ys you're passing in.

UPDATE

I would remove all your position properties from the piece. You're only using it as a proxy to figure out what spot the piece occupies during initialization. Instead, remove Player.initializePieces() and just initialize the Board with the pieces in the right spot (Board.Spot.Piece = King, etc.) and then let players choose a color.



Your Answer

Answer (1)

Designing a chess game in Java using object-oriented principles involves creating a series of classes that represent the different aspects of a chess game. Here’s a step-by-step approach to design such a game, focusing on clarity, maintainability, and the principles of object-oriented programming (OOP).

Step-by-Step Design

Identify the Main Components

The main components of a chess game typically include:

Board

Pieces

Players

Game logic (rules, moves, etc.)

Define Classes and Their Responsibilities

Class Diagram

+------------------+
| Game |
+------------------+
| - board: Board |
| - players: List |
| - currentTurn: Player |
+------------------+
| + start() |
| + makeMove() |
| + isGameOver() |
+------------------+
+------------------+
| Board |
+------------------+
| - squares: Square[][] |
+------------------+
| + initialize() |
| + getPieceAt() |
| + movePiece() |
+------------------+
+------------------+
| Square |
+------------------+
| - piece: Piece |
| - x: int |
| - y: int |
+------------------+
| + isEmpty() |
+------------------+
+------------------+
| Piece |
+------------------+
| - color: Color |
| - position: Square |
+------------------+
| + move() |
| + getValidMoves()|
+------------------+
+------------------+
| Player |
+------------------+
| - color: Color |
+------------------+
| + makeMove() |
+------------------+
+------------------+
| Color |
+------------------+
| WHITE, BLACK |
+------------------+
+------------------+
| Move |
+------------------+
| - from: Square |
| - to: Square |
+------------------+
| + execute() |
+------------------+
Implementing the Classes
java
Copy code
public enum Color {
    WHITE, BLACK;
}
public abstract class Piece {
    protected Color color;
    protected Square position;
    public Piece(Color color, Square position) {
        this.color = color;
        this.position = position;
    }
    public abstract List getValidMoves(Board board);
    public Color getColor() {
        return color;
    }
    public void setPosition(Square position) {
        this.position = position;
    }
    public Square getPosition() {
        return position;
    }
}
public class King extends Piece {
    public King(Color color, Square position) {
        super(color, position);
    }
    @Override
    public List getValidMoves(Board board) {
        // Implement logic for King's valid moves
        return new ArrayList<>();
    }
}
// Similarly, define other pieces like Queen, Rook, Bishop, Knight, and Pawn
public class Square {
    private int x;
    private int y;
    private Piece piece;
    public Square(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public boolean isEmpty() {
        return piece == null;
    }
    public Piece getPiece() {
        return piece;
    }
    public void setPiece(Piece piece) {
        this.piece = piece;
    }
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }
}
public class Board {
    private Square[][] squares;
    public Board() {
        squares = new Square[8][8];
        initialize();
    }
    public void initialize() {
        for (int i = 0; i < 8 xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed>();
        players.add(new Player(Color.WHITE));
        players.add(new Player(Color.BLACK));
        currentTurn = players.get(0);
    }
    public void start() {
        // Implement game loop
    }
    public void makeMove(Move move) {
        // Validate move, switch turn, and check game status
        currentTurn.makeMove(board, move);
        switchTurn();
    }
    private void switchTurn() {
        currentTurn = (currentTurn.getColor() == Color.WHITE) ? players.get(1) : players.get(0);
    }
    public boolean isGameOver() {
        // Implement game over logic
        return false;
    }
}

Explanation

Piece Class: Abstract base class for all chess pieces. Each piece has a color and position and an abstract method getValidMoves that must be implemented by each specific piece type (King, Queen, etc.).

Square Class: Represents a square on the chessboard. Each square knows its position (x, y) and may or may not have a piece on it.

Board Class: Represents the chessboard, which is an 8x8 array of Square objects. It includes methods to initialize the board, get a square by coordinates, and move a piece.

Move Class: Represents a move from one square to another. It includes an execute method to move the piece.

Player Class: Represents a player in the game, identified by their color. Players can make moves on the board.

Game Class: Manages the overall game, including the board, players, and the current turn. It contains the main game loop logic, switching turns, and checking game status.

Additional Considerations

  • Validation and Rules: Implement validation logic in methods like getValidMoves for each piece to ensure moves are legal according to chess rules.
  • User Interface: Consider creating a separate class or module to handle user interactions if you plan to develop a GUI or command-line interface.
  • Persistence: Implement saving and loading game states if needed.
  • Advanced Features: Add more advanced chess rules like castling, en passant, and pawn promotion.

By following this structured approach, you ensure your chess game is modular, maintainable, and adheres to object-oriented principles.


6 Months

Interviews

Parent Categories