Building a Tic-Tac-Toe Game in Java

Learn How to Develop a Two-Player Tic-Tac-Toe Game in Java

Configr Technologies
8 min readAug 24, 2024
Tic-Tac-Toe Game in Java

Java, a powerful and versatile programming language, is ideal for building games and applications of all complexities.

In this tutorial, you’ll learn how to create a basic two-player tic-tac-toe game in the console.

This project will help you understand fundamental Java concepts, particularly multidimensional arrays and game logic, while honing your problem-solving skills.

Setting Up the Project

Before diving into the code, ensure that your development environment is ready.

You can use any Integrated Development Environment (IDE) that supports Java, such as IntelliJ IDEA, Eclipse, Visual Studio Code, or NetBeans.

Alternatively, a simple text editor combined with a terminal or command prompt will suffice if you prefer a lightweight setup.

Once your environment is set up, create a new Java project.

Inside this project, create a class named TicTacToe which will contain the main method and the game logic.

Understanding the Game Structure

Tic-tac-toe is a simple game played on a 3x3 grid.

Two players take turns marking the grid’s cells with their respective symbols: ‘X’ for the first player and ‘O’ for the second player.

The objective is to place three of your symbols in a horizontal, vertical, or diagonal row before your opponent does.

In this project, the game will be implemented using a 2D array.

The grid will be represented as a 3x3 array of characters. Each cell in the array will initially be empty, represented by a space character (‘ ‘).

As players take turns, their symbols (‘X’ or ‘O’) will replace the empty spaces.

Writing the Code

Step 1: Initializing the Game Board

The first step is to create the 3x3 game board.

This will be represented as a two-dimensional array of characters.

public class TicTacToe {

private static char[][] board = new char[3][3];

public static void main(String[] args) {
initializeBoard();
printBoard();
}

// Initialize the board with empty spaces
private static void initializeBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}

// Print the board to the console
private static void printBoard() {
System.out.println("-------------");
for (int i = 0; i < 3; i++) {
System.out.print("| ");
for (int j = 0; j < 3; j++) {
System.out.print(board[i][j] + " | ");
}
System.out.println();
System.out.println("-------------");
}
}
}

In this code snippet, we initialize the board with empty spaces and print it to the console.

The printBoard() method displays the current state of the board, surrounded by lines and dividers to improve readability.

Step 2: Handling Player Input

Next, we need to allow the players to input their moves.

Since this is a console-based game, we’ll use the Scanner class to read input from the console.

Each player will input the row and column numbers where they want to place their symbol.

import java.util.Scanner;

public class TicTacToe {

private static char[][] board = new char[3][3];
private static char currentPlayer = 'X';

public static void main(String[] args) {
initializeBoard();
while (true) {
printBoard();
playerMove();
if (isWinner()) {
printBoard();
System.out.println("Player " + currentPlayer + " wins!");
break;
}
if (isBoardFull()) {
printBoard();
System.out.println("The game is a tie!");
break;
}
switchPlayer();
}
}

private static void playerMove() {
Scanner scanner = new Scanner(System.in);
int row, col;

while (true) {
System.out.println("Player " + currentPlayer + ", enter your move (row and column): ");
row = scanner.nextInt();
col = scanner.nextInt();

if (row >= 0 && row < 3 && col >= 0 && col < 3 && board[row][col] == ' ') {
board[row][col] = currentPlayer;
break;
} else {
System.out.println("This move is not valid");
}
}
}

// Rest of the methods remain the same...
}

The playerMove() method reads the player's move and checks if it is valid.

The move is considered valid if the chosen cell is within the bounds of the board and is currently empty.

If the move is valid, the player's symbol is placed in the chosen cell.

Otherwise, the program prompts the player to enter a valid move.

Step 3: Implementing Game Logic

To determine the game’s outcome, we need to check for a winner after each move.

The game can end in three ways: a player wins by getting three symbols in a row, the board is full, or the game continues if neither of the first two conditions is met.

private static boolean isWinner() {
// Check rows and columns for a win
for (int i = 0; i < 3; i++) {
if ((board[i][0] == currentPlayer && board[i][1] == currentPlayer && board[i][2] == currentPlayer) ||
(board[0][i] == currentPlayer && board[1][i] == currentPlayer && board[2][i] == currentPlayer)) {
return true;
}
}

// Check diagonals for a win
if ((board[0][0] == currentPlayer && board[1][1] == currentPlayer && board[2][2] == currentPlayer) ||
(board[0][2] == currentPlayer && board[1][1] == currentPlayer && board[2][0] == currentPlayer)) {
return true;
}

return false;
}

private static boolean isBoardFull() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == ' ') {
return false;
}
}
}
return true;
}

The isWinner() method checks all rows, columns, and diagonals for three identical symbols in a row.

If such a condition is found, the current player is declared the winner.

