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 neveropen!
