Saturday, November 16, 2024
Google search engine
HomeData Modelling & AIDesign a Chess Game

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:

  1. Spot: A spot represents one block of the 8×8 grid and an optional piece.
  2. 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.
  3. Board: Board is an 8×8 set of boxes containing all active chess pieces.
  4. Player: Player class represents one of the participants playing the game.
  5. 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.
  6. 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.
  7. 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

    Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
    Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments