Search code examples
chess

Programming Chess Rook Movement


I am trying to create a board game where all the pieces are able to move the same as a rook in chess. (i.e. Horizontally or vertically as many spaces as they wish)

My board is a simple 2d integer array, with values of 0,1,2 depending on whether the space is empty, has a red piece or a black piece.

My code for the movement so far is shown below, it creates a true or false value if the move is allowed or not:

int[][] board;

public boolean validMove(int fromRow, int fromCol, int toRow, int toCol) {
    if (pieceAt(toRow, toCol) != EMPTY) {
        return false;
    } else if (fromRow - toRow == 0 && fromCol - toCol != 0) {
        return true;
    } else if (fromCol - toCol == 0 && fromRow - toRow != 0) {
        // Trying to add piece collision code
        for (int i = fromRow; i < toRow; i++) {
            if (pieceAt(toCol, i) != EMPTY)
                return false;
        }
        return true;
    } else {
        return false;
    }
}

My problem is trying to create collision detection, if another piece is in the way it should not be able to move past it, however with my code currently it can. Can anyone help me do this?


Solution

  • Try code below. It's quite naive (and also not tested), but I think it should work just as is. And also I think it illustrates the idea pretty well (see comments). It's in C, but I'm sure you can transform it easily to Java (or whatever language you use).

    bool validMove(int fromRow, int fromCol, int toRow, int toCol)
    {
        int i;
    
        // Attempt to move to the same cell
        if (fromRow == toRow && fromCol == toCol)
            return false;
    
        // Collision detection
        if (fromRow == toRow) {
            // Horizontal move
            if (fromCol < toCol) {
                // Move right
                for (i = fromCol + 1; i <= toCol; ++i)
                    if (pieceAt(fromRow, i) != EMPTY)
                        return false;
            } else {
                // Move left
                for (i = fromCol - 1; i >= toCol; --i)
                    if (pieceAt(fromRow, i) != EMPTY)
                        return false;
            }
        } else if (fromCol == toCol) {
            // Vertical move
            if (fromRow < toRow) {
                // Move down
                for (i = fromRow + 1; i <= toRow; ++i)
                    if (pieceAt(i, fromCol) != EMPTY)
                        return false;
            } else {
                // Move up
                for (i = fromRow - 1; i >= toRow; --i)
                    if (pieceAt(i, fromCol) != EMPTY)
                        return false;
            }
        } else {
            // Not a valid rook move (neither horizontal nor vertical)
            return false;
        }
    
        return true;
    }
    

    EDIT

    You can also optimize your code by reducing conditional statement count, using the method proposed by Toon Krijthe. The main idea is to use "delta" values (dx/dy) for incrementing or decrementing cell indexes. In that case the destination cell should be checked explicitly.

    Code:

    bool validMove(int fromRow, int fromCol, int toRow, int toCol)
    {
        int i;
    
        // Attempt to move to the same cell
        if (fromRow == toRow && fromCol == toCol)
            return false;
    
        // Collision detection
        if (fromRow == toRow) { // Horizontal move
            int dx = (fromCol < toCol) ? 1 : -1;
    
            for (i = fromCol + dx; i != toCol; i += dx)
                if (pieceAt(fromRow, i) != EMPTY)
                    return false;
        } else if (fromCol == toCol) { // Vertical move
            int dy = (fromRow < toRow) ? 1 : -1;
    
            for (i = fromRow + dy; i != toRow; i += dy)
                if (pieceAt(i, fromCol) != EMPTY)
                    return false;
        } else { // Not a valid rook move
            return false;
        }
    
        // Return true if destination cell is free
        return pieceAt(toRow, toCell) == EMPTY;
    }