Krishan Patel Krishan Patel - 2 months ago 10
Java Question

Win check conditions Connect 4 (Java)

I've been struggling with getting my win checker methods to work for my Connect4 code. My "work" I mean the game doesn't recognize a win configuration and will only end when all spaces are filled

I think there's something wrong with my algorithm, so I'm sure if I can figure out what's wrong with one of them then I should be able to fix all of them.

I want these methods to return a boolean value which will state whether someone has won or not.

Here's my full code:

public class ConnectFour
{
private static int rowMax = 7;
private static int colMax = 8;
private static String boardFill = "| |";

public static void main(String[] args)
{
String playerX = choosePlayerName("X").toUpperCase();
String playerO = choosePlayerName("O").toUpperCase();
String[][] players = {{playerX, playerO},{"X","O"}};

String endChoice;
do
{
int playerTurn = pickFirstPlayer(players);

String board[][] = createBoard(rowMax, colMax, boardFill);
printBoard(board);

int turnCount = 0;
boolean gameOver = false;
while (gameOver == false)
{
showPlayerTurn(players, playerTurn);

int rowChosen = -1;
int colChosen = -1;
do
{
colChosen = chooseCol(colMax);
rowChosen = findRowIndex(board, colChosen);
}
while (isValidMove(board, rowChosen) == false);

board[rowChosen][colChosen] = ("|"+players[1][playerTurn]+"|");
printBoard(board);

playerTurn = changePlayerTurn(playerTurn);
turnCount++;

gameOver = checkWinRows(board, rowMax, colMax);
gameOver = checkWinVertical(board, rowMax, colMax);
gameOver = checkWinFSlash(board, rowMax, colMax);
gameOver = checkWinBSlash(board, rowMax, colMax);
gameOver = checkMaxTurnCount(turnCount, rowMax, colMax);

}

if (checkMaxTurnCount(turnCount, rowMax, colMax))
{
System.out.println("\n\nMaximum number of moves reached, it's a draw.");
}
else
{
System.out.println("\nPlayer"+players[0][playerTurn]+" Wins!");
}
endChoice = checkQuitOrRestart().toUpperCase();
endQuit(endChoice);
}
while (endChoice.equals("R"));
}

// Player Instantiate Methods
public static String choosePlayerName(String playerSymbol)
{

@SuppressWarnings("resource")
Scanner nameInput = new Scanner(System.in);
System.out.println("\nYour Symbol is "+playerSymbol+". Please Enter Player's Name: ");
String playerName = nameInput.nextLine();

return playerName;
}
public static int pickFirstPlayer(String[][] players)
{
return (int) Math.round(Math.random());

}
// Board Create/Print Methods
public static String[][] createBoard(int rowMax, int colMax, String boardFill)
{
{
String board[][] = new String[rowMax][colMax];

for (int row = 0; row < rowMax; row++)
{
for (int col = 0; col < colMax; col++)
{
board[row][col] = boardFill;
}
}
return board;
}
}
public static void printBoard(String[][] board)
{
System.out.print("\n 1 2 3 4 5 6 7 8");
for (int row = 0; row < rowMax; row++)
{
System.out.print("\n");
for (int col = 0; col < colMax; col++)
{
System.out.print(board[row][col]);
}
}
}
// Player Turn Methods
public static void showPlayerTurn(String players[][], int playerTurn)
{
System.out.println("\nPlayer's Turn: "+players[0][playerTurn]+" ["+players[1][playerTurn]+"]");
}
public static int chooseCol(int colMax)
{
boolean isColValid;
int colChosen = -1;

do
{
isColValid = true;
@SuppressWarnings("resource")
Scanner colInput = new Scanner(System.in);
System.out.println("Choose a column to place your token [1-8]: ");
try
{
colChosen = colInput.nextInt();
if (colChosen < 1 || colChosen > colMax)
{
isColValid = false;
System.out.println("Column out of bounds.");
}
}
catch (NumberFormatException e)
{
isColValid = false;
System.out.println("Enter valid number");
}
catch (InputMismatchException e)
{
isColValid = false;
System.out.println("Enter column number as integer.");
}
}
while (!isColValid);

return (colChosen - 1);
}
public static int findRowIndex(String[][] board, int colChosen)
{
int rowChosen = -1;

for (int rowIndex = 0; rowIndex < board.length; rowIndex++)
{
if (board[rowIndex][colChosen] == boardFill)
{
rowChosen = rowIndex;
}
}

return rowChosen;
}
public static boolean isValidMove(String[][] board, int rowChosen)
{
boolean validMove;

if (rowChosen == -1)
{
System.out.print("Column full, please select valid column.");
validMove = false;
}
else
{
validMove = true;
}

return validMove;
}
public static int changePlayerTurn(int playerTurn)
{
if (playerTurn == 0)
{
playerTurn = 1;
}
else if (playerTurn ==1)
{
playerTurn = 0;
}

return playerTurn;
}
// Win/End Condition Check Methods
// Win Check Methods
public static boolean checkWinRows(String[][] board, int rowMax, int colMax)
{
boolean winRowCheck = false;

for (int row = 0; row < rowMax; row++)
{
for (int col = 0; col < (colMax - 3); col++)
{
if (board[row][col] == board[row][col + 1] &&
board[row][col] == board[row][col + 2] &&
board[row][col] == board[row][col + 3] &&
board[row][col] != "| |")
{
winRowCheck = true;
}
}
}

return winRowCheck;
}
public static boolean checkWinVertical(String[][] board, int rowMax, int colMax)
{
boolean winVerticalCheck = false;

for (int row = 0; row < (rowMax - 3); row++)
{
for (int col = 0; col < (colMax - 3); col++)
{
if (board[row][col] == board[row + 1][col] &&
board[row][col] == board[row + 2][col] &&
board[row][col] == board[row + 3][col] &&
board[row][col] != "| |")
{
winVerticalCheck = true;
}
}
}

return winVerticalCheck;
}
public static boolean checkWinFSlash(String[][] board, int rowMax, int colMax)
{
Boolean winFSlashCheck = false;

for (int row = 3; row < rowMax; row++)
{
for (int col = 0; col < (colMax - 3); col++)
{
if (board[row][col] == board[row - 1][col + 1] &&
board[row][col] == board[row - 2][col + 2] &&
board[row][col] == board[row - 3][col + 3] &&
board[row][col] != "| |")
{
winFSlashCheck = true;
}
}
}

return winFSlashCheck;
}
public static boolean checkWinBSlash(String[][] board, int rowMax, int colMax)
{
boolean winBSlash = false;

for (int row = 4; row < rowMax; row++)
{
for (int col = 3; col < (colMax - 3); col++)
{
if (board[row][col] == board[row - 1][col - 1] &&
board[row][col] == board[row - 1][col - 2] &&
board[row][col] == board[row - 1][col - 3] &&
board[row][col] != "| |")
{
winBSlash = true;
}
}
}

return winBSlash;
}
public static boolean checkMaxTurnCount(int turnCount, int rowMax, int colMax)
{
boolean maxTurnCountReached = false;

if (turnCount >= rowMax*colMax)
{
maxTurnCountReached = true;
}

return maxTurnCountReached;
}
// End Prompt Methods
// End Game Methods
public static String checkQuitOrRestart()
{
@SuppressWarnings("resource")
Scanner endChoiceImport = new Scanner(System.in);
System.out.println("\nPlease Select: Restart [R] or Quit [Q]");
String endChoice = endChoiceImport.next();

return endChoice;
}
public static void endQuit(String endChoice)
{
if (endChoice.equals("Q") || endChoice.equals("q"))
{
System.out.println("\nQuitting Program.");
System.exit(0);
}
else if (endChoice.equals("R"))
{
System.out.println("\nRestarting Program.");
}
}


Here's one of the methods (checkWinRows):

public static boolean checkWinRows(String[][] board, int rowMax, int colMax)
{
boolean winRowCheck = false;

for (int row = 0; row < rowMax; row++)
{
for (int col = 0; col < (colMax - 3); col++)
{
if (board[row][col] == board[row][col + 1] &&
board[row][col] == board[row][col + 2] &&
board[row][col] == board[row][col + 3] &&
board[row][col] != "| |")
{
winRowCheck = true;
}
}
}

return winRowCheck;
}

Answer

First of all, Strings need to be compared using the equals method, otherwise you will compare their references instead of their content.

For example, the if statement in checkWinRows would look like this:

if ((board[row][col].equals(board[row + 1][col]))
    && (board[row][col].equals(board[row + 2][col]))
    && (board[row][col].equals(board[row + 3][col]))
    && (!board[row][col].equals("| |"))) {
    winVerticalCheck = true;
}

Then, when you are checking for the gameOver, the variable is overwritten by the subsequent methods. You could avoid this using a simple check like this:

gameOver = checkWinRows(board, rowMax, colMax);
if(!gameOver) {
    gameOver = checkWinVertical(board, rowMax, colMax);
}
if(!gameOver) {
    gameOver = checkWinFSlash(board, rowMax, colMax);
}
...

I didn't look at the whole source so there might be other errors or details you could optimize/improve (for example you could immediately return true when you find a win instead of always completing the whole cycle), but this should be enough for you to go on your own.

Also remember to always use a debugger when the program is not behaving as you would expect, it is really a fundamental tool. IDEs like Eclipse always have one integrated that you can easily use.

Comments