Search code examples
javaarraystic-tac-toe

Customizable TicTacToe game board with Java


I need to create a method to check wether the tictactoe game is PLAYING, DRAW, XWIN or OWIN. However, I am having difficulty writing the code to check if X or O has won, given that the size of the gameboard and the size needed to win (sizeWin) are changing according to the user's input. AND I am forced to use a 1D array for the game board. I simply do not know where to go from here. My latest idea was to use nested for loops to check for a win by row, column or diagonal but I'm not sure how to implement it. If anyone has any tips on how to approach this problem or has any other solutions I would be very grateful

private void setGameState(int i) {

    // Check rows
    getLines();
    getColumns();
    getSizeWin();
    for (row = 0; row == lines; row++) {
        for (col = 0; col == columns; col++) {

        }
    }
}

public TicTacToeGame(int lines, int columns, int sizeWin) {

    // linesXcolumns game, starts with X, need sizeWin in a line/column/diag to win
    this.lines = lines;
    this.columns = columns;
    CellValue currentCellValue = CellValue.X;
    this.sizeWin = sizeWin;

    // Creating board according to given size
    int size = lines * columns;
    this.board = new CellValue[size];

    // Setting up board to be empty
    for (int i = 0; i < size; i++) {
        board[i] = CellValue.EMPTY;
    }
}

PS. If someone were to call the operator TicTacToe(3,4,3), a game board of 3 lines and 4 columns would print. And the number of X's or O's to win would be 3.

    CAM$ java TicTacToe 3 4 3 
      |    |    |
    ---------------
      |    |    |     
    --------------- 
      |    |    |

Solution

  • It is a little more complicated than it looks but after you get it it's simple. I've made a function that works just fine:

    private static String checkGameState() {
        // Looking for errors.
        if (rowCount <= 0 || columnCount <= 0) {
            return "ERROR: Illegal board size: " + rowCount + "*" + columnCount;
        }
        if (boradContent.length != rowCount * columnCount) {
            return "ERROR: boradContent not compatible with rowSize and columnSize.";
        }
        if (sizeWin > rowCount && sizeWin > columnCount) {
            return "ERROR: Board is too small for this sizeWin: " + sizeWin + ".";
        }
    
        String gameState = "PLAYING";
    
        // Checking rows
        for (int i = 0; i < rowCount; i++) {
            char currentChar = getField(i, 0);
            int score = 1;
            for (int j = 1; j < columnCount; j++) {
                if (currentChar == getField(i, j)) {
                    score++;
                    if (score >= sizeWin) {
                        if (gameState.equals("PLAYING")) {
                            gameState = currentChar + "WIN";
                        } else if (!gameState.equals(currentChar + "WIN")) {
                            gameState = "DRAW";
                            return gameState;
                        }
                    }
                } else {
                    if (j > columnCount - sizeWin) {
                        break;
                    }
                    score = 1;
                    currentChar = getField(i, j);
                }
            }
        }
    
        // Checking columns
        for (int j = 0; j < columnCount; j++) {
            char currentChar = getField(0, j);
            int score = 1;
            for (int i = 1; i < rowCount; i++) {
                if (currentChar == getField(i, j)) {
                    score++;
                    if (score >= sizeWin) {
                        if (gameState.equals("PLAYING")) {
                            gameState = currentChar + "WIN";
                        } else if (!gameState.equals(currentChar + "WIN")) {
                            gameState = "DRAW";
                            return gameState;
                        }
                    }
                } else {
                    if (j > rowCount - sizeWin) {
                        break;
                    }
                    score = 1;
                    currentChar = getField(i, j);
                }
            }
        }
    
        // Checking diagonally
        // Checking diagonally - from top-left to bottom-right
        for (int i = 0; i < rowCount - sizeWin + 1; i++) {
            for (int j = 0; j < columnCount - sizeWin + 1; j++) {
                char currentChar = getField(i, j);
                int score = 1;
                for (int k = 1; k < sizeWin; k++) {
                    if (currentChar == getField(i + k, j + k)) {
                        score++;
                        if (score >= sizeWin) {
                            if (gameState.equals("PLAYING")) {
                                gameState = currentChar + "WIN";
                            } else if (!gameState.equals(currentChar + "WIN")) {
                                gameState = "DRAW";
                                return gameState;
                            }
                        }
                    } else {
                        break;
                    }
                }
    
            }
        }
    
        // Checking diagonally - from top-right to bottom-left
        for (int i = 0; i < rowCount - sizeWin + 1; i++) {
            for (int j = sizeWin -1; j < columnCount; j++) {
                char currentChar = getField(i, j);
                int score = 1;
                for (int k = 1; k < sizeWin; k++) {
                    if (currentChar == getField(i + k, j - k)) {
                        score++;
                        if (score >= sizeWin) {
                            if (gameState.equals("PLAYING")) {
                                gameState = currentChar + "WIN";
                            } else if (!gameState.equals(currentChar + "WIN")) {
                                gameState = "DRAW";
                                return gameState;
                            }
                        }
                    } else {
                        break;
                    }
                }
    
            }
        }
    
        return gameState;
    }
    

    It is worth to mention that the rowCount, columnCount, sizeWin and boradContent variables are class level variables and i used a getField(int X, int Y) method that is not a very complicated thing but is more useful. It just converts the given field coordinates to the place in a 1D array and returns it's content:

    private static char getField(int X, int Y) {
        return boradContent[X * columnCount + Y];
    }