7
\$\begingroup\$

I have written a 2 player chess game in C++.

Things I have accomplished so far:

  1. Legal moves validation
  2. Bit board generation

Things I look forward to (would appreciate advice on them):

  1. Move generation
  2. Move ordering (based on move values for each square)
  3. Pruning
  4. Reading data from opening books

Here is the model breakdown:

  • GameLogic: As the name indicates, initializes two players and keeps track of current player. Takes turns etc.
  • Player: Contains 16 pieces, checks for check and checkmate, castling, etc.
  • Piece: Contains respective piece strategies. Responsible for moving piece logic.
  • PieceStrategy: Responsible for respective move validation and bit board generation.
  • Bitboard: Contains 64 bit integers for possible moves and current positions on the board.
  • Board:*Contains 8x8 arrays for positions and moves representation.

Bitboard:

    class Bitboard {

    public:
        U64 position;
        U64 moves;

        LinkedList *computePositionsFromBitboard(U64 bitboardPosition) {

            LinkedList *list = new LinkedList();

            for(int order = 0; bitboardPosition != 0;) {
                for(; (bitboardPosition & 1) != 1; bitboardPosition >>= 1) {
                    order ++;
                }

                bitboardPosition &= 0b1111111111111111111111111111111111111111111111111111111111111110;

                int x = order % 8;
                int y = order / 8;

                Position position = Board::indexToPosition(x, y);
                list->add(position);
            }

            return list;
        }

        U64 computeBitboardFromPosition(Position position) {

            Index index = Board::positionToIndex(position);
            int x = index.x;
            int y = index.y;

            int order = (y * 8) + x;
            U64 bitboard = 1ull << order;
            return bitboard;
        }

        void performBitwiseORForPosition(Bitboard *first, Bitboard *second) {
            first->position |= second->position;
        }

        void performBitwiseANDForPosition(Bitboard *first, Bitboard *second) {
            first->position &= second->position;
        }

        void performBitwiseNOTForPosition(Bitboard *bitboard) {
            bitboard->position = ~bitboard->position;
        }

        void performBitwiseORForMoves(Bitboard *first, Bitboard *second) {
            first->moves |= second->moves;
        }

        void performBitwiseANDForMoves(Bitboard *first, Bitboard *second) {
            first->moves &= second->moves;
        }

        void performBitwiseNOTForMoves(Bitboard *bitboard) {
            bitboard->moves = ~bitboard->moves;
        }
    };

BitboardHandler:

    class BitboardHandler {

    private:
        Board *board;
        Color color;
        CentralBitboard *centralBitboard;

    public:
        BitboardHandler(Board *board, Color color, CentralBitboard *centralBitboard) {
            this->board = board;
            this->color = color;
            this->centralBitboard = centralBitboard;
        }

        void clearAllMovesBitboards() {
            this->centralBitboard->moves = 0;
            this->centralBitboard->pawnBitboard->moves = 0;
            this->centralBitboard->knightBitboard->moves = 0;
            this->centralBitboard->bishopBitboard->moves = 0;
            this->centralBitboard->rookBitboard->moves = 0;
            this->centralBitboard->queenBitboard->moves = 0;
            this->centralBitboard->kingBitboard->moves = 0;
        }

        void updateArray(bool whiteArray[8][8], bool blackArray[8][8], U64 bitboard) {
            for(LinkedList::Node *node = this->centralBitboard->computePositionsFromBitboard(bitboard)->head; node != nullptr; node = node->next) {
                Index index = this->board->positionToIndex(node->position);

                if (this->color == white) {
                    whiteArray[index.y][index.x] = true;
                } else {
                    blackArray[index.y][index.x] = true;
                }
            }
        }

        void updatePresenceAndMovesArrays() {
            if (this->color == white) {
                memset(this->board->whitePresenceArray, 0, sizeof(this->board->whitePresenceArray));
                memset(this->board->whitePawnPresenceArray, 0, sizeof(this->board->whitePawnPresenceArray));
                memset(this->board->whiteKnightPresenceArray, 0, sizeof(this->board->whiteKnightPresenceArray));
                memset(this->board->whiteBishopPresenceArray, 0, sizeof(this->board->whiteBishopPresenceArray));
                memset(this->board->whiteRookPresenceArray, 0, sizeof(this->board->whiteRookPresenceArray));
                memset(this->board->whiteQueenPresenceArray, 0, sizeof(this->board->whiteQueenPresenceArray));
                memset(this->board->whiteKingPresenceArray, 0, sizeof(this->board->whiteKingPresenceArray));

                memset(this->board->whiteMovesArray, 0, sizeof(this->board->whiteMovesArray));
                memset(this->board->whitePawnMovesArray, 0, sizeof(this->board->whitePawnMovesArray));
                memset(this->board->whiteKnightMovesArray, 0, sizeof(this->board->whiteKnightMovesArray));
                memset(this->board->whiteBishopMovesArray, 0, sizeof(this->board->whiteBishopMovesArray));
                memset(this->board->whiteRookMovesArray, 0, sizeof(this->board->whiteRookMovesArray));
                memset(this->board->whiteQueenMovesArray, 0, sizeof(this->board->whiteQueenMovesArray));
                memset(this->board->whiteKingMovesArray, 0, sizeof(this->board->whiteKingMovesArray));
            } else {
                memset(this->board->blackPresenceArray, 0, sizeof(this->board->blackPresenceArray));
                memset(this->board->blackPawnPresenceArray, 0, sizeof(this->board->blackPawnPresenceArray));
                memset(this->board->blackKnightPresenceArray, 0, sizeof(this->board->blackKnightPresenceArray));
                memset(this->board->blackBishopPresenceArray, 0, sizeof(this->board->blackBishopPresenceArray));
                memset(this->board->blackRookPresenceArray, 0, sizeof(this->board->blackRookPresenceArray));
                memset(this->board->blackQueenPresenceArray, 0, sizeof(this->board->blackQueenPresenceArray));
                memset(this->board->blackKingPresenceArray, 0, sizeof(this->board->blackKingPresenceArray));

                memset(this->board->blackMovesArray, 0, sizeof(this->board->blackMovesArray));
                memset(this->board->blackPawnMovesArray, 0, sizeof(this->board->blackPawnMovesArray));
                memset(this->board->blackKnightMovesArray, 0, sizeof(this->board->blackKnightMovesArray));
                memset(this->board->blackBishopMovesArray, 0, sizeof(this->board->blackBishopMovesArray));
                memset(this->board->blackRookMovesArray, 0, sizeof(this->board->blackRookMovesArray));
                memset(this->board->blackQueenMovesArray, 0, sizeof(this->board->blackQueenMovesArray));
                memset(this->board->blackKingMovesArray, 0, sizeof(this->board->blackKingMovesArray));
            }

            this->updateArray(this->board->whitePresenceArray, this->board->blackPresenceArray, this->centralBitboard->position);
            this->updateArray(this->board->whitePawnPresenceArray, this->board->blackPawnPresenceArray, this->centralBitboard->pawnBitboard->position);
            this->updateArray(this->board->whiteKnightPresenceArray, this->board->blackKnightPresenceArray, this->centralBitboard->knightBitboard->position);
            this->updateArray(this->board->whiteBishopPresenceArray, this->board->blackBishopPresenceArray, this->centralBitboard->bishopBitboard->position);
            this->updateArray(this->board->whiteRookPresenceArray, this->board->blackRookPresenceArray, this->centralBitboard->rookBitboard->position);
            this->updateArray(this->board->whiteQueenPresenceArray, this->board->blackQueenPresenceArray, this->centralBitboard->queenBitboard->position);
            this->updateArray(this->board->whiteKingPresenceArray, this->board->blackKingPresenceArray, this->centralBitboard->kingBitboard->position);

            this->updateArray(this->board->whiteMovesArray, this->board->blackMovesArray, this->centralBitboard->moves);
            this->updateArray(this->board->whitePawnMovesArray, this->board->blackPawnMovesArray, this->centralBitboard->pawnBitboard->moves);
            this->updateArray(this->board->whiteKnightMovesArray, this->board->blackKnightMovesArray, this->centralBitboard->knightBitboard->moves);
            this->updateArray(this->board->whiteBishopMovesArray, this->board->blackBishopMovesArray, this->centralBitboard->bishopBitboard->moves);
            this->updateArray(this->board->whiteRookMovesArray, this->board->blackRookMovesArray, this->centralBitboard->rookBitboard->moves);
            this->updateArray(this->board->whiteQueenMovesArray, this->board->blackQueenMovesArray, this->centralBitboard->queenBitboard->moves);
            this->updateArray(this->board->whiteKingMovesArray, this->board->blackKingMovesArray, this->centralBitboard->kingBitboard->moves);
        }
    };

