Tic-Tac-Toe Game in Java: Two-Player Console-Based Project
Introduction to the Java Tic-Tac-Toe Game:
Tic-Tac-Toe Game:
Create a simple two-player console-based game.
A console-based version of the classic two-player game. Players take turns marking spaces on a 3x3 grid, and the first player to get three marks in a row (horizontally, vertically, or diagonally) wins.
Input: Player move (row and column) on a 3x3 grid.
Output: Updated game board and game status (win/draw/continue).
Example:
- Input: Player 1 selects row 1, column 2
- Output: Updated grid, "Player 1 wins" or "Continue playing"
Solution 1: Tic-Tac-Toe with Simple Array and Loops
Code:
import java.util.Scanner;
public class TicTacToeSimple {
// Declare a 3x3 array to represent the game board
static char[][] board = new char[3][3];
public static void main(String[] args) {
// Initialize the board with empty spaces
initializeBoard();
// Variable to keep track of the current player ('X' or 'O')
char currentPlayer = 'X';
// Variable to check if the game is won or drawn
boolean gameWon = false;
boolean draw = false;
// Create a Scanner object for input
Scanner scanner = new Scanner(System.in);
// Main game loop, runs until a player wins or it's a draw
while (!gameWon && !draw) {
printBoard(); // Display the board
System.out.println("Player " + currentPlayer + "'s turn. Enter row and column (1-3):");
// Get player input for row and column
int row = scanner.nextInt() - 1;
int col = scanner.nextInt() - 1;
// Check if the selected cell is empty
if (board[row][col] == ' ') {
// Place the current player's mark on the board
board[row][col] = currentPlayer;
// Check if the current player has won the game
gameWon = checkWin(currentPlayer);
if (!gameWon) {
// Check if the board is full (draw)
draw = checkDraw();
// Switch the player if the game isn't won
currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';
}
} else {
System.out.println("Cell is already occupied! Try again.");
}
}
// Display the final board
printBoard();
// Display game result
if (gameWon) {
System.out.println("Player " + currentPlayer + " wins!");
} else {
System.out.println("It's a draw!");
}
// Close the scanner
scanner.close();
}
// Function to initialize the board with empty spaces
public static void initializeBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}
// Function to print the current state of the board
public static void printBoard() {
System.out.println(" 1 2 3");
for (int i = 0; i < 3; i++) {
System.out.print((i + 1) + " ");
for (int j = 0; j < 3; j++) {
System.out.print(board[i][j]);
if (j < 2) System.out.print("|");
}
System.out.println();
if (i < 2) System.out.println(" -----");
}
}
// Function to check if the current player has won
public static boolean checkWin(char player) {
// Check rows, columns, and diagonals
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;
}
if (board[0][0] == player && board[1][1] == player && board[2][2] == player)
return true;
if (board[0][2] == player && board[1][1] == player && board[2][0] == player)
return true;
return false;
}
// Function to check if the board is full (indicating a draw)
public static boolean checkDraw() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == ' ') {
return false; // If any cell is empty, it's not a draw
}
}
}
return true; // If no empty cells, it's a draw
}
}
Output:
1 2 3 1 | | ----- 2 | | ----- 3 | | Player X's turn. Enter row and column (1-3): 1 1 1 2 3 1 X| | ----- 2 | | ----- 3 | | Player O's turn. Enter row and column (1-3): 1 2 1 2 3 1 X|O| ----- 2 | | ----- 3 | | Player X's turn. Enter row and column (1-3): 3 3 1 2 3 1 X|O| ----- 2 | | ----- 3 | |X Player O's turn. Enter row and column (1-3): 3 2 1 2 3 1 X|O| ----- 2 | | ----- 3 |O|X Player X's turn. Enter row and column (1-3): 2 2 1 2 3 1 X|O| ----- 2 |X| ----- 3 |O|X Player X wins!
Explanation :
- Game Board: The board is represented by a 2D array, initialized with empty spaces.
- Player Input: Players input the row and column to place their mark.
- Win/Draw Conditions: The game checks for a win by rows, columns, or diagonals. It also checks if all spaces are filled (indicating a draw).
- Switching Players: The game alternates between 'X' and 'O'.
- Loop: The game loop runs until either a player wins or the game ends in a draw.
Solution 2: Using Object-Oriented Approach
Key points:
- Game Board Initialization: The board is initialized as a 3x3 grid, filled with empty spaces.
- Player Moves: The user inputs row and column values, and the game updates the board accordingly if the input is valid.
- Win Condition: After every move, the game checks if the current player has completed a row, column, or diagonal.
- Draw Condition: If the board is full and no one wins, the game is a draw.
- Switching Players: After every valid move, the current player switches between 'X' and 'O'.
- Game Restart: After a game ends, players can choose to restart the game with an empty board or end the session.
- Statistics: The game keeps track of how many games each player has won and the number of draws.
- Input Validation: Invalid inputs (e.g., selecting already occupied spots or entering out-of-bound values) are handled, and the player is prompted to re-enter their move.
Code:
TicTacToe.java
import java.util.Scanner;
class TicTacToe {
private char[][] board;
private char currentPlayer;
private int playerXWins;
private int playerOWins;
private int draws;
// Constructor to initialize the board and set the starting player
public TicTacToe() {
board = new char[3][3];
currentPlayer = 'X';
initializeBoard();
playerXWins = 0; // Track Player X wins
playerOWins = 0; // Track Player O wins
draws = 0; // Track draws
}
// Initialize the board with empty spaces
private void initializeBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = ' ';
}
}
}
// Display the current state of the board
public void printBoard() {
System.out.println(" 1 2 3");
for (int i = 0; i < 3; i++) {
System.out.print((i + 1) + " ");
for (int j = 0; j < 3; j++) {
System.out.print(board[i][j]);
if (j < 2) System.out.print("|");
}
System.out.println();
if (i < 2) System.out.println(" -----");
}
}
// Switch the current player between 'X' and 'O'
public void switchPlayer() {
currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';
}
// Handle player input and update the board
public boolean makeMove(int row, int col) {
if (row >= 0 && row < 3 && col >= 0 && col < 3 && board[row][col] == ' ') {
board[row][col] = currentPlayer;
return true;
}
return false;
}
// Check if the current player has won the game
public boolean checkWin() {
for (int i = 0; i < 3; i++) {
if (board[i][0] == currentPlayer && board[i][1] == currentPlayer && board[i][2] == currentPlayer)
return true;
if (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)
return true;
if (board[0][2] == currentPlayer && board[1][1] == currentPlayer && board[2][0] == currentPlayer)
return true;
return false;
}
// Check if the board is full (indicating a draw)
public boolean checkDraw() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == ' ') {
return false;
}
}
}
return true;
}
// Get the current player
public char getCurrentPlayer() {
return currentPlayer;
}
// Update the win count for the current player
public void updateWinCount() {
if (currentPlayer == 'X') {
playerXWins++;
} else {
playerOWins++;
}
}
// Increment the draw count
public void updateDrawCount() {
draws++;
}
// Display the game statistics
public void displayStatistics() {
System.out.println("Player X Wins: " + playerXWins);
System.out.println("Player O Wins: " + playerOWins);
System.out.println("Draws: " + draws);
}
// Reset the board for a new game
public void resetBoard() {
initializeBoard();
currentPlayer = 'X'; // Player X always starts the new game
}
}
Explanation:
- Class Definition:
- The TicTacToe class manages the game's logic, including the board, player turns, win checks, and statistics.
- Fields:
- board: A 3x3 char array representing the game board.
- currentPlayer: Tracks the current player ('X' or 'O').
- playerXWins, playerOWins, draws: Integers to track the number of wins for each player and the number of draws.
- Constructor:
- Initializes the board, sets the starting player to 'X', and resets the win/draw counters.
- initializeBoard():
- Fills the board with empty spaces (' ') to prepare it for gameplay.
- printBoard():
- Displays the current state of the board in a 3x3 grid format with row and column numbers for easy reference.
- switchPlayer():
- Switches the current player between 'X' and 'O' after each turn.
- makeMove(int row, int col):
- Places the current player's mark on the specified row and column, if the spot is valid and unoccupied.
- Returns true if the move is valid, otherwise false.
- checkWin():
- Checks all possible winning conditions (rows, columns, and diagonals) to determine if the current player has won.
- Returns true if there is a win, otherwise false.
- checkDraw():
- Checks if the board is full and no moves are possible, indicating a draw.
- Returns true if the game is a draw, otherwise false.
- getCurrentPlayer():
- Returns the current player ('X' or 'O').
- updateWinCount():
- Increments the win count for the current player (either playerXWins or playerOWins).
- updateDrawCount():
- Increments the draw count (draws).
- displayStatistics():
- Displays the current statistics: number of wins for Player X, Player O, and the number of draws.
- resetBoard():
- Resets the board for a new game, clearing all spaces and setting the starting player to 'X'.
TicTacToeOOP.java
import java.util.Scanner;
public class TicTacToeOOP {
public static void main(String[] args) {
TicTacToe game = new TicTacToe(); // Create a new TicTacToe game object
Scanner scanner = new Scanner(System.in);
boolean playAgain = true;
// Main game loop (for multiple games)
while (playAgain) {
boolean gameWon = false;
boolean draw = false;
// Game loop for a single game
while (!gameWon && !draw) {
game.printBoard(); // Display the game board
System.out.println("Player " + game.getCurrentPlayer() + "'s turn. Enter row and column (1-3):");
// Get player input for row and column
int row = scanner.nextInt() - 1;
int col = scanner.nextInt() - 1;
// Make the move and check for validity
if (game.makeMove(row, col)) {
gameWon = game.checkWin();
if (!gameWon) {
draw = game.checkDraw();
if (!draw) {
game.switchPlayer(); // Switch player if game isn't won
} else {
System.out.println("It's a draw!");
game.updateDrawCount(); // Increment the draw count
}
} else {
game.printBoard();
System.out.println("Player " + game.getCurrentPlayer() + " wins!");
game.updateWinCount(); // Increment win count for the current player
}
} else {
System.out.println("Invalid move. Try again.");
}
}
// Display the game statistics
game.displayStatistics();
// Ask if the players want to play again
System.out.println("Do you want to play again? (yes/no):");
String response = scanner.next();
if (response.equalsIgnoreCase("yes")) {
game.resetBoard(); // Reset the board for a new game
} else {
playAgain = false; // Exit the game loop
}
}
System.out.println("Thanks for playing!");
scanner.close();
}
}
Explanation:
- Imports:
- java.util.Scanner: Used to capture user input from the console.
- main() Method:
- The entry point of the program where the game logic is executed.
- Game Initialization:
- Creates a TicTacToe object named game.
- Initializes a Scanner object to read user input.
- Main Game Loop (while (playAgain)):
- Controls whether the players want to play another game.
- Runs continuously until the players choose not to play again.
- Single Game Loop:
- Repeats until either a player wins or the game ends in a draw.
- Calls game.printBoard() to display the current state of the board.
- Prompts the current player to enter row and column coordinates for their move.
- Input Handling:
- Player enters row and column (1-3), which are converted to 0-indexed values.
- Checks if the move is valid using game.makeMove().
- Move Validation:
- If the move is valid:
- Calls game.checkWin() to see if the current player has won.
- If no one has won, calls game.checkDraw() to see if the game is a draw.
- If the game is ongoing, switches the player using game.switchPlayer().
- Winning Condition:
- If a player wins, the board is displayed, and the current player is declared the winner.
- Increments the win count for the winner using game.updateWinCount().
- Draw Condition:
- If the game is a draw, displays a message and increments the draw count with game.updateDrawCount().
- Display Statistics:
- After each game, game.displayStatistics() shows the win and draw counts.
- Play Again Prompt:
- Asks the players if they want to play another game.
- If they answer "yes", the board is reset using game.resetBoard().
- If "no", the loop ends, and the game concludes.
- Game Conclusion:
- Displays a thank-you message and closes the Scanner object.
Output:
1 2 3 1 | | ----- 2 | | ----- 3 | | Player X's turn. Enter row and column (1-3): 1 1 1 2 3 1 X| | ----- 2 | | ----- 3 | | Player O's turn. Enter row and column (1-3): 1 3 1 2 3 1 X| |O ----- 2 | | ----- 3 | | Player X's turn. Enter row and column (1-3): 2 1 1 2 3 1 X| |O ----- 2 X| | ----- 3 | | Player O's turn. Enter row and column (1-3): 3 1 1 2 3 1 X| |O ----- 2 X| | ----- 3 O| | Player X's turn. Enter row and column (1-3): 2 2 1 2 3 1 X| |O ----- 2 X|X| ----- 3 O| | Player O's turn. Enter row and column (1-3): 2 3 1 2 3 1 X| |O ----- 2 X|X|O ----- 3 O| | Player X's turn. Enter row and column (1-3): 1 2 1 2 3 1 X|X|O ----- 2 X|X|O ----- 3 O| | Player O's turn. Enter row and column (1-3): 3 3 1 2 3 1 X|X|O ----- 2 X|X|O ----- 3 O| |O Player O wins! Player X Wins: 0 Player O Wins: 1 Draws: 0 Do you want to play again? (yes/no): no Thanks for playing!
Java Code Editor:
It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.
https://w3resource.com/projects/java/java-project-tic-tac-toe-game.php
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics