diff --git a/game/Board.java b/game/Board.java index e39fd5f..56961f2 100644 --- a/game/Board.java +++ b/game/Board.java @@ -1,511 +1,318 @@ +package game; + import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class Board { - /** - * The Board - */ - public Pieces boardPieces [][]={ - {new Pieces(true,Piece.Rook),new Pieces(true,Piece.Knight),new Pieces(true,Piece.Bishop),new Pieces(true,Piece.Queen),new Pieces(true,Piece.King),new Pieces(true,Piece.Bishop),new Pieces(true,Piece.Knight),new Pieces(true,Piece.Rook)}, - {new Pieces(true,Piece.Pawn),new Pieces(true,Piece.Pawn),new Pieces(true,Piece.Pawn),new Pieces(true,Piece.Pawn),new Pieces(true,Piece.Pawn),new Pieces(true,Piece.Pawn),new Pieces(true,Piece.Pawn),new Pieces(true,Piece.Pawn)}, - {null,null,null,null,null,null,null,null}, - {null,null,null,null,null,null,null,null}, - {null,null,null,null,null,null,null,null}, - {null,null,null,null,null,null,null,null}, - {new Pieces(false,Piece.Pawn),new Pieces(false,Piece.Pawn),new Pieces(false,Piece.Pawn),new Pieces(false,Piece.Pawn),new Pieces(false,Piece.Pawn),new Pieces(false,Piece.Pawn),new Pieces(false,Piece.Pawn),new Pieces(false,Piece.Pawn)}, - {new Pieces(false,Piece.Rook),new Pieces(false,Piece.Knight),new Pieces(false,Piece.Bishop),new Pieces(false,Piece.Queen),new Pieces(false,Piece.King),new Pieces(false,Piece.Bishop),new Pieces(false,Piece.Knight),new Pieces(false,Piece.Rook)} - }; -//Server server = new Server(3333); - /** - * @return Copy of Board(boardPieces) - */ - public Pieces[][] getBoard(){ - return getBoardCopy(this.boardPieces); - } - - /** - * @param inputs board of Pieces - * @return returns copy of board of Pieces - */ - private Pieces[][] getBoardCopy(Pieces[][] board){ - Pieces tempBoard[][]=new Pieces[board.length][]; - for(int j = 0; j < board.length; j++) - tempBoard[j] = board[j].clone(); - return tempBoard; - } - - /** - * @param Piece pieceType - * @param isWhite the color of piece - * @return int[] location of piece searching for(usually just kings) - */ - public int[] findPiece(Piece pieceType, boolean isWhite, Pieces[][] board) { - for(int i =0; i<8;i++) { - for(int j=0;j<8;j++) { - if(board[i][j]!=null && board[i][j].isWhite()==isWhite && board[i][j].getPieceType()==pieceType) { - int[] temp = {i,j}; - return temp; - }//end of if - }//end of for - }//end of for - return null; - }//end of find piece method - - /** - * @param oldLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @param newLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - */ - public void movePiece(int[] oldLocation, int[] newLocation) { - //rook and king switch places - //server.initialize(); - //server.sendString("["+oldLocation[0]+","+oldLocation[1]+","+newLocation[0]+","+newLocation[1]+"]"); - if(this.getBoard()[oldLocation[0]][oldLocation[1]].getPieceType()==Piece.King&&newLocation[1]-oldLocation[1]==2) { - this.boardPieces[newLocation[0]][5]=this.boardPieces[oldLocation[0]][7]; - this.boardPieces[oldLocation[0]][7]=null; - }//end of if - this.boardPieces[newLocation[0]][newLocation[1]]=this.boardPieces[oldLocation[0]][oldLocation[1]]; - this.boardPieces[oldLocation[0]][oldLocation[1]]=null; - }//end of move piece method - - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @param newType, new type to replace pawn - */ - public void changePawn(int[] pieceLocation, Piece newType) { - if(this.boardPieces[pieceLocation[0]][pieceLocation[1]]==null) { return;}; - this.boardPieces[pieceLocation[0]][pieceLocation[1]].setPieceType(newType); - }//end of method changePawn - - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @return ArrayList of possible moves for Pawn, first digit is row, and second is column, ex. 2,3,6,7 is 2,3 and 6,7 and 2 and 6 are rows while 3 and 7 are columns - */ - private ArrayList Pawn(int[] pieceLocation, Pieces[][] board) { - ArrayList availablePositions = new ArrayList(); - int row= pieceLocation[0]; - int column=pieceLocation[1]; - boolean isWhite=board[row][column].isWhite(); - int array[][] = {{1,1,1,2}, - {0,-1,1,0}}; - int repeater =1; - int multiplier=1; - if(!isWhite) { - multiplier=-1; - }if(row==1||row==6) { - repeater=2; - }//end of if - - for(int i=0; i=0&&8>row+rowAddition; - boolean isColumnBetween0and8 = column+columnAddition>=0&&8>column+columnAddition; - if(isRowBetwwen0and8&isColumnBetween0and8) { - if(board[row+rowAddition][column+columnAddition]==null) { - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - }else { - break; - }//End of else - }//end of if - }//End of for - for(int i=1; i<3; i++) { - int rowAddition=array[0][i]*multiplier; - int columnAddition=array[1][i]*multiplier; - boolean isRowBetwwen0and8 = row+rowAddition>=0&&8>row+rowAddition; - boolean isColumnBetween0and8 = column+columnAddition>=0&&8>column+columnAddition; - if(isRowBetwwen0and8&isColumnBetween0and8) { - if(board[row+rowAddition][column+columnAddition]==null) { - }else if(board[row+rowAddition][column+columnAddition].isWhite()!=isWhite){ - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - }//end of if - }//end of if - }//end of for - - return availablePositions; - }//end of Pawns checking system - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @return ArrayList of possible moves for Rook, first digit is row, and second is column, ex. 2,3,6,7 is 2,3 and 6,7 and 2 and 6 are rows while 3 and 7 are columns - */ - private ArrayList Rook(int[] pieceLocation, Pieces[][] board) { - ArrayList availablePositions = new ArrayList(); - int row= pieceLocation[0]; - int column=pieceLocation[1]; - boolean isWhite=board[row][column].isWhite(); - int array[][] = {{0,0,1,-1}, - {1,-1,0,0}}; - for(int i=0; i<4; i++) { - for(int j=1;j<8;j++) { - - int rowAddition=array[0][i]*j; - int columnAddition=array[1][i]*j; - boolean isRowBetwwen0and8 = row+rowAddition>=0&&8>row+rowAddition; - boolean isColumnBetween0and8 = column+columnAddition>=0&&8>column+columnAddition; - - if(isRowBetwwen0and8&isColumnBetween0and8) { - if(board[row+rowAddition][column+columnAddition]==null) { - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - }else if(board[row+rowAddition][column+columnAddition].isWhite()!=isWhite){ - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - break; - }else { - break; - }//end of else - }//end of if - }//end of for - }//End of for - return availablePositions; - } - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @return ArrayList of possible moves for Knight, first digit is row, and second is column, ex. 2,3,6,7 is 2,3 and 6,7 and 2 and 6 are rows while 3 and 7 are columns - */ - private ArrayList Knight(int[] pieceLocation, Pieces[][] board) { - ArrayList availablePositions = new ArrayList(); - int row= pieceLocation[0]; - int column=pieceLocation[1]; - boolean isWhite=board[row][column].isWhite(); - int array[][] = {{2,2,-2,-2,1,-1,1,-1}, - {1,-1,1,-1,2,2,-2,-2}}; - for(int i=0; i<8; i++) { - int rowAddition=array[0][i]; - int columnAddition=array[1][i]; - boolean isRowBetwwen0and8 = row+rowAddition>=0&&8>row+rowAddition; - boolean isColumnBetween0and8 = column+columnAddition>=0&&8>column+columnAddition; - - if(isRowBetwwen0and8&isColumnBetween0and8) { - if(board[row+rowAddition][column+columnAddition]==null||board[row+rowAddition][column+columnAddition].isWhite()!=isWhite) { - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - }//end of if - }//end of if - }//end of for - return availablePositions; - }//end of knight - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @return ArrayList of possible moves for Bishop, first digit is row, and second is column, ex. 2,3,6,7 is 2,3 and 6,7 and 2 and 6 are rows while 3 and 7 are columns - */ - private ArrayList Bishop(int[] pieceLocation, Pieces[][] board) { - ArrayList availablePositions = new ArrayList(); - int row= pieceLocation[0]; - int column=pieceLocation[1]; - boolean isWhite=board[row][column].isWhite(); - int array[][] = {{1,1,-1,-1}, - {1,-1,1,-1}}; - - for(int i=0; i<4; i++) { - for(int j=1;j<8;j++) { - - int rowAddition=array[0][i]*j; - int columnAddition=array[1][i]*j; - boolean isRowBetwwen0and8 = row+rowAddition>=0&&8>row+rowAddition; - boolean isColumnBetween0and8 = column+columnAddition>=0&&8>column+columnAddition; - - if(isRowBetwwen0and8&isColumnBetween0and8) { - if(board[row+rowAddition][column+columnAddition]==null) { - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - }else if(board[row+rowAddition][column+columnAddition].isWhite()!=isWhite){ - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - break; - }else { - break; - }//end of else - }//end of if - }//end of for - }//End of for - return availablePositions; - }//end of BIshop - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @return ArrayList of possible moves for Queen, first digit is row, and second is column, ex. 2,3,6,7 is 2,3 and 6,7 and 2 and 6 are rows while 3 and 7 are columns - */ - private ArrayList Queen(int[] pieceLocation, Pieces[][] board) { - ArrayList availablePositions = new ArrayList(); - availablePositions.addAll(this.Rook(pieceLocation, board)); - availablePositions.addAll(this.Bishop(pieceLocation,board)); - return availablePositions; - }//end of Queen - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @return ArrayList of possible moves for King, first digit is row, and second is column, ex. 2,3,6,7 is 2,3 and 6,7 and 2 and 6 are rows while 3 and 7 are columns - */ - private ArrayList King(int[] pieceLocation, Pieces[][] board) { - ArrayList availablePositions = new ArrayList(); - int row= pieceLocation[0]; - int column=pieceLocation[1]; - boolean isWhite=board[row][column].isWhite(); - int array[][] = {{1,1,-1,-1,0,0,1,-1}, - {1,-1,1,-1,1,-1,0,0}}; - int rowforrook=0; - //rook and king switch places - if(!isWhite) { - rowforrook=7; - }if((column==4&&row==rowforrook)&&(board[rowforrook][5]==null&&board[rowforrook][6]==null)&&board[rowforrook][7].getPieceType()==Piece.Rook&&board[rowforrook][7].isWhite()==isWhite) { - availablePositions.add(rowforrook); - availablePositions.add(6); - } - - for(int i=0;i<8;i++) { - int rowAddition=array[0][i]; - int columnAddition=array[1][i]; - boolean isRowBetwwen0and8 = row+rowAddition>=0&&8>row+rowAddition; - boolean isColumnBetween0and8 = column+columnAddition>=0&&8>column+columnAddition; - - if(isRowBetwwen0and8&isColumnBetween0and8) { - if(board[row+rowAddition][column+columnAddition]==null) { - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - }else if(board[row+rowAddition][column+columnAddition].isWhite()!=isWhite){ - availablePositions.add(row+rowAddition); - availablePositions.add(column+columnAddition); - }//end of if - }//end of if - }//End of for - return availablePositions; - }//end of King - - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @param board, The board where the pieces are located, a 2 dimensional array of Pieces - * @return ArrayList of possible moves for chosen piece but does not check for king in check, first digit is row, and second is column, ex. 2,3,6,7 is 2,3 and 6,7 and 2 and 6 are rows while 3 and 7 are columns - */ - private ArrayList possibleLegalMoves(int[] pieceLocation, Pieces[][] board) { - int row= pieceLocation[0]; - int column=pieceLocation[1]; - Piece temporaryPiece = board[row][column].getPieceType(); - switch(temporaryPiece) { - case King: - return this.King(pieceLocation,board); - case Queen: - return this.Queen(pieceLocation,board); - case Bishop: - return this.Bishop(pieceLocation,board); - case Knight: - return this.Knight(pieceLocation,board); - case Rook: - return this.Rook(pieceLocation,board); - case Pawn: - return this.Pawn(pieceLocation,board); - default: - return null; - }//end of switch - }//End of getLegalMoves - - /** - * @param isWhite the color of piece - * @param board, The board where the pieces are located, a 2 dimensional array of Pieces - * @return true if king is in check - */ - private boolean isKingInCheck(boolean isWhite, Pieces[][] board) { - int[] array = this.findPiece(Piece.King, isWhite,board); - for(int row =0; row<8;row++) { - for(int column=0;column<8;column++) { - if(board[row][column]!=null && board[row][column].isWhite()!=isWhite) { - int[] temporaryLocation = {row,column}; - ArrayList possibleMoves = this.possibleLegalMoves(temporaryLocation,board); - if(canPieceBeTakenHelper(array,possibleMoves)) { - return true; - }//end of if - }//end of if - }//end of for - }//End of for - return false; - }//end of king in check method - - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @param board, The board where the pieces are located, a 2 dimensional array of Pieces - * @return ArrayList of possible moves for chosen piece, first digit is row, and second is column, ex. 2,3,6,7 is 2,3 and 6,7 and 2 and 6 are rows while 3 and 7 are columns - */ - private ArrayListgetLegalMoves(int[] pieceLocation, Pieces[][] board) { - ArrayList returnArrayList = new ArrayList(); - ArrayList piecePossibleMoves =this.possibleLegalMoves(pieceLocation, board); - if(piecePossibleMoves!=null) { - for(int i=0; ipieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0], etc. - * @param attackingPiecePossibleMoves, Arraylist of possible moves from opponent - * @return true or false - */ - private boolean canPieceBeTakenHelper(int[] pieceLocation, ArrayList attackingPiecePossibleMoves){ - if(attackingPiecePossibleMoves!=null&&attackingPiecePossibleMoves.size()>0) { - for(int i=0;ipieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @param board, The board where the pieces are located, a 2 dimensional array of Pieces - * @return true or false depending on whether piece can be taken at position it is in. - */ - private boolean canPieceBeTaken(int[] pieceLocation, Pieces[][] board) { - boolean isWhite = board[pieceLocation[0]][pieceLocation[1]].isWhite(); - for(int row=0; row<8;row++) { - for(int column=0;column<8;column++) { - if(board[row][column]!=null && board[row][column].isWhite()!=isWhite) { - int[] temporaryLocation = {row,column}; - ArrayList temp =this.possibleLegalMoves(temporaryLocation,board); - if(canPieceBeTakenHelper(pieceLocation,temp)) { - return true; - }//end of if - }//end of if - }//end of for - }//end of for - return false; - }//end of can piece be taken at position method - - /** - * @param inputArrayList, ArrayList to remove duplicate locations from - * @return ArrayList without the duplicate locations in it. - */ - private ArrayList duplicateLocationRemoverforArrayList(ArrayList inputArrayList){ - ArrayList returnArrayList = new ArrayList(); - if(inputArrayList!=null&&inputArrayList.size()>0) { - for(int i=0;ipieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @param board, The board where the pieces are located, a 2 dimensional array of Pieces - * @return ArrayList of Locations where piece can be taken in one move - */ - private ArrayList pieceTakenLocations(int[] pieceLocation, Pieces[][] board) { - ArrayList returnArrayList = new ArrayList(); - ArrayList possiblePieceMoves=this.getRealLegalMoves(pieceLocation); - //repeats move for each possible move - for(int i=0;ipieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @return Arraylist of moves that can be taken by piece. - */ - public ArrayList getTakenMoves(int[] pieceLocation){ - return this.pieceTakenLocations(pieceLocation, this.getBoard()); - }//end of get taken moves method - - /** - * @param pieceLocation , Location of piece in question in array form so a1==[0,0], and a8=[7,0] - * @return Legal moves, which includes if a king is in check, so you have to protect them - */ - public ArrayList getRealLegalMoves(int[] pieceLocation) { - return this.getLegalMoves(pieceLocation, this.boardPieces); - }//end of real legal moves method - - /** - * @param isWhite the color of piece - * @return boolean true if is in checkMate - */ - public boolean isInCheckMate(boolean isWhite) { - //run get real legal moves for every piece of chosen color. - ArrayList temp = new ArrayList(); - for(int i =0; i<8;i++) { - for(int j=0;j<8;j++) { - if(this.boardPieces[i][j]!=null && this.boardPieces[i][j].isWhite()==isWhite) { - int[] location = {i,j}; - temp.addAll(this.getRealLegalMoves(location)); - }//end of if - }//end of for - }//end of for - if(temp.size()>0) { - //if your color can move then king is not in check mate - return false; - }//end of if - return true; - }//end of check mate method - - /** - * @param board, The board where the pieces are located, a 2 dimensional array of Pieces - * Prints board onto console - */ - public void commandLinePrinter(Pieces[][] board) { - String [] letters = {"A","B","C","D","E","F","G","H"}; - for(int i =0; i<8;i++) { - for(int j=0;j<8;j++) { - System.out.print((i+1)); - System.out.print(letters[j]); - if(board[i][j]!=null) { - System.out.print(" "+board[i][j].getPieceType().toString()+" |"); - }else { - System.out.print(" Empty |"); - }//end of else - }//end of for - System.out.print("\n"); - }//End of for - }//end of printer - - - - -}//End of class \ No newline at end of file + private static final int BOARD_SIZE = 8; + + public GamePiece[][] boardPieces = { + {new GamePiece(true, PieceType.Rook), new GamePiece(true, PieceType.Knight), new GamePiece(true, PieceType.Bishop), new GamePiece(true, PieceType.Queen), new GamePiece(true, PieceType.King), new GamePiece(true, PieceType.Bishop), new GamePiece(true, PieceType.Knight), new GamePiece(true, PieceType.Rook)}, + {new GamePiece(true, PieceType.Pawn), new GamePiece(true, PieceType.Pawn), new GamePiece(true, PieceType.Pawn), new GamePiece(true, PieceType.Pawn), new GamePiece(true, PieceType.Pawn), new GamePiece(true, PieceType.Pawn), new GamePiece(true, PieceType.Pawn), new GamePiece(true, PieceType.Pawn)}, + {null, null, null, null, null, null, null, null}, + {null, null, null, null, null, null, null, null}, + {null, null, null, null, null, null, null, null}, + {null, null, null, null, null, null, null, null}, + {new GamePiece(false, PieceType.Pawn), new GamePiece(false, PieceType.Pawn), new GamePiece(false, PieceType.Pawn), new GamePiece(false, PieceType.Pawn), new GamePiece(false, PieceType.Pawn), new GamePiece(false, PieceType.Pawn), new GamePiece(false, PieceType.Pawn), new GamePiece(false, PieceType.Pawn)}, + {new GamePiece(false, PieceType.Rook), new GamePiece(false, PieceType.Knight), new GamePiece(false, PieceType.Bishop), new GamePiece(false, PieceType.Queen), new GamePiece(false, PieceType.King), new GamePiece(false, PieceType.Bishop), new GamePiece(false, PieceType.Knight), new GamePiece(false, PieceType.Rook)} + }; + + public GamePiece[][] getBoard() { + return getBoardCopy(this.boardPieces); + } + + private GamePiece[][] getBoardCopy(GamePiece[][] board) { + GamePiece[][] tempBoard = new GamePiece[board.length][]; + for (int j = 0; j < board.length; j++) { + tempBoard[j] = board[j].clone(); + } + return tempBoard; + } + + public Position findPiece(PieceType pieceType, boolean isWhite, GamePiece[][] board) { + for (int i = 0; i < BOARD_SIZE; i++) { + for (int j = 0; j < BOARD_SIZE; j++) { + if (board[i][j] != null && board[i][j].isWhite() == isWhite && board[i][j].getPieceType() == pieceType) { + return new Position(i, j); + } + } + } + return null; + } + + public void movePiece(Position oldLocation, Position newLocation) { + if (this.getBoard()[oldLocation.getRow()][oldLocation.getColumn()].getPieceType() == PieceType.King && newLocation.getColumn() - oldLocation.getColumn() == 2) { + this.boardPieces[newLocation.getRow()][5] = this.boardPieces[oldLocation.getRow()][7]; + this.boardPieces[oldLocation.getRow()][7] = null; + } + this.boardPieces[newLocation.getRow()][newLocation.getColumn()] = this.boardPieces[oldLocation.getRow()][oldLocation.getColumn()]; + this.boardPieces[oldLocation.getRow()][oldLocation.getColumn()] = null; + } + + public void promotePawn(Position pieceLocation, PieceType newType) { + if (this.boardPieces[pieceLocation.getRow()][pieceLocation.getColumn()] == null) { + return; + } + this.boardPieces[pieceLocation.getRow()][pieceLocation.getColumn()].setPieceType(newType); + } + + private List getPawnMoves(Position pieceLocation, GamePiece[][] board) { + List availablePositions = new ArrayList<>(); + int row = pieceLocation.getRow(); + int column = pieceLocation.getColumn(); + boolean isWhite = board[row][column].isWhite(); + int direction = isWhite ? 1 : -1; + int startRow = isWhite ? 1 : 6; + + // Forward moves + Position oneStep = new Position(row + direction, column); + if (isValid(oneStep) && board[oneStep.getRow()][oneStep.getColumn()] == null) { + availablePositions.add(oneStep); + if (row == startRow) { + Position twoSteps = new Position(row + 2 * direction, column); + if (isValid(twoSteps) && board[twoSteps.getRow()][twoSteps.getColumn()] == null) { + availablePositions.add(twoSteps); + } + } + } + + // Capture moves + int[] captureCols = {column - 1, column + 1}; + for (int captureCol : captureCols) { + Position captureMove = new Position(row + direction, captureCol); + if (isValid(captureMove) && board[captureMove.getRow()][captureMove.getColumn()] != null && board[captureMove.getRow()][captureMove.getColumn()].isWhite() != isWhite) { + availablePositions.add(captureMove); + } + } + + return availablePositions; + } + + private List getRookMoves(Position pieceLocation, GamePiece[][] board) { + List availablePositions = new ArrayList<>(); + int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; + addSlidingPieceMoves(pieceLocation, board, availablePositions, directions); + return availablePositions; + } + + private List getKnightMoves(Position pieceLocation, GamePiece[][] board) { + List availablePositions = new ArrayList<>(); + int row = pieceLocation.getRow(); + int column = pieceLocation.getColumn(); + boolean isWhite = board[row][column].isWhite(); + int[][] moves = {{2, 1}, {2, -1}, {-2, 1}, {-2, -1}, {1, 2}, {1, -2}, {-1, 2}, {-1, -2}}; + + for (int[] move : moves) { + Position newPos = new Position(row + move[0], column + move[1]); + if (isValid(newPos)) { + if (board[newPos.getRow()][newPos.getColumn()] == null || board[newPos.getRow()][newPos.getColumn()].isWhite() != isWhite) { + availablePositions.add(newPos); + } + } + } + return availablePositions; + } + + private List getBishopMoves(Position pieceLocation, GamePiece[][] board) { + List availablePositions = new ArrayList<>(); + int[][] directions = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; + addSlidingPieceMoves(pieceLocation, board, availablePositions, directions); + return availablePositions; + } + + private List getQueenMoves(Position pieceLocation, GamePiece[][] board) { + List availablePositions = new ArrayList<>(); + availablePositions.addAll(this.getRookMoves(pieceLocation, board)); + availablePositions.addAll(this.getBishopMoves(pieceLocation, board)); + return availablePositions; + } + + private List getKingMoves(Position pieceLocation, GamePiece[][] board) { + List availablePositions = new ArrayList<>(); + int row = pieceLocation.getRow(); + int column = pieceLocation.getColumn(); + boolean isWhite = board[row][column].isWhite(); + int[][] moves = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}, {0, 1}, {0, -1}, {1, 0}, {-1, 0}}; + + for (int[] move : moves) { + Position newPos = new Position(row + move[0], column + move[1]); + if (isValid(newPos)) { + if (board[newPos.getRow()][newPos.getColumn()] == null || board[newPos.getRow()][newPos.getColumn()].isWhite() != isWhite) { + availablePositions.add(newPos); + } + } + } + + // Castling + int castleRow = isWhite ? 0 : 7; + if (row == castleRow && column == 4) { + // Kingside + if (board[castleRow][5] == null && board[castleRow][6] == null && board[castleRow][7] != null && board[castleRow][7].getPieceType() == PieceType.Rook) { + availablePositions.add(new Position(castleRow, 6)); + } + } + + return availablePositions; + } + + private List getPossibleMoves(Position pieceLocation, GamePiece[][] board) { + PieceType temporaryPiece = board[pieceLocation.getRow()][pieceLocation.getColumn()].getPieceType(); + switch (temporaryPiece) { + case King: + return this.getKingMoves(pieceLocation, board); + case Queen: + return this.getQueenMoves(pieceLocation, board); + case Bishop: + return this.getBishopMoves(pieceLocation, board); + case Knight: + return this.getKnightMoves(pieceLocation, board); + case Rook: + return this.getRookMoves(pieceLocation, board); + case Pawn: + return this.getPawnMoves(pieceLocation, board); + default: + return new ArrayList<>(); + } + } + + private boolean isKingInCheck(boolean isWhite, GamePiece[][] board) { + Position kingPosition = this.findPiece(PieceType.King, isWhite, board); + if (kingPosition == null) { + return false; + } + for (int row = 0; row < BOARD_SIZE; row++) { + for (int column = 0; column < BOARD_SIZE; column++) { + if (board[row][column] != null && board[row][column].isWhite() != isWhite) { + Position temporaryLocation = new Position(row, column); + List possibleMoves = this.getPossibleMoves(temporaryLocation, board); + if (possibleMoves.contains(kingPosition)) { + return true; + } + } + } + } + return false; + } + + private List getFilteredLegalMoves(Position pieceLocation, GamePiece[][] board) { + List returnArrayList = new ArrayList<>(); + List piecePossibleMoves = this.getPossibleMoves(pieceLocation, board); + if (piecePossibleMoves != null) { + for (Position move : piecePossibleMoves) { + GamePiece[][] temporaryBoard = this.getBoardCopy(board); + GamePiece temporaryPiece = temporaryBoard[pieceLocation.getRow()][pieceLocation.getColumn()]; + temporaryBoard[pieceLocation.getRow()][pieceLocation.getColumn()] = null; + temporaryBoard[move.getRow()][move.getColumn()] = temporaryPiece; + if (!this.isKingInCheck(temporaryPiece.isWhite(), temporaryBoard)) { + returnArrayList.add(move); + } + } + return returnArrayList; + } + return new ArrayList<>(); + } + + private boolean isPositionUnderAttack(Position pieceLocation, GamePiece[][] board) { + boolean isWhite = board[pieceLocation.getRow()][pieceLocation.getColumn()].isWhite(); + for (int row = 0; row < BOARD_SIZE; row++) { + for (int column = 0; column < BOARD_SIZE; column++) { + if (board[row][column] != null && board[row][column].isWhite() != isWhite) { + Position temporaryLocation = new Position(row, column); + List temp = this.getPossibleMoves(temporaryLocation, board); + if (temp.contains(pieceLocation)) { + return true; + } + } + } + } + return false; + } + + private Set getThreatenedMoves(Position pieceLocation, GamePiece[][] board) { + Set returnArrayList = new HashSet<>(); + List possiblePieceMoves = this.getLegalMoves(pieceLocation); + for (Position move : possiblePieceMoves) { + GamePiece[][] temporaryBoard = this.getBoardCopy(board); + GamePiece temporaryPiece = temporaryBoard[pieceLocation.getRow()][pieceLocation.getColumn()]; + temporaryBoard[pieceLocation.getRow()][pieceLocation.getColumn()] = null; + temporaryBoard[move.getRow()][move.getColumn()] = temporaryPiece; + if (this.isPositionUnderAttack(move, temporaryBoard)) { + returnArrayList.add(move); + } + } + return returnArrayList; + } + + + public List getThreatenedMoves(Position pieceLocation) { + return new ArrayList<>(this.getThreatenedMoves(pieceLocation, this.getBoard())); + } + + public List getLegalMoves(Position pieceLocation) { + return this.getFilteredLegalMoves(pieceLocation, this.boardPieces); + } + + public boolean isCheckmate(boolean isWhite) { + if (!isKingInCheck(isWhite, boardPieces)) { + return false; + } + List allMoves = new ArrayList<>(); + for (int i = 0; i < BOARD_SIZE; i++) { + for (int j = 0; j < BOARD_SIZE; j++) { + if (this.boardPieces[i][j] != null && this.boardPieces[i][j].isWhite() == isWhite) { + allMoves.addAll(this.getLegalMoves(new Position(i, j))); + } + } + } + return allMoves.isEmpty(); + } + + public void printBoard(GamePiece[][] board) { + String[] letters = {"A", "B", "C", "D", "E", "F", "G", "H"}; + for (int i = 0; i < BOARD_SIZE; i++) { + for (int j = 0; j < BOARD_SIZE; j++) { + System.out.print((i + 1)); + System.out.print(letters[j]); + if (board[i][j] != null) { + System.out.print(" " + board[i][j].getPieceType().toString() + " |"); + } else { + System.out.print(" Empty |"); + } + } + System.out.print("\n"); + } + } + + private boolean isValid(Position pos) { + return pos.getRow() >= 0 && pos.getRow() < BOARD_SIZE && pos.getColumn() >= 0 && pos.getColumn() < BOARD_SIZE; + } + + private void addSlidingPieceMoves(Position pieceLocation, GamePiece[][] board, List availablePositions, int[][] directions) { + int row = pieceLocation.getRow(); + int column = pieceLocation.getColumn(); + boolean isWhite = board[row][column].isWhite(); + + for (int[] dir : directions) { + for (int i = 1; i < BOARD_SIZE; i++) { + Position newPos = new Position(row + dir[0] * i, column + dir[1] * i); + if (isValid(newPos)) { + if (board[newPos.getRow()][newPos.getColumn()] == null) { + availablePositions.add(newPos); + } else if (board[newPos.getRow()][newPos.getColumn()].isWhite() != isWhite) { + availablePositions.add(newPos); + break; + } else { + break; + } + } else { + break; + } + } + } + } +} \ No newline at end of file diff --git a/game/BoardGUI.java b/game/BoardGUI.java index dcd7bfc..ccad91b 100644 --- a/game/BoardGUI.java +++ b/game/BoardGUI.java @@ -1,245 +1,186 @@ -import java.awt.EventQueue; -import java.awt.Font; +package game; -import javax.swing.JFrame; -import javax.swing.JPanel; import java.awt.BorderLayout; -import javax.swing.UIManager; - -import java.awt.GridLayout; -import javax.swing.JButton; -import javax.swing.JOptionPane; import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.ArrayList; +import java.util.List; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.UIManager; public class BoardGUI { - private JFrame chessGameFrame; - private Color oppositeColorofWhite = new Color(211,211,211); - private Color legalMoveColor = new Color(137, 207, 240); - private Color takenMoveColor = new Color(234, 60, 83); - private Font defaultFont=new Font(null, Font.PLAIN, 70); - private JButton Square[][]; - private int[] movePiecelocation; - private boolean isWhiteTurn=true; - private Board board=new Board(); - private String [] letters = {"A","B","C","D","E","F","G","H"}; - String[] pawnPromotionOptions = {"Queen", "Knight", "Rook", "Bishop"}; - //Server server = new Server(3333); - /** - * Launch the application. - */ - public static void main(String[] args) { - EventQueue.invokeLater(new Runnable() { - public void run() { - try { - BoardGUI window = new BoardGUI(); - window.chessGameFrame.setVisible(true); - } catch (Exception e) { - e.printStackTrace(); - }//end of catch - }//end of method run - }); - }//end of maiun mehtod + private JFrame chessGameFrame; + private final Color oppositeColorofWhite = new Color(211, 211, 211); + private final Color legalMoveColor = new Color(137, 207, 240); + private final Color takenMoveColor = new Color(234, 60, 83); + private final Font defaultFont = new Font(null, Font.PLAIN, 70); + private JButton[][] square; + private Position selectedPiecePosition; + private final Game game = new Game(); + private final String[] letters = {"A", "B", "C", "D", "E", "F", "G", "H"}; + String[] pawnPromotionOptions = {"Queen", "Knight", "Rook", "Bishop"}; + + public static void main(String[] args) { + EventQueue.invokeLater(() -> { + try { + BoardGUI window = new BoardGUI(); + window.chessGameFrame.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + public BoardGUI() { + initialize(); + } - public BoardGUI() { - initialize(); - }//end of boardgui + private void initialize() { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + e.printStackTrace(); + } + chessGameFrame = new JFrame(); + chessGameFrame.setResizable(false); + chessGameFrame.setTitle("Chess Game-V 1.3.2"); + chessGameFrame.setBounds(100, 100, 900, 900); + chessGameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel panel_1 = new JPanel(); + chessGameFrame.getContentPane().add(panel_1, BorderLayout.CENTER); + panel_1.setLayout(new GridLayout(0, 8, 0, 0)); - /** - * Initialize the contents of the frame. - */ - private void initialize() { - //server.initialize(); - try { - UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");} catch (Exception e) {} - chessGameFrame = new JFrame(); - chessGameFrame.setResizable(false); - chessGameFrame.setTitle("Chess Game-V 1.3.2"); - chessGameFrame.setBounds(100, 100, 900, 900); - chessGameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - JPanel panel_1 = new JPanel(); - chessGameFrame.getContentPane().add(panel_1, BorderLayout.CENTER); - panel_1.setLayout(new GridLayout(0, 8, 0, 0)); + square = new JButton[8][8]; + for (int i = 7; i >= 0; i--) { + for (int j = 0; j < 8; j++) { + square[i][j] = new JButton(letters[j] + (i + 1)); + if (i % 2 != 0 && j % 2 == 0 || i % 2 == 0 && j % 2 != 0) { + square[i][j].setBackground(Color.WHITE); + } + if (i % 2 != 0 && j % 2 != 0 || i % 2 == 0 && j % 2 == 0) { + square[i][j].setBackground(oppositeColorofWhite); + } + final int finalI = i; + final int finalJ = j; + square[i][j].addActionListener(e -> handleSquareClick(new Position(finalI, finalJ))); + panel_1.add(square[i][j]); + } + } + updateBoard(); + } - Square= new JButton[8][8]; - for(int i =7; i>=0;i--) { - for(int j=0;j<8;j++) { - Square[i][j] = new JButton(letters[j]+(i+1)); - if(i%2!=0&&j%2==0||i%2==0&&j%2!=0) { - Square[i][j].setBackground(Color.WHITE); - }if(i%2!=0&&j%2!=0||i%2==0&&j%2==0) { - Square[i][j].setBackground(oppositeColorofWhite); - }// end of if - Square[i][j].addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - determinePiecemovement( getbuttonLocation( (JButton) e.getSource() ) ); - }}); - panel_1.add(Square[i][j]); - }//end of for - }//end of for - painter(); - }//end of method initialize + private void handleSquareClick(Position position) { + if (selectedPiecePosition == null) { + GamePiece piece = game.getBoard().boardPieces[position.getRow()][position.getColumn()]; + if (piece != null && piece.isWhite() == game.isWhiteTurn()) { + selectedPiecePosition = position; + highlightLegalMoves(position); + } + } else { + List legalMoves = game.getBoard().getLegalMoves(selectedPiecePosition); + if (legalMoves.contains(position)) { + game.move(selectedPiecePosition, position); + if (game.getBoard().boardPieces[position.getRow()][position.getColumn()].getPieceType() == PieceType.Pawn && (position.getRow() == 0 || position.getRow() == 7)) { + promotePawn(position); + } + selectedPiecePosition = null; + updateBoard(); + if (game.isCheckmate()) { + String winner = game.isWhiteTurn() ? "Black" : "White"; + JOptionPane.showMessageDialog(null, "Checkmate! " + winner + " wins."); + } + } else { + selectedPiecePosition = null; + updateBoard(); + } + } + } - public boolean determinePiecemovement(int[] pieceLocation) { - if((Square[pieceLocation[0]][pieceLocation[1]].getBackground()==legalMoveColor||Square[pieceLocation[0]][pieceLocation[1]].getBackground()==takenMoveColor)&&movePiecelocation!=null ) { - board.movePiece(movePiecelocation, pieceLocation); - - //Adding Networking capabilities - //server.sendString(movePiecelocation.toString()+pieceLocation.toString()); - - isWhiteTurn=!isWhiteTurn; - movePiecelocation=null; - painter(); - - if(board.boardPieces[pieceLocation[0]][pieceLocation[1]].getPieceType()==Piece.Pawn&&(pieceLocation[0]==0||pieceLocation[0]==7)) { - boolean changePawnBoolean=false; - do{ - changePawnBoolean=changePawnType(pieceLocation); - }while(!changePawnBoolean); - painter(); - }//end of if - return true; - }else if(!board.isInCheckMate(isWhiteTurn)){ - painter(); - if(board.boardPieces[pieceLocation[0]][pieceLocation[1]]!=null&&board.boardPieces[pieceLocation[0]][pieceLocation[1]].isWhite()==isWhiteTurn) { - //edit above line for network - //if(board.boardPieces[pieceLocation[0]][pieceLocation[1]].isWhite()==true) { - possiblemovespainter(board.getRealLegalMoves(pieceLocation), legalMoveColor); - possiblemovespainter(board.getTakenMoves(pieceLocation), takenMoveColor); - movePiecelocation= pieceLocation.clone(); - return true; - //} - }//end of if - }else if(board.isInCheckMate(isWhiteTurn)) { - String text="Black"; - if(isWhiteTurn) { - text="White"; - }//end of if - JOptionPane.showMessageDialog( null, text+ " is in checkmate. \nPlease Close The Chess Game Window!" ); - return true; - }// end of else if - return false; - }//end of determine piece movement method + private void highlightLegalMoves(Position position) { + List legalMoves = game.getBoard().getLegalMoves(position); + List threatenedMoves = game.getBoard().getThreatenedMoves(position); + for (Position move : legalMoves) { + square[move.getRow()][move.getColumn()].setBackground(legalMoveColor); + } + for (Position move : threatenedMoves) { + square[move.getRow()][move.getColumn()].setBackground(takenMoveColor); + } + } - public void possiblemovespainter(ArrayList locations, Color color) { - if(locations.size()>0) { - for(int i=0; i=0;i--) { - for(int j=0;j<8;j++) { - if(i%2!=0&&j%2==0||i%2==0&&j%2!=0) { - Square[i][j].setBackground(Color.WHITE); - }if(i%2!=0&&j%2!=0||i%2==0&&j%2==0) { - Square[i][j].setBackground(oppositeColorofWhite); - }// end of if - Square[i][j].setFont(defaultFont); - if(board.boardPieces[i][j]==null) { - Square[i][j].setText(""); - }else { - String text=null; - if(board.boardPieces[i][j].isWhite()) { - switch(board.boardPieces[i][j].getPieceType()) { - case King: - text="\u2654"; - break; - case Queen: - text="\u2655"; - break; - case Rook: - text="\u2656"; - break; - case Bishop: - text="\u2657"; - break; - case Knight: - text="\u2658"; - break; - case Pawn: - text="\u2659"; - break; - default: - text=""; - }//end of switch - }else if(!board.boardPieces[i][j].isWhite()) { - - switch(board.boardPieces[i][j].getPieceType()) { - case King: - text="\u265A"; - break; - case Queen: - text="\u265B"; - break; - case Rook: - text="\u265C"; - break; - case Bishop: - text="\u265D"; - break; - case Knight: - text="\u265E"; - break; - case Pawn: - text="\u265F"; - break; - default: - text=""; - }//edn of switch - }//edn of else if - Square[i][j].setText(text); - }//edn of else - }//end of for - }//end of for - }//end of method + private void updateBoard() { + for (int i = 7; i >= 0; i--) { + for (int j = 0; j < 8; j++) { + if (i % 2 != 0 && j % 2 == 0 || i % 2 == 0 && j % 2 != 0) { + square[i][j].setBackground(Color.WHITE); + } + if (i % 2 != 0 && j % 2 != 0 || i % 2 == 0 && j % 2 == 0) { + square[i][j].setBackground(oppositeColorofWhite); + } + square[i][j].setFont(defaultFont); + GamePiece piece = game.getBoard().boardPieces[i][j]; + if (piece == null) { + square[i][j].setText(""); + } else { + square[i][j].setText(getPieceUnicode(piece)); + } + } + } + } - public int[] getbuttonLocation(JButton temp) { - int [] location; - for(int i =0; i<8;i++) { - for(int j=0;j<8;j++) { - if(Square[i][j]==temp) { - location= new int[2]; - location[0]=i; - location[1]=j; - return location; - }//End of if - }//end of for - }//end of for - return null; - }//end of class + private String getPieceUnicode(GamePiece piece) { + switch (piece.getPieceType()) { + case King: + return piece.isWhite() ? "\u2654" : "\u265A"; + case Queen: + return piece.isWhite() ? "\u2655" : "\u265B"; + case Rook: + return piece.isWhite() ? "\u2656" : "\u265C"; + case Bishop: + return piece.isWhite() ? "\u2657" : "\u265D"; + case Knight: + return piece.isWhite() ? "\u2658" : "\u265E"; + case Pawn: + return piece.isWhite() ? "\u2659" : "\u265F"; + default: + return ""; + } + } - public boolean changePawnType(int[] piecelocation) { - int selection = JOptionPane.showOptionDialog(null, - "Upgrade Your Pawn! Limited time only.", - "Choose a Promotion", - JOptionPane.DEFAULT_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, - pawnPromotionOptions, - pawnPromotionOptions[0]); - switch (selection){ - case 0: - board.changePawn(piecelocation, Piece.Queen); - return true; - case 1: - board.changePawn(piecelocation, Piece.Knight); - return true; - case 2: - board.changePawn(piecelocation, Piece.Rook); - return true; - case 3: - board.changePawn(piecelocation, Piece.Bishop); - return true; - default: - return false; - }//end of switch - }//end of piecelocation method - -}//end of GUI class + public void promotePawn(Position pieceLocation) { + int selection = JOptionPane.showOptionDialog(null, + "Upgrade Your Pawn! Limited time only.", + "Choose a Promotion", + JOptionPane.DEFAULT_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + pawnPromotionOptions, + pawnPromotionOptions[0]); + PieceType selectedPiece; + switch (selection) { + case 0: + selectedPiece = PieceType.Queen; + break; + case 1: + selectedPiece = PieceType.Knight; + break; + case 2: + selectedPiece = PieceType.Rook; + break; + case 3: + selectedPiece = PieceType.Bishop; + break; + default: + return; + } + game.promotePawn(pieceLocation, selectedPiece); + } +} diff --git a/game/Game.java b/game/Game.java new file mode 100644 index 0000000..ccb7243 --- /dev/null +++ b/game/Game.java @@ -0,0 +1,32 @@ +package game; + +public class Game { + private Board board; + private boolean isWhiteTurn; + + public Game() { + this.board = new Board(); + this.isWhiteTurn = true; + } + + public Board getBoard() { + return board; + } + + public boolean isWhiteTurn() { + return isWhiteTurn; + } + + public void move(Position oldPosition, Position newPosition) { + board.movePiece(oldPosition, newPosition); + isWhiteTurn = !isWhiteTurn; + } + + public boolean isCheckmate() { + return board.isCheckmate(isWhiteTurn); + } + + public void promotePawn(Position position, PieceType type) { + board.promotePawn(position, type); + } +} \ No newline at end of file diff --git a/game/GamePiece.java b/game/GamePiece.java new file mode 100644 index 0000000..164e08f --- /dev/null +++ b/game/GamePiece.java @@ -0,0 +1,40 @@ + + + + +package game; + +public class GamePiece { + + private boolean isWhite; + private PieceType type; + + public GamePiece(boolean isWhite, PieceType type) { + this.setPieceType(type); + this.setIsWhite(isWhite); + }//default constructor + + public GamePiece() { + + } + + public void setIsWhite(boolean isWhite) { + this.isWhite = isWhite; + } + public boolean isWhite() { + return isWhite; + } + public void setPieceType(PieceType newpiece) { + type=newpiece; + } + public PieceType getPieceType() { + return type; + } + public String getPieceColor() { + if(this.isWhite()) { + return "White"; + }else { + return "Black"; + } + } +} diff --git a/game/Piece.java b/game/PieceType.java similarity index 78% rename from game/Piece.java rename to game/PieceType.java index 8accce9..056368b 100644 --- a/game/Piece.java +++ b/game/PieceType.java @@ -1,9 +1,11 @@ -public enum Piece { +package game; + +public enum PieceType { Pawn("Pawn "), Bishop("Bishop"), Knight("Knight"), Rook("Rook "), Queen("Queen "), King("King "); private final String name; - Piece(String string) { + PieceType(String string) { this.name=string; } public String toString() { diff --git a/game/Pieces.java b/game/Pieces.java deleted file mode 100644 index 631f71b..0000000 --- a/game/Pieces.java +++ /dev/null @@ -1,39 +0,0 @@ - - - - -public class Pieces { - - private boolean isWhite; - private Piece type; - - public Pieces(boolean iswhite, Piece tYpe) { - - this.setPieceType(tYpe); - this.setIsWhite(iswhite); - }//default constructor - - public Pieces() { - - } - - public void setIsWhite(boolean iswhite) { - isWhite=iswhite; - } - public boolean isWhite() { - return isWhite; - } - public void setPieceType(Piece newpiece) { - type=newpiece; - } - public Piece getPieceType() { - return type; - } - public String getPieceColor() { - if(this.isWhite()) { - return "White"; - }else { - return "Black"; - } - } -} diff --git a/game/Position.java b/game/Position.java new file mode 100644 index 0000000..d126dbe --- /dev/null +++ b/game/Position.java @@ -0,0 +1,32 @@ +package game; + +public class Position { + private final int row; + private final int column; + + public Position(int row, int column) { + this.row = row; + this.column = column; + } + + public int getRow() { + return row; + } + + public int getColumn() { + return column; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Position position = (Position) obj; + return row == position.row && column == position.column; + } + + @Override + public int hashCode() { + return 31 * row + column; + } +} \ No newline at end of file