Board:

    class Board {

    public:
        Piece *pieceArray[8][8];

        bool whitePresenceArray[8][8];
        bool blackPresenceArray[8][8];

        bool whitePawnPresenceArray[8][8];
        bool whiteKnightPresenceArray[8][8];
        bool whiteBishopPresenceArray[8][8];
        bool whiteRookPresenceArray[8][8];
        bool whiteQueenPresenceArray[8][8];
        bool whiteKingPresenceArray[8][8];

        bool blackPawnPresenceArray[8][8];
        bool blackKnightPresenceArray[8][8];
        bool blackBishopPresenceArray[8][8];
        bool blackRookPresenceArray[8][8];
        bool blackQueenPresenceArray[8][8];
        bool blackKingPresenceArray[8][8];

        bool whiteMovesArray[8][8];
        bool blackMovesArray[8][8];

        bool whitePawnMovesArray[8][8];
        bool whiteKnightMovesArray[8][8];
        bool whiteBishopMovesArray[8][8];
        bool whiteRookMovesArray[8][8];
        bool whiteQueenMovesArray[8][8];
        bool whiteKingMovesArray[8][8];

        bool blackPawnMovesArray[8][8];
        bool blackKnightMovesArray[8][8];
        bool blackBishopMovesArray[8][8];
        bool blackRookMovesArray[8][8];
        bool blackQueenMovesArray[8][8];
        bool blackKingMovesArray[8][8];

        static Index positionToIndex(Position position) {

            Index index;

            index.x = position.file - 'a';
            index.y = position.rank - '1';

            return index;
        }

        static Position indexToPosition(int x, int y) {

            Position position;

            position.file = x + 'a';
            position.rank = y + '1';

            return position;
        }
    };

CentralBitboard:

    class CentralBitboard : public Bitboard {

    public:
        DecentralBitboard *pawnBitboard;
        DecentralBitboard *knightBitboard;
        DecentralBitboard *bishopBitboard;
        DecentralBitboard *rookBitboard;
        DecentralBitboard *queenBitboard;
        DecentralBitboard *kingBitboard;

        CentralBitboard() {
            this->pawnBitboard = new DecentralBitboard();
            this->knightBitboard = new DecentralBitboard();
            this->bishopBitboard = new DecentralBitboard();
            this->rookBitboard = new DecentralBitboard();
            this->queenBitboard = new DecentralBitboard();
            this->kingBitboard = new DecentralBitboard();
        }

        void clearPreviousPosition(DecentralBitboard decentralBitboard) {
            this->performBitwiseNOTForPosition(&decentralBitboard);
            this->performBitwiseANDForPosition(this, &decentralBitboard);
        }

        void clearPreviousPawnPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseNOTForPosition(decentralBitboard);
            this->performBitwiseANDForPosition(this->pawnBitboard, decentralBitboard);
        }

        void clearPreviousKnightPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseNOTForPosition(decentralBitboard);
            this->performBitwiseANDForPosition(this->knightBitboard, decentralBitboard);
        }

        void clearPreviousBishopPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseNOTForPosition(decentralBitboard);
            this->performBitwiseANDForPosition(this->bishopBitboard, decentralBitboard);
        }

        void clearPreviousRookPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseNOTForPosition(decentralBitboard);
            this->performBitwiseANDForPosition(this->rookBitboard, decentralBitboard);
        }

        void clearPreviousQueenPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseNOTForPosition(decentralBitboard);
            this->performBitwiseANDForPosition(this->queenBitboard, decentralBitboard);
        }

        void clearPreviousKingPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseNOTForPosition(decentralBitboard);
            this->performBitwiseANDForPosition(this->kingBitboard, decentralBitboard);
        }

        void setPawnPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForPosition(this->pawnBitboard, decentralBitboard);
            this->performBitwiseORForPosition(this, decentralBitboard);
        }

        void setKnightPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForPosition(this->knightBitboard, decentralBitboard);
            this->performBitwiseORForPosition(this, decentralBitboard);
        }

        void setBishopPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForPosition(this->bishopBitboard, decentralBitboard);
            this->performBitwiseORForPosition(this, decentralBitboard);
        }

        void setRookPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForPosition(this->rookBitboard, decentralBitboard);
            this->performBitwiseORForPosition(this, decentralBitboard);
        }

        void setQueenPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForPosition(this->queenBitboard, decentralBitboard);
            this->performBitwiseORForPosition(this, decentralBitboard);
        }

        void setKingPosition(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForPosition(this->kingBitboard, decentralBitboard);
            this->performBitwiseORForPosition(this, decentralBitboard);
        }

        void setPawnMoves(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForMoves(this->pawnBitboard, decentralBitboard);
            this->performBitwiseORForMoves(this, decentralBitboard);
        }

        void setKnightMoves(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForMoves(this->knightBitboard, decentralBitboard);
            this->performBitwiseORForMoves(this, decentralBitboard);
        }

        void setBishopMoves(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForMoves(this->bishopBitboard, decentralBitboard);
            this->performBitwiseORForMoves(this, decentralBitboard);
        }

        void setRookMoves(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForMoves(this->rookBitboard, decentralBitboard);
            this->performBitwiseORForMoves(this, decentralBitboard);
        }

        void setQueenMoves(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForMoves(this->queenBitboard, decentralBitboard);
            this->performBitwiseORForMoves(this, decentralBitboard);
        }

        void setKingMoves(DecentralBitboard *decentralBitboard) {
            this->performBitwiseORForMoves(this->kingBitboard, decentralBitboard);
            this->performBitwiseORForMoves(this, decentralBitboard);
        }
    };

