Jan 17, 2025

Tic-Tac-Toe Game with Atmega 256 MicroController

In this blog, I’ll walk you through how I built a Tic-Tac-Toe game using an AVR microcontroller, a 4x3 keypad, and a grid of LEDs. This project combines the basics of embedded programming, game logic, and user interaction to create a fun and interactive game.

1. Overview of the Project

The goal of this project was to create a Tic-Tac-Toe game where players could input their moves using a keypad and see the results displayed on an LED grid. Each move lights up an LED in red or green, depending on the player's turn. The game identifies the winner and celebrates with an animation.

2. Hardware Setup

For this project, I used:

  • ATmega microcontroller (running at 8 MHz)
  • 4x3 Keypad for player input
  • 3x3 LED grid to display the game
  • A few resistors and wires for connections

3. Software Workflow

Step 1: Setting Up the Keypad

The keypad is the primary input device. Each button corresponds to a grid cell (1-9). I used the PORTK and PINK registers to scan the keypad rows and columns.

void initKeypad() {
    DDRK = 0x0F;   // Lower nibble output, upper nibble input
    PORTK |= 0x70; // Enable pull-ups for inputs
}

The keypad() function polls for key presses and debounces inputs to ensure accurate readings.

Step 2: Initializing the LED Grid

The grid is controlled using multiple ports: PORTA, PORTC, PORTD, and PORTG. Each LED represents a cell in the grid, and I assigned specific bits to control them.

void initGrid() {
    DDRA = 0xFF;  // Set PORTA as output
    // Similar setup for other ports
}
Step 3: Game Logic

The core of the game is managing the players' turns and checking for a winner. The grid is represented as a 3x3 array, and each player alternates their turn by pressing a key to light up the respective cell.

void play(int index) {
    int row = (index - 1) / 3;
    int col = (index - 1) % 3;

    if (grid[row][col] == 0) { // If cell is empty
        grid[row][col] = turn; // Mark the cell
        controlLed(row, col, turn, ON);
        turn = (turn == RED) ? GREEN : RED;
    }
}
Step 4: Checking for a Winner

Once a move is made, the checkWinner() function evaluates rows, columns, and diagonals for three matching symbols.

int checkWinner() {
    for (int i = 0; i < 3; i++) {
        if (grid[i][0] == grid[i][1] && grid[i][1] == grid[i][2])
            return grid[i][0];
    }
    // Similar checks for columns and diagonals
    return 0;
}
Step 5: Winning Animation

If a player wins, a simple animation flashes the winning LEDs.

void animation(int winner) {
    for (int i = 0; i < 3; i++) {
        controlLed(0, i, winner, ON);
        _delay_ms(300);
    }
}
ABOUT HACKSLAND

Explorer the world of cyber security. Read some cool articles on System exploitation, Web application hacking, exploit development, malwara analysis, Cryptography etc.

CATEGORIES
SOCIAL