Creating simple computer opponent for tic-tac-toe game

I’m working on a tic-tac-toe project where I need to create a basic computer player. The computer should automatically find an empty spot and place its marker (represented by number 3) when it’s the AI’s turn.

This is for my Java programming course but our instructor got sick and isn’t available to help. I’m really stuck on implementing the aiMove() method at the bottom of my code. Can someone point me in the right direction?

package tictactoe;

public class GameLogic {

    public static int HUMAN = 1;
    public static int COMPUTER = 3;
    static Scanner input = new Scanner(System.in);
    static final int DELAY = 300;

    public static int[][] grid = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };

    public static void main(String[] args) {
        boolean gameRunning = true;

        while (gameRunning) {
            displayGrid(grid);
            humanMove();
            delay(DELAY);
            checkGameState(grid);
            input.reset();
        }
    }

    public static void delay(int milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (Exception e) {
            // ignore
        }
    }

    public static void makeMove(int[][] grid, int row, int col, int symbol) {
        grid[row][col] = symbol;
    }

    public static boolean hasWon(int[][] grid, int symbol) {
        // check rows and columns
        for (int x = 0; x < grid.length; x++) {
            int matches = 0;
            for (int y = 0; y < grid[x].length; y++) {
                if (grid[x][y] == symbol
                    || grid[y][x] == symbol ) {
                    matches++;
                }
            }
            if (matches == grid[x].length)
                return true;
        }
        return false;
    }

    public static int checkGameState(int[][] grid) {
        if (hasWon(grid, HUMAN)) {
            return 1;
        } else if (hasWon(grid, COMPUTER)) {
            return 3;
        } else {
            return 0;
        }
    }

    public static void displayGrid(int[][] grid) {
        System.out.println("======");
        for (int[] line : grid) {
            for (int cell : line) {
                System.out.print(cell + " ");
            }
            System.out.println("");
        }
        System.out.println("======");
        System.out.println("status: " + checkGameState(grid));
    }

    public static void humanMove() {
        char key = input.nextChar();
        switch (key) {
        case 'q':
            makeMove(grid, 0, 0, 1);
            break;
        case 'w':
            makeMove(grid, 0, 1, 1);
            break;
        case 'e':
            makeMove(grid, 0, 2, 1);
            break;
        case 'a':
            makeMove(grid, 1, 0, 1);
            break;
        case 's':
            makeMove(grid, 1, 1, 1);
            break;
        case 'd':
            makeMove(grid, 1, 2, 1);
            break;
        case 'z':
            makeMove(grid, 2, 0, 1);
            break;
        case 'x':
            makeMove(grid, 2, 1, 1);
            break;
        case 'c':
            makeMove(grid, 2, 2, 1);
            break;
        }
    }

    public static int aiMove(int[][] grid) {
        int position[] = {-1, -1};
        for (int row = 0; row < grid.length; row++) {
            for (int col = 0; col < grid[row].length; col++) {
                if (grid(0)) {
                    // need help here
                }
            }
        }
    }
}

Your aiMove method has a syntax error - you wrote grid(0) instead of grid[row][col] == 0. Plus you’re not calling aiMove() in your main loop, so the computer never moves.

Here’s a working fix:

public static void aiMove(int[][] grid) {
    Random rand = new Random();
    int row, col;
    do {
        row = rand.nextInt(3);
        col = rand.nextInt(3);
    } while (grid[row][col] != 0);
    
    makeMove(grid, row, col, COMPUTER);
}

This picks random spots until it finds an empty cell. Way more fun than going top-to-bottom every time. Just remember to call aiMove(grid) in your main game loop after the human move, and add import java.util.Random; at the top.

I see a few problems you need to fix first. Your hasWon method has a logic error - it’s checking both grid[x][y] and grid[y][x] in the same loop, which won’t work for checking rows and columns separately.

For the aiMove method, you’re on the right track with nested loops. Here’s a simple approach:

public static void aiMove(int[][] grid) {
    for (int row = 0; row < grid.length; row++) {
        for (int col = 0; col < grid[row].length; col++) {
            if (grid[row][col] == 0) {
                makeMove(grid, row, col, COMPUTER);
                return; // exit after making one move
            }
        }
    }
}

This makes the AI take the first available spot (left to right, top to bottom).

I changed your method to return void instead of int since you’re not returning anything meaningful. Don’t forget to actually call aiMove(grid) in your main game loop after the human move.

I’ve worked with similar game logic before and this approach works well for a basic opponent. Once you get this running, you can make the AI smarter by adding logic to block the player or go for wins.