DecentralBitboard:

    class DecentralBitboard : public Bitboard {

    public:
        void setPosition(Position position) {
            this->position = this->computeBitboardFromPosition(position);
        }

        void setMoves(LinkedList *moves) {
            this->moves = 0;
            for(LinkedList::Node *node = moves->head; node != nullptr; node = node->next) {
                this->moves |= this->computeBitboardFromPosition(node->position);
            }
        }
    };

GameLogic:

    class GameLogic : ErrorDelegate, InputDelegate {

    private:
        Board *board;
        Player *whitePlayer;
        Player *blackPlayer;
        Player *currentPlayer;
        ErrorDelegate *errorDelegate;
        InputDelegate *inputDelegate;

    public:
        GameLogic(ErrorDelegate *errorDelegate, InputDelegate *inputDelegate) {
            this->board = new Board();
            this->errorDelegate = errorDelegate;
            this->inputDelegate = inputDelegate;
            this->whitePlayer = new Player(this, this, white, this->board);
            this->blackPlayer = new Player(this, this, black, this->board);
            this->whitePlayer->opponent = this->blackPlayer;
            this->blackPlayer->opponent = this->whitePlayer;
            this->currentPlayer = this->whitePlayer;

            this->whitePlayer->updateMoves();
            this->blackPlayer->updateMoves();
        }

        Board *getBoard() {
            return this->board;
        }

        bool movePiece(Position from, Position to) {

            if (this->currentPlayer->takeTurn(from, to) == true) {
                this->currentPlayer->removeEnPassants();
                this->currentPlayer = this->currentPlayer->opponent;

                this->whitePlayer->updateMoves();
                this->blackPlayer->updateMoves();

                return true;
            }

            return false;
        }

        bool shouldTakeInputFromHuman() {
            return not this->currentPlayer->isAI;
        }

        void inputTaken(Position from, Position to) {
            this->inputDelegate->inputTaken(from, to);
        }

        void askAIToGenerateMove() {
            ((AIPlayer *)this->currentPlayer)->generateMove();
        }

        void error(string message) {
            this->errorDelegate->error(message);
        }
    };

BishopStrategy:

    class BishopStrategy : public PieceStrategy {

    private:
        void setColor(Color color) {
            this->color = color;
        }

        void setPosition(Position position) {
            this->centralBitboard->clearPreviousPosition(*this->decentralBitboard);
            this->centralBitboard->clearPreviousBishopPosition(this->decentralBitboard);
            this->position = position;

            this->decentralBitboard->setPosition(this->position);
            this->centralBitboard->setBishopPosition(this->decentralBitboard);
        }

        void updateMoves() {
            this->decentralBitboard->setMoves(this->getMoves(this->position));
            this->centralBitboard->setBishopMoves(this->decentralBitboard);
        }

        LinkedList *getMoves(Position position) {

            LinkedList *movesList = new LinkedList();
            this->getMoves(this, movesList);
            return movesList;
        }

    public:
        BishopStrategy(Board *board) : PieceStrategy(board) {
        }

        static void getMoves(PieceStrategy *pieceStrategy, LinkedList *movesList) {

            Index index = pieceStrategy->board->positionToIndex(pieceStrategy->position);

            if (index.y <= index.x) {
                for (int x = index.x - index.y, y = 0; x < 8; x ++, y ++) {
                    Position to = pieceStrategy->board->indexToPosition(x, y);
                    pieceStrategy->addMoveToList(pieceStrategy->position, to, movesList);
                }
            } else {
                for (int x = 0, y = index.y - index.x; y < 8; x ++, y ++) {
                    Position to = pieceStrategy->board->indexToPosition(x, y);
                    pieceStrategy->addMoveToList(pieceStrategy->position, to, movesList);
                }
            }

            if (index.x + index.y < 8) {
                for (int x = 0, y = index.x + index.y; y >= 0; x ++, y --) {
                    Position to = pieceStrategy->board->indexToPosition(x, y);
                    pieceStrategy->addMoveToList(pieceStrategy->position, to, movesList);
                }
            } else {
                for (int x = index.x + index.y - 7, y = 7; x < 8; x ++, y --) {
                    Position to = pieceStrategy->board->indexToPosition(x, y);
                    pieceStrategy->addMoveToList(pieceStrategy->position, to, movesList);
                }
            }
        }

        bool move(Position from, Position to) {

            Index toIndex = this->board->positionToIndex(to);
            Piece *destinationPiece = this->board->pieceArray[toIndex.y][toIndex.x];

            if (destinationPiece == nullptr || destinationPiece->color != this->color) {
                return this->move(this->board, from, to);
            }

            return false;
        }

        static bool move(Board *board, Position from, Position to) {

            using namespace std;

            Index fromIndex = board->positionToIndex(from);
            Index toIndex = board->positionToIndex(to);

            if (from.file != to.file) {
                if (from.rank != to.rank) {
                    if (fabs(from.file - to.file) == fabs(from.rank - to.rank)) {

                        if (fromIndex.x < toIndex.x && fromIndex.y < toIndex.y) {
                            for (int i = fromIndex.x + 1, j = fromIndex.y + 1; i < toIndex.x && j < toIndex.y; i ++, j ++) {
                                if (board->pieceArray[j][i] != nullptr) {
                                    return false;
                                }
                            }
                        } else if (fromIndex.x > toIndex.x && fromIndex.y < toIndex.y) {
                            for (int i = fromIndex.x - 1, j = fromIndex.y + 1; i > toIndex.x && j < toIndex.y; i --, j ++) {
                                if (board->pieceArray[j][i] != nullptr) {
                                    return false;
                                }
                            }
                        } else if (fromIndex.x > toIndex.x && fromIndex.y > toIndex.y) {
                            for (int i = fromIndex.x - 1, j = fromIndex.y - 1; i > toIndex.x && j > toIndex.y; i --, j --) {
                                if (board->pieceArray[j][i] != nullptr) {
                                    return false;
                                }
                            }
                        } else if (fromIndex.x < toIndex.x && fromIndex.y > toIndex.y) {
                            for (int i = fromIndex.x + 1, j = fromIndex.y - 1; i < toIndex.x && j > toIndex.y; i ++, j --) {
                                if (board->pieceArray[j][i] != nullptr) {
                                    return false;
                                }
                            }
                        }

                        return true;
                    }
                }
            }

            return false;
        }
    };

