Many "if" in an old game for android

7

When checking if someone has won, I need to use IF several times. I would like to know if you can simplify the code a bit and even replace the IF s.

//left, top, right, bottom are int positions relative to canvas
//state is a enum{Blank,Red,Blue} which is used to determine if the square was clicked and who clicked it

private boolean checkHorizontalWin() {
    for (Square s1 : squareList) {
        if (s1.getState() != State.BLANK) {
            for (Square s2 : squareList) {
                if (s1 != s2) {
                    if (s1.getTop() == s2.getTop()) {
                        if (s1.getState() == s2.getState()) {
                            for (Square s3 : squareList) {
                                if (s1 != s3 && s2 != s3) {
                                    if (s1.getTop() == s3.getTop()) {
                                        if (s1.getState() == s3.getState()) {
                                            return true;
                                        } else break;
                                    }
                                }
                            }
                        } else break;
                    }
                }
            }
        }
    } return false;
}

private boolean checkVerticalWin() {
    for (Square s1 : squareList) {
        if (s1.getState() != State.BLANK) {
            for (Square s2 : squareList) {
                if (s1 != s2) {
                    if (s1.getLeft() == s2.getLeft()) {
                        if (s1.getState() == s2.getState()) {
                            for (Square s3 : squareList) {
                                if (s1 != s3 && s2 != s3) {
                                    if (s1.getLeft() == s3.getLeft()) {
                                        if (s1.getState() == s3.getState()) {
                                            return true;
                                        } else break;
                                    }
                                }
                            }
                        } else break;
                    }
                }
            }
        }
    } return false;
}

private boolean checkDiagonalWin() {
    for (Square s1 : squareList) {
        if (s1.getState() != State.BLANK) {
            for (Square s2 : squareList) {
                if (s1 != s2) {
                    if (s1.getBottom() != s2.getBottom()) {
                        if (s1.getRight() == s2.getLeft()) {
                            for (Square s3 : squareList) {
                                if (s1 != s3 && s2 != s3) {
                                    if (s1.getBottom() != s3.getBottom() && s2.getBottom() != s3.getBottom()) {
                                        if (s2.getRight() == s3.getLeft()){
                                            if (s1.getState() == s2.getState() && s1.getState() == s3.getState()) {
                                                return true;
                                            } else break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    } return false;
}

squareList is created in a similar way as this:

private List<Square> squareList = new ArrayList<>();
private final int GRID_SIZE = 3;
private final int GRID_AREA = GRID_SIZE * GRID_SIZE;

private void createSquares() {
    int x = 0;
    int y = 0;
    for (int i = 0; i < gridArea; i++) {
        int left = field.getWidth() / 3 * x;
        int top = field.getHeight() / 3 * y + field.getBorder();
        int right = field.getWidth() / 3 * (x + 1);
        int bottom = field.Height() / 3 * (y + 1) + field.getBorder();
        squareList.add(new Square(left, top, right, bottom, State.BLANK));

        x++;
        if (x == GRID_SIZE) {
            x = 0;
            y++;
        }
    }
}

I'd rather not be Java 8 due to lack of compatibility with old APIs

    
asked by anonymous 06.08.2018 / 22:20

2 answers

14

Do something like this:

// O squareList deve ser uma lista com 9 posições onde os índices estão assim:

// +---+---+---+
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// +---+---+---+

private State[] getStates() {
    State[] s = new State[9];
    int i = 0;
    for (Square sq : squareList) {
        s[i] = sq.getState();
        i++;
    }
    return s;
}

private boolean isWon(State[] s, int a, int b, int c) {
    return s[a] != State.BLANK && s[a] == s[b] && s[b] == s[c];
}

private boolean checkWin() {
    State[] s = getStates();
    return isWon(s, 0, 1, 2)  // Horizontal 1.
        || isWon(s, 3, 4, 5)  // Horizontal 2.
        || isWon(s, 6, 7, 8)  // Horizontal 3.
        || isWon(s, 0, 3, 6)  // Vertical 1.
        || isWon(s, 1, 4, 7)  // Vertical 2.
        || isWon(s, 2, 5, 8)  // Vertical 3.
        || isWon(s, 0, 4, 8)  // Diagonal 1.
        || isWon(s, 2, 4, 6); // Diagonal 2.
}

If you prefer to use Java ≥ 8, you can construct the getStates() method like this:

private State[] getStates() {
    return squareList.stream()
            .map(Square::getState)
            .collect(Collectors.toArray(State[]::new));
}

If the order of the elements in squareList is not what is outlined above, I strongly recommend that you change the mechanism by which squareList is built to be.

    
06.08.2018 / 22:42
0

I think it's cleaner this way:

private boolean checkHorizontalWin() {
        if(isEqual(squareList.get(0), squareList.get(1), squareList.get(2))) return true;
        if(isEqual(squareList.get(3), squareList.get(4), squareList.get(5))) return true;
        if(isEqual(squareList.get(6), squareList.get(7), squareList.get(8))) return true;
        return false;
    }

    private boolean checkVerticalWin() {
        if(isEqual(squareList.get(0), squareList.get(3), squareList.get(6))) return true;
        if(isEqual(squareList.get(1), squareList.get(4), squareList.get(7))) return true;
        if(isEqual(squareList.get(2), squareList.get(5), squareList.get(8))) return true;
        return false;
    }

    private boolean checkDiagonalWin() {
        if(isEqual(squareList.get(0), squareList.get(4), squareList.get(8))) return true;
        if(isEqual(squareList.get(2), squareList.get(4), squareList.get(6))) return true;
        return false;
    }

    private boolean isEqual(Square first, Square second, Square third) {
        if(first.getState() == State.BLANK || second.getState() == State.BLANK || third.getState() == State.BLANK)
            return false;

        long equalStatus = Arrays.asList(first, second, third)
                .stream().map(square -> square.getState()).collect(Collectors.toList())
                .stream().distinct().count();

        return equalStatus == 1;
    }
    
06.08.2018 / 23:12