4

I am a beginner android "developer" developing a chess app.

There is one variable in the InGameActivity class called currentBoardState which is public static. Every ChessPiece has a boolean[][] possibleMoves. This following method will take the possibleMoves and determine if any of the moves will cause the player to put him/herself in check and set it to false because it is no longer a possible move.

@Override
public void eliminateMovesThatPutYouInCheck() {
    ChessPiece[][] originalBoard = InGameActivity.currentBoardState;
    final ChessPiece emptyPiece = new EmptyPiece(Color.EMPTY);
    final ChessPiece tempKnight = new Knight(side);
    //This block eliminates moves that will cause a player
    //to put him/her self in check.
    InGameActivity.currentBoardState[x][y] = emptyPiece;
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            if (possibleMoves[i][j] == true) {
                tempKnight.x = i;
                tempKnight.y = j;
                InGameActivity.currentBoardState[i][j] = tempKnight;
                if (InGameActivity.isPlayerInCheck(side)) {
                    possibleMoves[i][j] = false;
                }
                InGameActivity.currentBoardState[i][j] = emptyPiece;
            }
        }
    }
    InGameActivity.currentBoardState = originalBoard;
}

The problem is, my currentBoardState variable is being messed up and I dont know why, ive saved the value then reset it at the end of the method why is it losing its values?

EDIT: Here is the isPlayerInCheck method if you need it, thank you.

public static boolean isPlayerInCheck(Color side) {
        List<boolean[][]> opponentsMoves = new ArrayList<boolean[][]>();
        int xKing = -1;
        int yKing = -1;

        if (side.equals(Color.WHITE)) {
            xKing = whiteKing.x;
            yKing = whiteKing.y;
        } else {
            xKing = blackKing.x;
            yKing = blackKing.y;
        }

        if (side.equals(Color.WHITE)) {
            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {
                    if (currentBoardState[i][j].isBlack()) {
                        opponentsMoves.add(currentBoardState[i][j].possibleMoves);
                    }
                }
            }
            for (boolean[][] b : opponentsMoves) {
                for (int i = 0; i < 8; i++) {
                    for (int j = 0; j < 8; j++) {
                        if (b[xKing][yKing] == true) {
                            return true;
                        }
                    }
                }
            }
            return false;

        } else {
            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {
                    if (currentBoardState[i][j].isWhite()) {
                        opponentsMoves.add(currentBoardState[i][j].possibleMoves);
                    }
                    if (currentBoardState[i][j].isBlack() && currentBoardState[i][j].getType().equals(Type.KING)) {
                        xKing = currentBoardState[i][j].x;
                        yKing = currentBoardState[i][j].y;
                    }
                }
            }
            for (boolean[][] b : opponentsMoves) {
                for (int i = 0; i < 8; i++) {
                    for (int j = 0; j < 8; j++) {
                        if (b[xKing][yKing] == true) {
                            return true;
                        }
                    }
                }
            }
            return false;

        }
    }

Also, I understand and appreciate that my code is probably very inefficient and the design is horrible for chess but that isn't really what I am concerned about at the moment.

Ogen
  • 6,499
  • 7
  • 58
  • 124
  • OK, but what does it mean that "your `currentBoardState` variable is being **messed up**" !? – Eel Lee Nov 22 '13 at 09:39
  • Do you mean its not resetting to the original board? – initramfs Nov 22 '13 at 09:40
  • Sorry for the ambiguity, my `currentBoardState` before the method, has `ChessPiece`s of type `King` `Queen` etc etc etc, but after I use the method, every cell is just a `ChessPiece` of type `Empty` – Ogen Nov 22 '13 at 09:43

3 Answers3

2

I'm assuming by messed up you mean the currentBoardState variable isn't being "reset" to the original board.

This is due to this line:

ChessPiece[][] originalBoard = InGameActivity.currentBoardState;

passing a reference of the current board state to the variable originalBoard.

As you make you modification to currentBoardState, since the originalBoard variable points to the same object, it gets modified as well.

Copy the array to the originalBoard variable like such:

ChessPiece[][] originalBoard = new ChessPiece[InGameActivity.currentBoardState.length][];
for(int i = 0; i < InGameActivity.currentBoardState.length; i++){
    ChessPiece[] pieces = InGameActivity.currentBoardState[i];
    int len = pieces.length;
    originalBoard[i] = new ChessPiece[len];
    System.arraycopy(pieces, 0, originalBoard[i], 0, len);
}

//Rest of code here...

Only when you copy by value does a actual copy of the data exist. Disregarding primitive types and some immutable data, using the assignment operator = merely assigns the reference of the RHS to the LHS.

initramfs
  • 8,275
  • 2
  • 36
  • 58
  • I will try this now and get back to you. So this is what the whole "passing by reference" and "passing by value" thing is about... – Ogen Nov 22 '13 at 09:50
  • @Clay Glad to help. I recommend you read up in depth on _pass by reference_ vs _pass by value_ since its a very fundamental concept in programming and will really screw you over if you don't take note of it. :) – initramfs Nov 22 '13 at 09:57
  • I definitely will after spending this much time trying to figure out what was going on >_< Thanks again. – Ogen Nov 22 '13 at 10:02
1

If I understand your code correctly, I think you need to copy the original to a new array, for example:

ChessPiece[][] originalBoard = Arrays.copyOf(
    InGameActivity.currentBoardState, InGameActivity.currentBoardState.length);

This prevents modification of the original array.

ThomasEdwin
  • 2,035
  • 1
  • 24
  • 36
0

You have the problem here:

if (possibleMoves[i][j]) 
{ 
    tempKnight.x = i;
    tempKnight.y = j;
    InGameActivity.currentBoardState[i][j] = tempKnight;
    if (InGameActivity.isPlayerInCheck(side))
    {
       possibleMoves[i][j] = false;
    }
    /** whatever was before next line resets the value at i,j: puts empty piece here */
    InGameActivity.currentBoardState[i][j] = emptyPiece;
}