KingStrategy:

    class KingStrategy : public PieceStrategy {

    private:
        void setColor(Color color) {
            this->color = color;
        }

        void setPosition(Position position) {
            this->centralBitboard->clearPreviousPosition(*this->decentralBitboard);
            this->centralBitboard->clearPreviousKingPosition(this->decentralBitboard);
            this->position = position;

            this->decentralBitboard->setPosition(this->position);
            this->centralBitboard->setKingPosition(this->decentralBitboard);
        }

        void updateMoves() {
            this->decentralBitboard->setMoves(this->getMoves(this->position));
            this->centralBitboard->setKingMoves(this->decentralBitboard);
        }

        LinkedList *getMoves(Position position) {

            LinkedList *movesList = new LinkedList();

            if (position.rank > '1') {
                Position toOneForwardStep = { (char)(position.rank - 1), position.file };
                this->addMoveToList(position, toOneForwardStep, movesList);
            }

            if (position.rank < '8') {
                Position toOneBackwardStep = { (char)(position.rank + 1), position.file };
                this->addMoveToList(position, toOneBackwardStep, movesList);
            }

            if (position.file > 'a') {
                Position toOneLeftStep = { position.rank, (char)(position.file - 1) };
                this->addMoveToList(position, toOneLeftStep, movesList);

                if (position.rank > '1') {
                    Position toOneLeftBackwardStep = { (char)(position.rank - 1), (char)(position.file - 1) };
                    this->addMoveToList(position, toOneLeftBackwardStep, movesList);
                }

                if (position.rank < '8') {
                    Position toOneLeftForwardStep = { (char)(position.rank + 1), (char)(position.file - 1) };
                    this->addMoveToList(position, toOneLeftForwardStep, movesList);
                }
            }

            if (position.file < 'h') {
                Position toOneRightStep = { position.rank, (char)(position.file + 1) };
                this->addMoveToList(position, toOneRightStep, movesList);

                if (position.rank > '1') {
                    Position toOneRightBackwardStep = { (char)(position.rank - 1), (char)(position.file + 1) };
                    this->addMoveToList(position, toOneRightBackwardStep, movesList);
                }

                if (position.rank < '8') {
                    Position toOneRightForwardStep = { (char)(position.rank + 1), (char)(position.file + 1) };
                    this->addMoveToList(position, toOneRightForwardStep, movesList);
                }
            }

            return movesList;
        }

    public:
        KingStrategy(Board *board) : PieceStrategy(board) {
        }

        bool move(Position from, Position to) {

            using namespace std;

            Index toIndex = this->board->positionToIndex(to);
            Piece *destinationPiece = this->board->pieceArray[toIndex.y][toIndex.x];

            if (destinationPiece == nullptr || destinationPiece->color != this->color) {
                Index fromIndex = this->board->positionToIndex(from);

                if (fabs(from.file - to.file) <= 1 && fabs(from.rank - to.rank) <= 1) {

                    return true;

                } else if (this->hasMoved == false) {
                    if (to.file == 'c' && from.rank == to.rank) {

                        if (fromIndex.x > toIndex.x) {
                            for (int i = toIndex.x + 1; i < fromIndex.x; i ++) {
                                if(this->pieceStrategyDelegate->canCheckDuringPassing(board->indexToPosition(i, fromIndex.y))) {
                                    return false;
                                }
                            }
                        }

                        if (this->pieceStrategyDelegate->moveQueenSideRook() == true) {

                            return true;
                        }
                        return false;

                    } else if (to.file == 'g' && from.rank == to.rank) {

                        if (fromIndex.x < toIndex.x) {
                            for (int i = fromIndex.x + 1; i < toIndex.x; i ++) {
                                if(this->pieceStrategyDelegate->canCheckDuringPassing(board->indexToPosition(fromIndex.y, i))) {
                                    return false;
                                }
                            }
                        }

                        if (this->pieceStrategyDelegate->moveKingSideRook() == true) {

                            return true;
                        }
                        return false;
                    }
                }
            }

            return false;
        }
    };

