Search code examples
javaarraysloopsif-statementcounting

Win condition in game not working. Trouble finding subsequent elements in 2D Array


I have an issue with my Gomoku game win conditions, in which I iterate through the 2D array looking for symbols related to each player. I have the typical nested for loop that goes through the array and a count that increases each time a symbol is found. However, I can't get it to display the count after iterating it at all, like it isn't even running through the loop. The function headers were given by my teacher, I'm not looking for a handout, but I am genuinely dumbfounded and feel like its something very simple I'm missing. The sout's in the function never display. Am I not iterating through the rows/columns correctly? The count should reset when moving to the next row/column and I thought it was doing that.

I thought it could be my main function structure further below not calling it correctly, but Ive messed with it for hours. Sorry its a mess and too much. The HorizontalWin and VerticalWin functions are at the bottom. They are being called in the main twice because I wasn't sure if hasPLayerWon was returning correctly.

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        char[][] board  = new char[19][19];

        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                board[i][j] = '.';
            }
        }
        displayBoard(board);

        /*
        !! WORKS !! Making a player boolean and putting player1 turn in an if statement nested within the win condition while loop
        and having the player2 work off the else. !! WORKS !!


        */
        int currentPlayer = 0;
        while ((!hasPlayerWon(board, currentPlayer) && isBoardFull(board))) {
            currentPlayer++;
            if (currentPlayer % 2 != 0) {
                System.out.println("Player 1's turn!");
                System.out.print("Enter row: ");
                int p1Row = input.nextInt();
                System.out.print("Enter col: ");
                int p1Col = input.nextInt();
                if (isValidMove(board, p1Row, p1Col)) //Move to while loop that returns boolean to stop loop once valid?
                {
                    board[p1Row][p1Col] = '●';
                    displayBoard(board);
                    isVerticalWin(board, currentPlayer);
                    isHorizontalWin(board, currentPlayer);
                } else {
                    currentPlayer--;
                }
            } else
                {
                    System.out.println("Player 2's turn!");
                    System.out.print("Enter row: ");
                    int p2Row = input.nextInt();
                    System.out.print("Enter col: ");
                    int p2Col = input.nextInt();
                if (isValidMove(board, p2Row, p2Col))
                {
                    board[p2Row][p2Col] = '○';
                    displayBoard(board);
                    isVerticalWin(board, currentPlayer);
                    isHorizontalWin(board, currentPlayer);
                } else {
                    currentPlayer--;
                }
            }
        }
    }

    public static void displayBoard(char[][] board)
    {
        for (int i = 0; i < board.length; i++)
        {
            for (int j = 0; j < board[i].length; j++)
            {
                System.out.print(" " + board[i][j]);
            }
            System.out.println();
        }
    }

    public static boolean isValidMove(char[][] board, int row, int column)
    {

        if (board[row][column] == '●')
        {
            System.out.println("Invalid move! Try again!");
            System.out.println();
            return false;

        } else if (board[row][column] == '○')
        {
            System.out.println("Invalid move! Try again!");
            System.out.println();
            return false;
        }else
        {
            return true;
        }

    }

    public static boolean isBoardFull(char[][] board)
    {
        int count = 0;
        for (int r = 0; r < board.length; r++)
        {
            for (int c = 0; c < board[r].length; c++)
            {
                if (board[r][c] == '●' || board[r][c] == '○')
                {
                    count++;
                    if (count == 361)
                    {
                        System.out.println("Board is full");
                        return false;
                    }
                }
            }
        }
        return true;
    }

    public static boolean hasPlayerWon(char[][] board, int currentPlayer)
    {
        if (isHorizontalWin(board, currentPlayer)) {
            System.out.println("Player " + currentPlayer + " wins!");
            return true;
        }
        if (isVerticalWin(board, currentPlayer)) {
            System.out.println("Player " + currentPlayer + " wins!");
            return true;
        }
        else return false;
    }

    public static boolean isHorizontalWin(char[][] board, int currentPlayer) {
        int count = 0;
        boolean hWin = false;
        if (currentPlayer == 0) {
            for (int r = 0; r < board.length; r++) {
                for (int c = 0; c < board[r].length; c++) {
                    if (board[r][c] == '●') {
                        System.out.println(count);
                        count++;
                    } else if (count == 5) {
                        hWin = true;
                    }
                }
            }
        }
        if (currentPlayer == 1) {
            for (int r = 0; r < board.length; r++) {
                for (int c = 0; c < board[r].length; c++) {
                    if (board[r][c] == '○') {
                        count++;
                        System.out.println(count);
                    } else if (count == 5) {
                        hWin = true;
                    }
                }
            }
        }
        return hWin;
    }

    public static boolean isVerticalWin(char[][] board, int currentPlayer)
    {
        int count = 0;
        boolean vWin = false;
        if (currentPlayer == 0) {
            for (int r = 0; r < board.length; r++) {
                for (int c = 0; c < board[r].length; c++) {
                    if (board[c][r] == '●') {
                        count++;
                        System.out.println(count);
                    } else if (count == 5) {
                        vWin = true;
                    }
                }
            }
        }
        if (currentPlayer == 1) {
            for (int r = 0; r < board.length; r++) {
                for (int c = 0; c < board[r].length; c++) {
                    if (board[c][r] == '○') {
                        count++;
                        System.out.println(count);
                    } else if (count == 5) {
                        vWin = true;
                    }
                }
            }
        }
        return vWin;
    }
}

I have tried multiple things. I have attempted to iterate through the functions by using the player as a boolean instead of a currentPlayer int. Ive tried to iterate through the array differently by changing the row/column in their respective for loops but it started getting messy and never worked. Ive tried to reset count to zero in an else statement. Ive placed sout's multiple places and the only time they DONT display is when inside of the if statement after the nested for. This code was working days ago but I never tested it thoroughly before rewriting a different section that changed the way my loops work, and now it doesnt work at all.


Solution

  • The issue with your code is in the currentPlayer variable.

    You are incrementing it every time in your loop with currentPlayer++; and only decrease it when the player makes in invalid move (no idea why you do that).

    In your isHorizontalWin and isVerticalWin functions, you are only checking if currentPlayer is 0 or 1. Since currentPlayer is already greater than 1 after the first move, the code that checks for a win will never run.

    The easiest way to fix this would probably be to just change the checks inside of your isHorizontalWin and isVerticalWin functions to:

    if (currentPlayer % 2 != 0) {
        // player 1 checks
    } else {
        // player 2 checks
    }
    

    Also, your hasPlayerWon function would have to be changed to convert currentPlayer to 1 or 2 by doing currentPlayer % 2.

    public static boolean hasPlayerWon(char[][] board, int currentPlayer)
    {
        if (isHorizontalWin(board, currentPlayer)) {
            System.out.println("Player " + currentPlayer % 2 + " wins!");
            return true;
        }
        if (isVerticalWin(board, currentPlayer)) {
            System.out.println("Player " + currentPlayer % 2 + " wins!");
            return true;
        }
        else return false;
    }