3

I have been trying to get my tic tac toe program to work for a while now. At the moment I'm stuck in the win condition.

The game can now end as a draw but no player (human || computer) can win it.

I need to determine the winning conditions (horizontal, vertical, across) in playerHasWon but have no idea how to implement them.

import java.util.Scanner;
import java.util.Random;

public class NewTicTacToe {

public static final int DRAW = 0;
public static final int COMPUTER = 1;
public static final int PLAYER = 2;
public static final char PLAYER_MARK = 'X';
public static final char COMPUTER_MARK = 'O';

public static int size;
public static String[][] board;
public static int score = 0;
public static Scanner scan = new Scanner(System.in);

/**
 * Creates base for the game.
 *
 * @param args the command line parameters. Not used.
 */
public static void main(String[] args) {

    while (true) {
        System.out.println("Select board size");
        System.out.print("[int]: ");
        try {
            size = Integer.parseInt(scan.nextLine());
        } catch (Exception e) {
            System.out.println("You can't do that.");
            continue;
        }

        break;
    }

    int[] move = {};
    board = new String[size][size];
    setupBoard();

    int i = 1;

    loop:

    while (true) {
        if (i % 2 == 1) {
            displayBoard();
            move = getMove();
        } else {
            computerTurn();
        }

        switch (isGameFinished(move)) {
            case PLAYER:
                System.err.println("YOU WIN!");
                break loop;
            case COMPUTER:
                System.err.println("Computer WINS!\nYOU LOSE!");
                break loop;
            case DRAW:
                System.err.println("IT'S A DRAW");
                break loop;
        }

        i++;
    }
}

private static int isGameFinished(int[] move) {
    if (isDraw()) {
        return DRAW;
    } else if (playerHasWon(board, move, COMPUTER_MARK)) {
        return COMPUTER;
    } else if (playerHasWon(board, move, PLAYER_MARK)) {
        return PLAYER;
    }

    return -1;
}

/**
 * Checks for win.
 *
 * @param board
 * @return if the game is won.
 */
public static boolean playerHasWon(String[][] board, int[] move,
        char playerMark) { //playermark x || o
    boolean hasWon = false;

    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            // check if 5 in a line
            if (board[i][j].equals(playerMark)) {
                score++;
            } else {
                score = 0;
            }

            if (score == 5) {
                return true;
            }
        }
    }

    return hasWon;
}

/**
 * Checks for draws.
 *
 * @return if this game is a draw
 */
public static boolean isDraw() {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            if (board[i][j] == " ") {
                return false;
            }
        }
    }

    return true;
}

/**
 * Displays the board.
 *
 *
 */
public static void displayBoard() {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            System.out.printf("[%s]", board[i][j]);
        }

        System.out.println();
    }
}

/**
 * Displays the board.
 *
 *
 */
public static void setupBoard() {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            board[i][j] = " ";
        }
    }
}

/*
 * Takes in userinput and sends it to isValidPlay. 
 *
 *
 */
public static int[] getMove() {

    Scanner sc = new Scanner(System.in);
    System.out.println("Your turn:");

    while (true) {
        try {
            System.out.printf("ROW: [0-%d]: ", size - 1);
            int x = Integer.parseInt(sc.nextLine());
            System.out.printf("COL: [0-%d]: ", size - 1);
            int y = Integer.parseInt(sc.nextLine());

            if (isValidPlay(x, y)) {
                board[x][y] = "" + PLAYER_MARK;
                return new int[]{x, y};
            }
        } catch (Exception e) {
            System.out.println("You can't do that.");
        }
        return null;
    }
}

/*
 * Randomizes computer's turn - where it inputs the mark 'O'.
 *
 *
 */
public static void computerTurn() {
    Random rgen = new Random();  // Random number generator   

    while (true) {
        int x = (int) (Math.random() * size);
        int y = (int) (Math.random() * size);

        if (isValidPlay(x, y)) {
            board[x][y] = "" + COMPUTER_MARK;
            break;
        }
    }
}

/**
 * Checks if the move is possible.
 *
 * @param inX
 * @param inY
 * @return
 */
public static boolean isValidPlay(int inX, int inY) {

    // Play is out of bounds and thus not valid.
    if ((inX >= size) || (inY >= size)) {
        return false;
    }

    // Checks if a play have already been made at the location,
    // and the location is thus invalid. 
    return (board[inX][inY] == " ");
    }
}

// End of file
jjimih
  • 89
  • 11
  • 1
    You can check how others did it, for example: http://www.coderslexicon.com/a-beginner-tic-tac-toe-class-for-java/ – Albert Bos Nov 22 '15 at 15:25
  • This question is similar to another one where many different ideas were suggested in order to check the state of the game. http://stackoverflow.com/questions/1056316/algorithm-for-determining-tic-tac-toe-game-over?rq=1 – Omar Sharaki Nov 22 '15 at 19:34

1 Answers1

2

You could use a different approach to check for victories. Maybe split in three parts? Horizontal, vertical, and diagonals?

I made some changes to your code to give an example:

public static boolean playerHasWon(String[][] board, int[] move,
                                   String playerMark) { //playermark x || o

    //Horizontal check
    for (int i = 0; i < size; i++) {
        if (board[i][0].equals(playerMark)) {
            int j;
            for (j = 1; j < size; j++) {
                if (!board[i][j].equals(playerMark)) {
                    break;
                }
            }

            if (j == size) {
                return true;
            }
        }
    }

    //Vertical check
    for (int i = 0; i < size; i++) {
        if (board[0][i].equals(playerMark)) {
            int j;
            for (j = 1; j < size; j++) {
                if (!board[j][i].equals(playerMark)) {
                    break;
                }
            }

            if (j == size) {
                return true;
            }
        }
    }

    //Diagonals
    int i;
    for (i = 0; i < size; i++) {
        if (!board[i][i].equals(playerMark)) {
            break;
        }
    }
    if (i == size) {
        return true;
    }

    for (i = 0; i < size; i++) {
        if (!board[i][(size - 1) - i].equals(playerMark)) {
            break;
        }
    }
    if (i == size) {
        return true;
    }

    return false;
}

Note that you have to change the playerMarks from char to String. Also, I suggest displaying the board just before announcing who won. That way, if the computer wins, you can see its last move

mr.celo
  • 585
  • 1
  • 5
  • 17