KnightStrategy:

    class KnightStrategy : public PieceStrategy {

    private:
        void setColor(Color color) {
            this->color = color;
        }

        void setPosition(Position position) {
            this->centralBitboard->clearPreviousPosition(*this->decentralBitboard);
            this->centralBitboard->clearPreviousKnightPosition(this->decentralBitboard);
            this->position = position;

            this->decentralBitboard->setPosition(this->position);
            this->centralBitboard->setKnightPosition(this->decentralBitboard);
        }

        void updateMoves() {
            this->decentralBitboard->setMoves(this->getMoves(this->position));
            this->centralBitboard->setKnightMoves(this->decentralBitboard);
        }

        LinkedList *getMoves(Position position) {

            LinkedList *movesList = new LinkedList();

            if (position.file > 'a') {
                if (position.rank > '2') {
                    Position toOneLeftTwoBackwardStep = { (char)(position.rank - 2), (char)(position.file - 1) };
                    this->addMoveToList(position, toOneLeftTwoBackwardStep, movesList);
                }

                if (position.rank < '7') {
                    Position toOneLeftTwoForwardStep = { (char)(position.rank + 2), (char)(position.file - 1) };
                    this->addMoveToList(position, toOneLeftTwoForwardStep, movesList);
                }

                if (position.file > 'b') {
                    if (position.rank > '1') {
                        Position toTwoLeftOneBackwardStep = { (char)(position.rank - 1), (char)(position.file - 2) };
                        this->addMoveToList(position, toTwoLeftOneBackwardStep, movesList);
                    }

                    if (position.rank < '8') {
                        Position toTwoLeftOneForwardStep = { (char)(position.rank + 1), (char)(position.file - 2) };
                        this->addMoveToList(position, toTwoLeftOneForwardStep, movesList);
                    }
                }
            }

            if (position.file < 'h') {
                if (position.rank > '2') {
                    Position toOneRightTwoBackwardStep = { (char)(position.rank - 2), (char)(position.file + 1) };
                    this->addMoveToList(position, toOneRightTwoBackwardStep, movesList);
                }

                if (position.rank < '7') {
                    Position toOneRightTwoForwardStep = { (char)(position.rank + 2), (char)(position.file + 1) };
                    this->addMoveToList(position, toOneRightTwoForwardStep, movesList);
                }

                if (position.file < 'g') {
                    if (position.rank > '1') {
                        Position toTwoRightOneBackwardStep = { (char)(position.rank - 1), (char)(position.file + 2) };
                        this->addMoveToList(position, toTwoRightOneBackwardStep, movesList);
                    }

                    if (position.rank < '8') {
                        Position toTwoRightOneForwardStep = { (char)(position.rank + 1), (char)(position.file + 2) };
                        this->addMoveToList(position, toTwoRightOneForwardStep, movesList);
                    }
                }
            }

            return movesList;
        }

    public:
        KnightStrategy(Board *board) : PieceStrategy(board) {
        }

        bool move(Position from, Position to) {

            using namespace std;

            Index toIndex = this->board->positionToIndex(to);
            Piece *destinationPiece = this->board->pieceArray[toIndex.y][toIndex.x];

            if (destinationPiece == nullptr || destinationPiece->color != this->color) {
                if (fabs(from.file - to.file) == 2 && fabs(from.rank - to.rank) == 1) {

                    return true;

                } else if (fabs(from.rank - to.rank) == 2 && fabs(from.file - to.file) == 1) {

                    return true;
                }
            }

            return false;
        }
    };

PawnStrategy:

    class PawnStrategy : public PieceStrategy {

    private:
        int oneStep = 1;
        int twoStep = 2;

        void setColor(Color color) {

            this->color = color;

            if (color == black) {

                oneStep *= -1;
                twoStep *= -1;
            }
        }

        void setPosition(Position position) {
            this->centralBitboard->clearPreviousPosition(*this->decentralBitboard);
            this->centralBitboard->clearPreviousPawnPosition(this->decentralBitboard);
            this->position = position;

            this->decentralBitboard->setPosition(this->position);
            this->centralBitboard->setPawnPosition(this->decentralBitboard);
        }

        void updateMoves() {
            this->decentralBitboard->setMoves(this->getMoves(this->position));
            this->centralBitboard->setPawnMoves(this->decentralBitboard);
        }

        LinkedList *getMoves(Position position) {

            LinkedList *movesList = new LinkedList();

            if ((this->color == white && position.rank < '7') || (this->color == black && position.rank > '2')) {
                if ((this->color == white && position.rank < '8') || (this->color == black && position.rank > '1')) {
                    Position toOneStep = { position.rank + oneStep, position.file };
                    this->addMoveToList(position, toOneStep, movesList);

                    if (position.file > 'a') {
                        Position toOneLeftStep = { position.rank + oneStep, (char)(position.file - 1) };
                        this->addMoveToList(position, toOneLeftStep, movesList);
                    }

                    if (position.file < 'h') {
                        Position toOneRightStep = { position.rank + oneStep, (char)(position.file + 1) };
                        this->addMoveToList(position, toOneRightStep, movesList);
                    }
                }
                Position toTwoStep = { position.rank + twoStep, position.file };
                this->addMoveToList(position, toTwoStep, movesList);
            }

            return movesList;
        }

    public:
        PawnStrategy(Board *board) : PieceStrategy(board) {
        }

        bool move(Position from, Position to) {

            using namespace std;

            Index toIndex = this->board->positionToIndex(to);
            Piece *destinationPiece = this->board->pieceArray[toIndex.y][toIndex.x];

            if (destinationPiece == nullptr || destinationPiece->color != this->color) {
                Index fromIndex = board->positionToIndex(from);

                if (from.file == to.file && (this->board->pieceArray[toIndex.y][toIndex.x] == nullptr || this->board->pieceArray[toIndex.y][toIndex.x]->value == KING)) {

                    if (from.rank + oneStep == to.rank) {

                        return true;

                    } else if (from.rank + twoStep == to.rank && this->hasMoved == false && this->board->pieceArray[fromIndex.y + oneStep][fromIndex.x] == nullptr) {

        //                this->isEnPassant = true;
                        return true;
                    }
                } else if (fabs(from.file - to.file) == 1 && from.rank + oneStep == to.rank) {

                    Piece *piece = this->board->pieceArray[toIndex.y - oneStep][toIndex.x];
                    if (this->board->pieceArray[toIndex.y][toIndex.x] != nullptr) {

                        return true;
                    } else if (from.rank == 5 && this->board->pieceArray[toIndex.y][toIndex.x] == nullptr && piece != nullptr && fabs(piece->value) == PAWN && piece->pieceStrategy->isEnPassant == true) {
                        piece->value = 0;
                        piece = nullptr;

                        return true;
                    }
                }
            }

            return false;
        }
    };

