← All writing

FIELD NOTES

My Tic-Tac-Toe Game in Java

In this note

I built this two-player Tic-Tac-Toe game as a way to practise Java fundamentals: arrays, loops, methods, conditionals and reading input from the console. The Java version runs in the terminal. A small browser preview is included below so the game can be tried without compiling the Java program. The browser preview is a separate HTML/CSS/JavaScript implementation; it is not a Java GUI.

Java implementation

The board is a 3 × 3 character array. Players choose X or O, select a square from 1 to 9, and alternate turns. Invalid input and occupied squares do not consume a turn.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import java.util.Scanner;

public class TicTacToe {
    private static final Scanner INPUT = new Scanner(System.in);

    public static void main(String[] args) {
        char playerOne = readSymbol("Player 1, choose X or O: ");
        char playerTwo = playerOne == 'X' ? 'O' : 'X';
        char firstTurn = readSymbol("Which symbol goes first (X/O)? ");

        play(playerOne, playerTwo, firstTurn);
    }

    private static char readSymbol(String prompt) {
        while (true) {
            System.out.print(prompt);
            String input = INPUT.next().trim().toUpperCase();
            if (input.length() == 1 && (input.charAt(0) == 'X' || input.charAt(0) == 'O')) {
                return input.charAt(0);
            }
            System.out.println("Enter X or O.");
        }
    }

    private static void play(char playerOne, char playerTwo, char currentPlayer) {
        char[][] board = {
            {'1', '2', '3'},
            {'4', '5', '6'},
            {'7', '8', '9'}
        };

        int moves = 0;
        while (moves < 9) {
            displayBoard(board);
            int square = readSquare(board, currentPlayer);
            int row = (square - 1) / 3;
            int col = (square - 1) % 3;
            board[row][col] = currentPlayer;
            moves++;

            if (hasWinner(board, currentPlayer)) {
                displayBoard(board);
                System.out.println("Player " + (currentPlayer == playerOne ? "1" : "2")
                        + " (" + currentPlayer + ") wins!");
                return;
            }

            currentPlayer = currentPlayer == playerOne ? playerTwo : playerOne;
        }

        displayBoard(board);
        System.out.println("It's a draw!");
    }

    private static int readSquare(char[][] board, char player) {
        while (true) {
            System.out.print("Player " + player + ", choose a free square (1-9): ");
            if (!INPUT.hasNextInt()) {
                String invalid = INPUT.next();
                System.out.println("'" + invalid + "' is not a number. Try again.");
                continue;
            }

            int square = INPUT.nextInt();
            if (square < 1 || square > 9) {
                System.out.println("Choose a number between 1 and 9.");
                continue;
            }

            int row = (square - 1) / 3;
            int col = (square - 1) % 3;
            if (board[row][col] == 'X' || board[row][col] == 'O') {
                System.out.println("That square is already taken.");
                continue;
            }
            return square;
        }
    }

    private static boolean hasWinner(char[][] board, char player) {
        for (int i = 0; i < 3; i++) {
            if (board[i][0] == player && board[i][1] == player && board[i][2] == player) return true;
            if (board[0][i] == player && board[1][i] == player && board[2][i] == player) return true;
        }
        return (board[0][0] == player && board[1][1] == player && board[2][2] == player)
                || (board[0][2] == player && board[1][1] == player && board[2][0] == player);
    }

    private static void displayBoard(char[][] board) {
        System.out.println();
        for (int row = 0; row < 3; row++) {
            System.out.printf(" %c | %c | %c %n", board[row][0], board[row][1], board[row][2]);
            if (row < 2) System.out.println("---+---+---");
        }
        System.out.println();
    }
}

Run it locally

Save the code as TicTacToe.java, then compile and run it with a JDK:

1
2
javac TicTacToe.java
java TicTacToe

What this project taught me

  • A two-dimensional array is a straightforward way to model a fixed-size board.
  • Input validation belongs at the boundary where user input enters the program.
  • Separating input, display, move validation and winner detection makes the code easier to reason about.
  • A game loop should stop immediately after a win and report a draw only after all nine valid moves.