Search code examples
javafunctional-programmingchess

Changing classic code to functional


I have the following portion of ugly (but working) code for checking if fields on a chessboard are vacant:

if (abs(xDst - xSrc) == abs(yDst - ySrc)) {
            boolean backslashMove = xSrc < xDst && ySrc > yDst || xSrc > xDst && ySrc < yDst;
            if (backslashMove) {
                int y = max(ySrc, yDst) - 1;
                for (int x = min(xSrc, xDst) + 1; x < max(xSrc, xDst); x++) {

                    if (board.getActiveChessmanAt(x, y).isAlive()) {
                        return false;
                    }
                    y--;
                }
            } else { //slash move

Obviously, it examines fields between coordinates (xScr, ySrc) and (xDst, yDst) in Bishop-like line of move.

I'm trying to transform this with using IntStream:

if (backslashMove) {
                final int y = max(ySrc, yDst) - 1;

                if (IntStream.range(min(xSrc, xDst) + 1, max(xSrc, xDst))
                        .anyMatch(x -> board.getActiveChessmanAt(x, y).isAlive()))
                return false;

How can I perform y-- in this case? It has to be final if it's about to be used within 'anyMatch' command


Solution

  • If you really need to rewrite it using streams, then you can use the fact that both x and y are incremented simultaneously. So you can build a range of increments instead of the range of x-values:

    final int xSrc = min(xSrc, xDst) + 1;
    final int xDst = max(xSrc, xDst);
    final int ySrc = max(ySrc, yDst) - 1;
    
    if (IntStream.range(0, xDst - xSrc)
        .anyMatch(distance -> board.getActiveChessmanAt(xSrc + distance, ySrc + distance).isAlive())) {
        return false;
    }
    

    In general, it's not possible to use a non-final local variable from the "parent" method directly. Java doesn't support real closures. You would need a wrapper object for this (AtomicInteger is an often suggested candidate), or you could make the non-final variable a class field (note the potential thread safety problems). To me personally, these both "tricks" are bad.