Design a Chess Game - GeeksforGeeks

30 Sep, 2020
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 piecepublic 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.htmlMy Personal Notes
arrow_drop_upSave
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 piecepublic 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.htmlMy Personal Notes
arrow_drop_upSave
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
shutovleonid
Java-Object Oriented
Marketing
Object-Oriented-Design
Advanced Data Structure
Algorithms
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Red-Black Tree | Set 3 (Delete)
Difference between B tree and B+ tree
Splay Tree | Set 1 (Search)
Fibonacci Heap | Set 1 (Introduction)
Pattern Searching using Suffix Tree
SDE SHEET - A Complete Guide for SDE Preparation
Top 50 Array Coding Problems for Interviews
DSA Sheet by Love Babbar
Difference between BFS and DFS
A* Search Algorithm