Piece:

    class Piece : PieceStrategyDelegate {

        private:
            Position previousPosition;
            Board *board;
            PieceDelegate *pieceDelegate;
            Piece *destinationPiece;

        public:
            int value;
            Color color;
            Position position;
            PieceStrategy *pieceStrategy;
            CentralBitboard *centralBitboard;

            Piece(int value, Color color, Board *board, PieceDelegate *pieceDelegate, CentralBitboard *centralBitboard) {
                this->value = value;
                this->color = color;
                this->board = board;
                this->pieceDelegate = pieceDelegate;
                this->centralBitboard = centralBitboard;
            }

            void setPieceStrategy(PieceStrategy *pieceStrategy) {

                this->pieceStrategy = pieceStrategy;
                this->pieceStrategy->pieceStrategyDelegate = this;
                this->pieceStrategy->board = this->board;
                this->pieceStrategy->centralBitboard = this->centralBitboard;
                this->pieceStrategy->setColor(this->color);
            }

            void setPosition(Position position) {
                this->position = position;
                this->pieceStrategy->setPosition(this->position);
            }

            void promoteIfApplicable() {
                if ((this->position.rank == 1 || this->position.rank == 8) && this->value == PAWN) {
                    this->value = QUEEN;
        //            this->setPieceStrategy(new QueenStrategy(this->board)); // UNCOMMENT THIS PLEASE
                }
            }

            bool moveTo(Position position) {

                if (this->pieceStrategy->move(this->position, position) == true) {

                    this->pieceStrategy->hasMoved = true;

                    this->promoteIfApplicable();

                    Index fromIndex = this->board->positionToIndex(this->position);
                    Index toIndex = this->board->positionToIndex(position);

                    this->previousPosition = this->position;
                    this->setPosition(position);

                    this->destinationPiece = this->board->pieceArray[toIndex.y][toIndex.x];
                    this->board->pieceArray[toIndex.y][toIndex.x] = this->board->pieceArray[fromIndex.y][fromIndex.x];
                    this->board->pieceArray[fromIndex.y][fromIndex.x] = nullptr;

                    return true;
                }

                return false;
            }

            void undoMove() {

                Index fromIndex = board->positionToIndex(this->position);
                Index toIndex = board->positionToIndex(this->previousPosition);

                this->setPosition(this->previousPosition);

                this->board->pieceArray[toIndex.y][toIndex.x] = this->board->pieceArray[fromIndex.y][fromIndex.x];
                this->board->pieceArray[fromIndex.y][fromIndex.x] = this->destinationPiece;
            }

            bool canCheck(Position position) {
                return this->pieceStrategy->move(this->position, position);
            }

            bool moveKingSideRook() {
                return this->pieceDelegate->moveKingSideRook();
            }

            bool moveQueenSideRook() {
                return this->pieceDelegate->moveQueenSideRook();
            }

            bool canCheckDuringPassing(Position position) {
                return this->pieceDelegate->canCheckDuringPassing(position);
            }

            void updateMoves() {
                this->pieceStrategy->updateMoves();
            }
        };

PieceStrategy:

    class PieceStrategy {

    protected:
        Color color;

    public:
        bool hasMoved;
        Position position;
        Board *board;
        PieceStrategyDelegate *pieceStrategyDelegate;
        CentralBitboard *centralBitboard;
        DecentralBitboard *decentralBitboard;

        bool isEnPassant = false;

        virtual void setColor(Color color) = 0;
        virtual void setPosition(Position position) = 0;
        virtual bool move(Position from, Position to) = 0;
        virtual LinkedList *getMoves(Position position) = 0;
        virtual void updateMoves() = 0;

        PieceStrategy(Board *board) {
            this->board = board;
            this->decentralBitboard = new DecentralBitboard();
        }

        LinkedList *addMoveToList(Position from, Position to, LinkedList *movesList) {

            if (this->move(from, to) == true) {
                movesList->add(to);
            }

            return movesList;
        }
    };

QueenStrategy:

    class QueenStrategy : public PieceStrategy {

    private:
        void setColor(Color color) {
            this->color = color;
        }

        void setPosition(Position position) {
            this->centralBitboard->clearPreviousPosition(*this->decentralBitboard);
            this->centralBitboard->clearPreviousQueenPosition(this->decentralBitboard);
            this->position = position;

            this->decentralBitboard->setPosition(this->position);
            this->centralBitboard->setQueenPosition(this->decentralBitboard);
        }

        void updateMoves() {
            this->decentralBitboard->setMoves(this->getMoves(this->position));
            this->centralBitboard->setQueenMoves(this->decentralBitboard);
        }

        LinkedList *getMoves(Position position) {

            LinkedList *movesList = new LinkedList();
            BishopStrategy::getMoves(this, movesList);
            RookStrategy::getMoves(this, movesList);
            return movesList;
        }

    public:
        QueenStrategy(Board *board) : PieceStrategy(board) {
        }

        bool move(Position from, Position to) {

            Index toIndex = this->board->positionToIndex(to);
            Piece *destinationPiece = this->board->pieceArray[toIndex.y][toIndex.x];

            if (destinationPiece == nullptr || destinationPiece->color != this->color) {
                if (RookStrategy::move(this->board, from, to)) {
                    return true;
                } else if (BishopStrategy::move(this->board, from, to)) {
                    return true;
                }
            }

            return false;
        }
    };

