How to simplify this 4 loop functions into 1 function?

Viewed 94

I have an exercise. An int[8][8] chess grid. I have to find out if white can take a black. The input is: (lowercaps = black, upper = white)

tc.drf.t
ppp.pppp
...p...c
.....f..
..C..P..
..P.D.P.
PP.....P
T.F.RFCT

For the qeen/towers, I used a loop to check in each direction (top/bottom/left/right) and now have 4 simple loop functions that looks more or less the same. I would like to have only one function but can't manage to find how. Any idea?

    static boolean attackRowRt(String[] board, int y, int fromX){
        for(int x=fromX+1; x<=7; x++){
            char attacked = board[y].charAt(x);
            if(attacked == '.') continue;
            return  Character.isLowerCase(attacked);
        }
        return false;
    }

    static boolean attackRowLt(String[] board, int y, int fromX){
        for(int x=fromX-1; x>=0; x--){
            char attacked = board[y].charAt(x);
            if(attacked == '.') continue;
            return  Character.isLowerCase(attacked);
        }
        return false;
    }

    static boolean attackColBtm(String[] board, int x, int fromY){
        for(int y=fromY+1; y<=7; y++){
            char attacked = board[y].charAt(x);
            if(attacked == '.') continue;
            return  Character.isLowerCase(attacked);
        }
        return false;
    }

    static boolean attackColTop(String[] board, int x, int fromY){
        for(int y=fromY-1; y>=0; y--){
            char attacked = board[y].charAt(x);
            if(attacked == '.') continue;
            return  Character.isLowerCase(attacked);
        }
        return false;
    }
2 Answers

All four your methods share three lines of code that can be extracted to a separate method that you can call from your current methods (and you can simplify it to two lines of code if you invert the comparison with attacked). So basically have a separate method that does the following and call it from your methods:

char attacked = board[y].charAt(x);
if(attacked != '.') {
  return  Character.isLowerCase(attacked);
}

Furthermore, your methods are equal to each other in pairs: attackColTop() and attackRowLt are the same, and so are the other two methods. You don't need to have two methods that do the same if the only difference is the values of the parameters that you pass to the method: you can subsume both methods into one and just call it with the appropriate values.

The logic in every method is the same only the direction to walk differs. So by passing this as a parameter you can reuse the same method for all directions:

static boolean attackLine(String[] board, int fromY, int fromX, int deltaX, int deltaY) {
    int x = fromX + deltaX;
    int y = fromY + deltaY;
    while (true) {
        if (x <0 || x > 7 || y <0 || y > 7) {
            // outside board, this is the end
            return false;
        }
        System.out.println(String.format("checking (x,y):(%d,%d)", x, y));
        char attacked = board[y].charAt(x);
        if (attacked != '.')
        {
            System.out.println(String.format("piece found at (x,y):(%d,%d)", x, y));
            return Character.isLowerCase(attacked);
        }
        x += deltaX;
        y += deltaY;
    }
}

public static void main(String[] args) {
    String[] board = new String[] { //
            "tc.drf.t", //
            "ppp.pppp", //
            "...p...c", //
            ".....f..", //
            "..C..P..", //
            "..P.D.P.", //
            "PP.....P", //
            "T.F.RFCT" };
    // white queen left up
    System.out.println("" + attackLine(board, 7, 4, -1, -1));
    // white queen right up
    System.out.println("" + attackLine(board, 7, 4, 1, -1));
    // white queen left down
    System.out.println("" + attackLine(board, 7, 4, -1, 1));
    // white queen right down
    System.out.println("" + attackLine(board, 7, 4, 1, 1));
    // white tower up
    System.out.println("" + attackLine(board, 7, 0, 0, -1));
    
}
Related