The isBoardFull() method checks whether the board is completely filled, which would result in a tie if no winner is found.

Step 4: Switching Turns

To alternate between the two players, we need a method that switches the current player after each valid move.

private static void switchPlayer() {
currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';
}

The switchPlayer() method simply toggles the currentPlayer variable between 'X' and 'O' after each move.

Tic-Tac-Toe Game in Java

Final Code Overview

Below is the complete code for your Tic-Tac-Toe game in Java:

import java.util.Scanner;

public class TicTacToe {

private static char[][] board = new char[3][3];
private static char currentPlayer = 'X';

public static void main(String[] args) {
initializeBoard();
while (true) {
printBoard();
playerMove();
if (isWinner()) {
printBoard();
System.out.println("Player " + currentPlayer + " wins!");
break;
}
if (isBoardFull()) {
printBoard();
System.out.println("The game is a tie!");
break;
}
switchPlayer();
}
}

private static void initializeBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}

private static void printBoard() {
System.out.println("-------------");
for (int i = 0; i < 3; i++) {
System.out.print("| ");
for (int j = 0; j < 3; j++) {
System.out.print(board[i][j] + " | ");
}
System.out.println();
System.out.println("-------------");
}
}

private static void playerMove() {
Scanner scanner = new Scanner(System.in);
int row, col;

while (true) {
System.out.println("Player " + currentPlayer + ", enter your move (row and column): ");
row = scanner.nextInt();
col = scanner.nextInt();

if (row >= 0 && row < 3 && col >= 0 && col < 3 && board[row][col] == ' ') {
board[row][col] = currentPlayer;
break;
} else {
System.out.println("This move is not valid");
}
}
}

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

if ((board[0][0] == currentPlayer && board[1][1] == currentPlayer && board[2][2] == currentPlayer) ||
(board[0][2] == currentPlayer && board[1][1] == currentPlayer && board[2][0] == currentPlayer)) {
return true;
}

return false;
}

private static boolean isBoardFull() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == ' ') {
return false;
}
}
}
return true;
}

private static void switchPlayer() {
currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';
}
}

This code encapsulates the core logic of a Tic-Tac-Toe game in Java.

Here’s a concise breakdown of how the game operates:

  • Board Initialization: The initializeBoard() method sets up the 3x3 grid, initializing each cell with an empty space. This ensures that the game starts with a clean slate every time it's run.
  • Displaying the Board: The printBoard() method provides a clear, visually structured representation of the board after every move. The layout includes lines and dividers, making it easy to see the current game state.
  • Player Input: The playerMove() method allows each player to input their move. It verifies the move's validity by checking if the cell is within bounds and unoccupied. If the move is invalid, the player is prompted to enter a different move.
  • Game Logic: The isWinner() method evaluates whether the current player has won by checking rows, columns, and diagonals for three matching symbols. The isBoardFull() method checks if all cells are occupied, which would result in a tie if no winner is declared.
  • Switching Turns: The switchPlayer() method alternates the turn between players 'X' and 'O', ensuring fair gameplay.

Enhancing the Game

While the current version of the game is functional and demonstrates the essential concepts of Java, there are many ways to extend its capabilities:

  • Input Validation: Implementing more robust input validation can enhance user experience. For example, you can handle non-integer inputs and provide meaningful error messages.
  • Single-Player Mode: Adding an AI opponent allows for single-player gameplay. A basic AI might choose random empty spots, while a more advanced AI could use algorithms like minimax to provide a challenging experience.
  • Graphical Interface: Transitioning the game to a graphical user interface (GUI) using libraries such as Swing or JavaFX will make the game more interactive and visually appealing.
  • Scoring System: Keeping track of scores across multiple rounds adds another layer of engagement. Implement features to reset the game and display the running score.
  • Customizable Grid: Allow players to choose different grid sizes (e.g., 4x4 or 5x5) for increased complexity, which would require adjusting the game logic accordingly.

Creating a basic Tic-Tac-Toe game in Java is an excellent exercise for learning fundamental programming concepts.

This project introduced you to multidimensional arrays, user input handling, and basic game logic.

Whether you’re a beginner solidifying your understanding of Java or an experienced developer looking for a fun side project, building games like Tic-Tac-Toe is both educational and enjoyable.

As you advance in your Java development journey, consider expanding this project with additional features and exploring other classic games.

Tic-Tac-Toe Game in Java

The skills you’ve developed here will provide a strong foundation for tackling more complex challenges in the future.

Follow me on Medium, LinkedIn, and Facebook.

Please clap my articles if you find them useful, comment below, and subscribe to me on Medium for updates on when I post my latest articles.

Want to help support my future writing endeavors?

You can do any of the above things and/or “Buy me a cup of coffee.

It would be greatly appreciated!

Last and most important, enjoy your Day!

Regards,

George

--

--

Configr Technologies

Empowering Your Business With Technology Solutions That Meet Your Needs!