Zoho round 3 tic tac toe

Designing a Command-Line Tic Tac Toe Game in Java

In this article, I’ll share my approach to solving a challenging programming question posed during the Zoho 3rd-round technical interview. The task?

Develop a robust n x n Tic Tac Toe game that runs in the command line, adheres to coding standards, and handles all edge cases independently.

Let’s dive into the requirements, design considerations, and the Java implementation for this program.

The Question: Build an n x n Tic Tac Toe Game

Requirements:

  • Dynamic grid size: The game should work for any grid size n.
  • Two-player functionality: Players alternate turns, marking X or O.
  • Win detection: Determine the winner based on row, column, or diagonal matches.
  • Edge cases: Handle invalid moves, boundary conditions, and draw scenarios.
  • Clean, optimized code: Follow coding standards and close resources to prevent memory leaks.

Approach and Design

Before writing the code, I focused on structuring the solution logically:

  1. Board Initialization: Set up an n x n board initialized with -.
  2. Player Interaction: Alternate between two players (X and O) and validate moves.
  3. Win Check: Implement efficient methods to check rows, columns, and diagonals for a win condition.
  4. Game States: Track the number of moves, detect invalid moves, and determine draw conditions.
  5. Edge Cases: Handle scenarios like out-of-bound inputs, overwriting existing moves, and ensuring diagonal checks are robust.

The Java Code: Step-by-Step Implementation

Here’s the complete Java program for the n x n Tic Tac Toe game. I’ve added comments to explain the logic behind each block:

import java.util.Scanner;

public class TicTacToe {
    // Board to hold the game state
    private static char[][] board;
    private static int n;  // Size of the grid
    private static char currentPlayer;  // Current player's symbol ('X' or 'O')
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // Ask user for grid size
        System.out.print("Enter the size of the grid (n x n): ");
        n = scanner.nextInt();
        // Initialize the board
        board = new char[n][n];
        initializeBoard();
        // Start with player 'X'
        currentPlayer = 'X';
        int moves = 0;
        boolean gameWon = false;
        // Game loop: Continue until all moves are played or a player wins
        while (moves < n * n && !gameWon) {
            printBoard(); // Show the current board to players
            System.out.printf("Player %c, enter your move (row and column): ", currentPlayer);
            
            int row = scanner.nextInt();
            int col = scanner.nextInt();
            // Validate the move
            if (isValidMove(row, col)) {
                board[row][col] = currentPlayer; // Mark the board
                moves++; // Increment move count
                
                // Check if the current player wins
                if (checkWin(row, col)) {
                    gameWon = true;
                    printBoard();
                    System.out.printf("Player %c wins!%n", currentPlayer);
                } else {
                    // Switch to the next player
                    currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';
                }
            } else {
                System.out.println("Invalid move. Try again.");
            }
        }
        // If no one wins, it's a draw
        if (!gameWon) {
            printBoard();
            System.out.println("The game is a draw!");
        }
        scanner.close(); // Close the scanner to prevent resource leaks
    }
    // Initialize the board with empty cells
    private static void initializeBoard() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = '-';
            }
        }
    }
    // Print the current state of the board
    private static void printBoard() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(board[i][j] + " ");
            }
            System.out.println();
        }
    }
    // Validate if a move is within bounds and the cell is empty
    private static boolean isValidMove(int row, int col) {
        return row >= 0 && row < n && col >= 0 && col < n && board[row][col] == '-';
    }
    // Check if the current move results in a win
    private static boolean checkWin(int row, int col) {
        return checkRow(row) || checkColumn(col) || checkDiagonals();
    }
    // Check if all cells in the row belong to the current player
    private static boolean checkRow(int row) {
        for (int col = 0; col < n; col++) {
            if (board[row][col] != currentPlayer) {
                return false;
            }
        }
        return true;
    }
    // Check if all cells in the column belong to the current player
    private static boolean checkColumn(int col) {
        for (int row = 0; row < n; row++) {
            if (board[row][col] != currentPlayer) {
                return false;
            }
        }
        return true;
    }
    // Check the two diagonals for a win condition
    private static boolean checkDiagonals() {
        boolean diag1 = true, diag2 = true;
        for (int i = 0; i < n; i++) {
            if (board[i][i] != currentPlayer) {
                diag1 = false;
            }
            if (board[i][n - i - 1] != currentPlayer) {
                diag2 = false;
            }
        }
        return diag1 || diag2;
    }
}

Key Features

1. Dynamic Grid Size

  • The grid size is determined at runtime, allowing flexibility.

2. Efficient Win Checks

  • Row, column, and diagonal checks are implemented with minimal iteration.

3. Edge Case Handling

  • Prevents moves outside the grid or on already occupied cells.
  • Detects draw scenarios after all moves are exhausted.

4. Optimized Logic

  • Logical separation of concerns: Initialization, printing, validation, and game logic.

Conclusion

This implementation demonstrates a clean and efficient solution for the n x n Tic Tac Toe game in Java. It highlights the importance of proper coding standards, handling edge cases, and maintaining clarity in logic — critical for acing coding interviews like Zoho’s.

Let me know your thoughts in the comments. Have you encountered similar challenges in interviews? Let’s discuss!

Picture of aravind16101800@gmail.com

aravind16101800@gmail.com

Leave a Reply

Your email address will not be published. Required fields are marked *