RookStrategy:

    class RookStrategy : public PieceStrategy {

    private:
        void setColor(Color color) {
            this->color = color;
        }

        void setPosition(Position position) {
            this->centralBitboard->clearPreviousPosition(*this->decentralBitboard);
            this->centralBitboard->clearPreviousRookPosition(this->decentralBitboard);
            this->position = position;

            this->decentralBitboard->setPosition(this->position);
            this->centralBitboard->setRookPosition(this->decentralBitboard);
        }

        void updateMoves() {
            this->decentralBitboard->setMoves(this->getMoves(this->position));
            this->centralBitboard->setRookMoves(this->decentralBitboard);
        }

        LinkedList *getMoves(Position position) {

            LinkedList *movesList = new LinkedList();
            this->getMoves(this, movesList);
            return movesList;
        }

    public:
        RookStrategy(Board *board) : PieceStrategy(board) {
        }

        static void getMoves(PieceStrategy *pieceStrategy, LinkedList *movesList) {

            Index fromIndex = pieceStrategy->board->positionToIndex(pieceStrategy->position);
            Index index = fromIndex;

            for (int rank = 0; rank < 8; rank ++) {
                index.y = rank;
                Position to = pieceStrategy->board->indexToPosition(index.x, index.y);
                pieceStrategy->addMoveToList(pieceStrategy->position, to, movesList);
            }

            index.y = fromIndex.y;

            for (int file = 0; file < 8; file ++) {
                index.x = file;
                Position to = pieceStrategy->board->indexToPosition(index.x, index.y);
                pieceStrategy->addMoveToList(pieceStrategy->position, to, movesList);
            }
        }

        bool move(Position from, Position to) {

            Index toIndex = this->board->positionToIndex(to);
            Piece *destinationPiece = this->board->pieceArray[toIndex.y][toIndex.x];

            if (destinationPiece == nullptr || destinationPiece->color != this->color) {
                return this->move(this->board, from, to);
            }

            return false;
        }

        static bool move(Board *board, Position from, Position to) {

            Index fromIndex = board->positionToIndex(from);
            Index toIndex = board->positionToIndex(to);

            if (from.file == to.file) {
                if (from.rank != to.rank) {

                    if (fromIndex.y < toIndex.y) {
                        for (int i = fromIndex.y + 1; i < toIndex.y; i ++) {
                            if (board->pieceArray[i][fromIndex.x] != nullptr) {
                                return false;
                            }
                        }
                    } else {
                        for (int i = toIndex.y + 1; i < fromIndex.y; i ++) {
                            if (board->pieceArray[i][fromIndex.x] != nullptr) {
                                return false;
                            }
                        }
                    }

                    return true;
                }
            } else if (from.rank == to.rank) {
                if (from.file != to.file) {

                    if (fromIndex.x < toIndex.x) {
                        for (int i = fromIndex.x + 1; i < toIndex.x; i ++) {
                            if (board->pieceArray[fromIndex.y][i] != nullptr) {
                                return false;
                            }
                        }
                    } else {
                        for (int i = toIndex.x + 1; i < fromIndex.x; i ++) {
                            if (board->pieceArray[fromIndex.y][i] != nullptr) {
                                return false;
                            }
                        }
                    }

                    return true;
                }
            }

            return false;
        }
    };

Player:

    class Player : PieceDelegate {

    protected:
        Color color;
        Piece *king;
        Piece *kingSideRook;
        Piece *queenSideRook;
        Board *board;
        CentralBitboard *centralBitboard;

        ErrorDelegate *errorDelegate;
        InputDelegate *inputDelegate;
        BitboardHandler *bitboardHandler;

    public:
        LinkedList *piecesList;
        Player *opponent;
        bool isAI;

        Player(ErrorDelegate *errorDelegate, InputDelegate *inputDelegate, Color color, Board *board) {

            this->piecesList = new LinkedList();

            this->errorDelegate = errorDelegate;
            this->inputDelegate = inputDelegate;
            this->color = color;
            this->board = board;

            this->centralBitboard = new CentralBitboard();
            this->bitboardHandler = new BitboardHandler(this->board, this->color, this->centralBitboard);

            this->setupPieces();

            this->isAI = false;
        }

        void addPiece(Piece *piece) {
            if (piece != nullptr) {
                this->piecesList->add(piece);
            }
        }

        void removePiece(Piece *piece) {
            if (piece != nullptr) {
                this->piecesList->remove(piece);
            }
        }

        bool isUnderCheck() {

            this->updateMoves();
            this->opponent->updateMoves();

            if ((this->opponent->centralBitboard->moves & this->king->pieceStrategy->decentralBitboard->position) != 0) {
                return true;
            }
            return false;
        }

        bool isUnderCheckmate() {

            for(LinkedList::Node *pieceNode = this->piecesList->head; pieceNode != nullptr; pieceNode = pieceNode->next) {
                for(LinkedList::Node *moveNode = this->centralBitboard->computePositionsFromBitboard(pieceNode->piece->pieceStrategy->decentralBitboard->moves)->head; moveNode != nullptr; moveNode = moveNode->next) {

                    Index toIndex = this->board->positionToIndex(moveNode->position);
                    Piece *capturedPiece = this->board->pieceArray[toIndex.y][toIndex.x];

                    if (pieceNode->piece->moveTo(moveNode->position) == true) {

                        this->opponent->removePiece(capturedPiece);

                        if (this->isUnderCheck() == false) {
                            pieceNode->piece->undoMove();
                            this->opponent->addPiece(capturedPiece);

                            return false;
                        }
                        pieceNode->piece->undoMove();
                        this->opponent->addPiece(capturedPiece);
                    }
                }
            }
            return true;
        }

        void setupPieces() {

            for (int a = 7; a > -1; a--) {
                for (int b = 0; b < 8; b++) {
                    int value = startup[a][b];

                    if (value != 0) {

                        Position position = this->board->indexToPosition(b, a);

                        if (this->color == white && value > 0) {
                            this->createPiece(fabs(value), position, a, b);
                        } else if (this->color == black && value < 0) {
                            this->createPiece(fabs(value), position, a, b);
                        }
                    }
                }
            }
        }

        void createPiece(int value, Position position, int a, int b) {

            Piece *piece = PieceFactory::createPiece(value, this->color, position, this->board, this, this->centralBitboard);
            this->addPiece(piece);

            if (value == KING) {
                this->king = piece;
            } else if (value == ROOK && position.file == 'a') {
                this->queenSideRook = piece;
            } else if (value == ROOK && position.file == 'h') {
                this->kingSideRook = piece;
            }

            this->board->pieceArray[a][b] = piece;
        }

        bool takeTurn(Position from, Position to) {

            if (this->movePiece(from, to)) {
                return true;
            }

            return false;
        }

        void updateMoves() {
            this->bitboardHandler->clearAllMovesBitboards();
            for(LinkedList::Node *node = this->piecesList->head; node != nullptr; node = node->next) {
                node->piece->updateMoves();
            }
            this->bitboardHandler->updatePresenceAndMovesArrays();
        }

        bool movePiece(Position from, Position to) {

            Index fromIndex = this->board->positionToIndex(from);
            Index toIndex = this->board->positionToIndex(to);

            Piece *piece = this->board->pieceArray[fromIndex.y][fromIndex.x];
            Piece *destinationPiece = this->board->pieceArray[toIndex.y][toIndex.x];

            if (from.rank != to.rank || from.file != to.file) {
                if (piece != nullptr) {
                    if (piece->color == this->color) {
                        if (piece->moveTo(to) == true) {
                            this->opponent->removePiece(destinationPiece);
                            if (this->isUnderCheck() == false) {
                                if (this->opponent->isUnderCheck() == true) {
                                    if (this->opponent->isUnderCheckmate() == true) {
                                        this->errorDelegate->error("Checkmate!");
                                    } else {
                                        this->errorDelegate->error("Check!");
                                    }
                                }
                                return true;
                            } else {
                                piece->undoMove();
                                this->addPiece(destinationPiece);
                                this->errorDelegate->error("King is under check");
                            }
                        } else {
                            this->errorDelegate->error("Invalid move");
                        }
                    } else {
                        this->errorDelegate->error("Wrong turn");
                    }
                } else {
                    this->errorDelegate->error("Piece does not exist");
                }
            } else {
                this->errorDelegate->error("Piece not moved");
            }
            return false;
        }

        bool moveKingSideRook() {
            Position position;
            position.rank = this->kingSideRook->position.rank;
            position.file = 'f';
            return this->movePiece(this->kingSideRook->position, position);
        }

        bool moveQueenSideRook() {
            Position position;
            position.rank = this->queenSideRook->position.rank;
            position.file = 'd';
            return this->movePiece(this->queenSideRook->position, position);
        }

        bool canCheckDuringPassing(Position position) {
            for(LinkedList::Node *node = this->opponent->piecesList->head; node != nullptr; node = node->next) {
                if (node->piece->canCheck(position) == true) {
                    return true;
                }
            }
            return false;
        }

        void removeEnPassants() {
            for(LinkedList::Node *node = this->opponent->piecesList->head; node != nullptr; node = node->next) {
                if (node->piece->pieceStrategy->isEnPassant == true) {
                    node->piece->pieceStrategy->isEnPassant = false;
                }
            }
        }
    };

Those were only the model classes. View, controller, delegates, constants and some basic structs aren't shown for the sake of conciseness.

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

There's a lot of code here, so I haven't gone through all of it. A few remarks on things that caught my eye though:

Repetition

I see a lot of repeated or very similar code in the Board class and board updating in updatePresenceAndMovesArrays(). Don't Repeat Yourself is one of the golden rules of programming.

In Board, we have this:

   bool whitePresenceArray[8][8];
   bool blackPresenceArray[8][8];

   bool whitePawnPresenceArray[8][8];
   bool whiteKnightPresenceArray[8][8];
   bool whiteBishopPresenceArray[8][8];
   bool whiteRookPresenceArray[8][8];
   bool whiteQueenPresenceArray[8][8];
   bool whiteKingPresenceArray[8][8];

   bool blackPawnPresenceArray[8][8];
   bool blackKnightPresenceArray[8][8];
   bool blackBishopPresenceArray[8][8];
   bool blackRookPresenceArray[8][8];
   bool blackQueenPresenceArray[8][8];
   bool blackKingPresenceArray[8][8];

And then following the same set of small matrices for the Moves. You should turn that into a helper structure:

struct PieceInBoard // Probably not a great name, just an example
{
    bool pawn[8][8];
    bool knight[8][8];
    bool bishop[8][8];
    bool rook[8][8];
    bool queen[8][8];
    bool king[8][8];
};

class Board
{
    PieceInBoard blackPresence;
    PieceInBoard blackMoves;

    PieceInBoard whitePresence;
    PieceInBoard whiteMoves;
};

Likewise, those massive memset blocks that zero fill the arrays can now be replaced by a single memset on the PieceInBoard instance, or even better be moved into a member method of PieceInBoard (such as a clear() method like it is common in the Standard Library).

Try to look into some of your loops as well. I can see several places that look like copy-paste only changing one or two things. Try to refactor these cases into individual helper functions.

Use C++ references

I see a lot of pointers in your code. Pointers are normally associated with three concepts:

  • The pointer can be null, usually to indicate an optional parameter.
  • The pointer is actually the head of a C-style array.
  • You are passing ownership of some memory to another object/function.

Apart from that, when you just want to pass a reference to a single object, which shouldn't be null, use a C++ reference. When neither of the points above fit your intent, a reference is much more clear and safer and almost certainly the best choice.

Still on pointers though...

Who manages the memory?

I can see a few calls to operator new in there, but no calls to delete. In C++, you must manually free memory that you allocate, or use automated memory management with smart pointers.

Using smart pointers would be the recommended in most cases, unless you have a very good reason to take matters in your own hands an risk running into memory leaks and other nasty memory corruption bugs that we easily run into when doing that sort of stuff.

Other minor issues

  • Please don't this-> qualify class members. We don't do that in C++. If you'd like to have a visual distinction between members and non-members, consider a prefix such as m_, m_likeThis, or a suffix _, likeThis_. But keep in mind that adding prefixes according to context can be a nuisance when you need to refactor some non-member to member or vice-versa. Potentially lots of places to update. Same issue with using this->.

  • C-style cast on class instance is very dangerous. See: "The dangers of C-style casts".

    ((AIPlayer *)this->currentPlayer)->generateMove();
    

    Use either static_cast if you know for sure that currentPlayer is in fact an AIPlayer instance. Otherwise, use dynamic_cast and check the return value for nullptr before dereferencing it.

  • Use auto when you have to repeat a type on both sides of an expression. It was invented to avoid things like this:

    LinkedList *movesList = new LinkedList();
    

    Now you can write the type on the right-hand side only:

    auto movesList = new LinkedList();
    
  • You use the literal characters 1, 8, a, g, etc in some places. I'd prefer to see an enum with more descriptive names instead.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the review. I'll try to implement the suggestions. One quick comment though, delete operations are performed in my LinkedList class which is not shown here. In my case, only the "pieces" need to be deleted. Everything else needs to exist in memory. \$\endgroup\$ Commented Apr 2, 2016 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.