Design a Chess Game

Problem Statement: The problem is to design a Chess Game using Object Oriented Principles.
Asked In: Adobe, Amazon, Microsoft, etc.
Solution:
These type of questions are asked in interviews to Judge the Object-Oriented Design skill of a candidate. So, first of all we should think about the classes.
The main classes will be:
- Spot: A spot represents one block of the 8×8 grid and an optional piece.
- Piece: The basic building block of the system, every piece will be placed on a spot. Piece class is an abstract class. The extended classes (Pawn, King, Queen, Rook, Knight, Bishop) implements the abstracted operations.
- Board: Board is an 8×8 set of boxes containing all active chess pieces.
- Player: Player class represents one of the participants playing the game.
- Move: Represents a game move, containing the starting and ending spot. The Move class will also keep track of the player who made the move.
- Game: This class controls the flow of a game. It keeps track of all the game moves, which player has the current turn, and the final result of the game.
Let’s look at the details. These codes are self-explanatory. You can have a look at the properties/variables and methods of different classes.
Spot: To represent a cell on the chess board:
public class Spot { private Piece piece; private int x; private int y; public Spot(int x, int y, Piece piece) { this.setPiece(piece); this.setX(x); this.setY(y); } public Piece getPiece() { return this.piece; } public void setPiece(Piece p) { this.piece = p; } public int getX() { return this.x; } public void setX(int x) { this.x = x; } public int getY() { return this.y; } public void setY(int y) { this.y = y; } } |
Piece: An abstract class to represent common functionality of all chess pieces:
public abstract class Piece { private boolean killed = false; private boolean white = false; public Piece(boolean white) { this.setWhite(white); } public boolean isWhite() { return this.white; } public void setWhite(boolean white) { this.white = white; } public boolean isKilled() { return this.killed; } public void setKilled(boolean killed) { this.killed = killed; } public abstract boolean canMove(Board board, Spot start, Spot end); } |
King: To represent King as a chess piece:
public class King extends Piece { private boolean castlingDone = false; public King(boolean white) { super(white); } public boolean isCastlingDone() { return this.castlingDone; } public void setCastlingDone(boolean castlingDone) { this.castlingDone = castlingDone; } @Override public boolean canMove(Board board, Spot start, Spot end) { // we can't move the piece to a Spot that // has a piece of the same color if (end.getPiece().isWhite() == this.isWhite()) { return false; } int x = Math.abs(start.getX() - end.getX()); int y = Math.abs(start.getY() - end.getY()); if (x + y == 1) { // check if this move will not result in the king // being attacked if so return true return true; } return this.isValidCastling(board, start, end); } private boolean isValidCastling(Board board, Spot start, Spot end) { if (this.isCastlingDone()) { return false; } // Logic for returning true or false } public boolean isCastlingMove(Spot start, Spot end) { // check if the starting and // ending position are correct } } |
Knight: To represent Knight as a chess piece
public class Knight extends Piece { public Knight(boolean white) { super(white); } @Override public boolean canMove(Board board, Spot start, Spot end) { // we can't move the piece to a spot that has // a piece of the same colour if (end.getPiece().isWhite() == this.isWhite()) { return false; } int x = Math.abs(start.getX() - end.getX()); int y = Math.abs(start.getY() - end.getY()); return x * y == 2; } } |
Similarly, we can create classes for other pieces like Queen, Pawns, Rooks, Bishops etc.
Board: To represent a chess board:
public class Board { Spot[][] boxes; public Board() { this.resetBoard(); } public Spot getBox(int x, int y) { if (x < 0 || x > 7 || y < 0 || y > 7) { throw new Exception("Index out of bound"); } return boxes[x][y]; } public void resetBoard() { // initialize white pieces boxes[0][0] = new Spot(0, 0, new Rook(true)); boxes[0][1] = new Spot(0, 1, new Knight(true)); boxes[0][2] = new Spot(0, 2, new Bishop(true)); //... boxes[1][0] = new Spot(1, 0, new Pawn(true)); boxes[1][1] = new Spot(1, 1, new Pawn(true)); //... // initialize black pieces boxes[7][0] = new Spot(7, 0, new Rook(false)); boxes[7][1] = new Spot(7, 1, new Knight(false)); boxes[7][2] = new Spot(7, 2, new Bishop(false)); //... boxes[6][0] = new Spot(6, 0, new Pawn(false)); boxes[6][1] = new Spot(6, 1, new Pawn(false)); //... // initialize remaining boxes without any piece for (int i = 2; i < 6; i++) { for (int j = 0; j < 8; j++) { boxes[i][j] = new Spot(i, j, null); } } } } |
Player: An abstract class for player, it can be a human or a computer.
public abstract class Player { public boolean whiteSide; public boolean humanPlayer; public boolean isWhiteSide() { return this.whiteSide; } public boolean isHumanPlayer() { return this.humanPlayer; } } public class HumanPlayer extends Player { public HumanPlayer(boolean whiteSide) { this.whiteSide = whiteSide; this.humanPlayer = true; } } public class ComputerPlayer extends Player { public ComputerPlayer(boolean whiteSide) { this.whiteSide = whiteSide; this.humanPlayer = false; } } |
Move: To represent a chess move:
public class Move { private Player player; private Spot start; private Spot end; private Piece pieceMoved; private Piece pieceKilled; private boolean castlingMove = false; public Move(Player player, Spot start, Spot end) { this.player = player; this.start = start; this.end = end; this.pieceMoved = start.getPiece(); } public boolean isCastlingMove() { return this.castlingMove; } public void setCastlingMove(boolean castlingMove) { this.castlingMove = castlingMove; } } |
public enum GameStatus { ACTIVE, BLACK_WIN, WHITE_WIN, FORFEIT, STALEMATE, RESIGNATION } |
Game: To represent a chess game:
public class Game { private Player[] players; private Board board; private Player currentTurn; private GameStatus status; private List<Move> movesPlayed; private void initialize(Player p1, Player p2) { players[0] = p1; players[1] = p2; board.resetBoard(); if (p1.isWhiteSide()) { this.currentTurn = p1; } else { this.currentTurn = p2; } movesPlayed.clear(); } public boolean isEnd() { return this.getStatus() != GameStatus.ACTIVE; } public boolean getStatus() { return this.status; } public void setStatus(GameStatus status) { this.status = status; } public boolean playerMove(Player player, int startX, int startY, int endX, int endY) { Spot startBox = board.getBox(startX, startY); Spot endBox = board.getBox(startY, endY); Move move = new Move(player, startBox, endBox); return this.makeMove(move, player); } private boolean makeMove(Move move, Player player) { Piece sourcePiece = move.getStart().getPiece(); if (sourcePiece == null) { return false; } // valid player if (player != currentTurn) { return false; } if (sourcePiece.isWhite() != player.isWhiteSide()) { return false; } // valid move? if (!sourcePiece.canMove(board, move.getStart(), move.getEnd())) { return false; } // kill? Piece destPiece = move.getStart().getPiece(); if (destPiece != null) { destPiece.setKilled(true); move.setPieceKilled(destPiece); } // castling? if (sourcePiece != null && sourcePiece instanceof King && sourcePiece.isCastlingMove()) { move.setCastlingMove(true); } // store the move movesPlayed.add(move); // move piece from the stat box to end box move.getEnd().setPiece(move.getStart().getPiece()); move.getStart.setPiece(null); if (destPiece != null && destPiece instanceof King) { if (player.isWhiteSide()) { this.setStatus(GameStatus.WHITE_WIN); } else { this.setStatus(GameStatus.BLACK_WIN); } } // set the current turn to the other player if (this.currentTurn == players[0]) { this.currentTurn = players[1]; } else { this.currentTurn = players[0]; } return true; } } |
Reference: http://massivetechinterview.blogspot.com/2015/07/design-chess-game-using-oo-principles.html
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



