Find Winner on a Tic Tac Toe Game

🏠 ⬅️ ➑️

Tic-tac-toe is played by two players A and B on a 3 x 3 grid. The rules of Tic-Tac-Toe are:

  • Players take turns placing characters into empty squares ' '.
  • The first player A always places 'X' characters, while the second player B always places 'O' characters.
  • 'X' and 'O' characters are always placed into empty squares, never on filled ones.
  • The game ends when there are three of the same (non-empty) character filling any row, column, or diagonal.
  • The game also ends if all squares are non-empty.
  • No more moves can be played if the game is over.

Given a 2D integer array moves where moves[i] = [rowi, coli] indicates that the ith move will be played on grid[rowi][coli]. return the winner of the game if it exists (A or B). In case the game ends in a draw return "Draw ". If there are still movements to play return "Pending ".

You can assume that moves is valid (i.e., it follows the rules of Tic-Tac-Toe), the grid is initially empty, and A will play first.

Example 1:

Input: moves = [[0,0],[2,0],[1,1],[2,1],[2,2]] Output: "A " Explanation: A wins, they always play first.

Example 2:

Input: moves = [[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]] Output: "B " Explanation: B wins.

Example 3:

Input: moves = [[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]] Output: "Draw " Explanation: The game ends in a draw since there are no moves to make.

Constraints:

  • 1 <= moves.length <= 9
  • moves[i].length == 2
  • 0 <= rowi, coli <= 2
  • There are no repeated elements on moves.
  • moves follow the rules of tic tac toe.

Note: This problem is from LeetCode.
❌ Compiled
❌ Executed
❌ Correct
program tictactoe
    implicit none

    integer :: i, j, k, l, m, n
    integer :: moves(9, 2)
    character(len=1) :: grid(3, 3)
    character(len=1) :: winner

    ! Examples
    moves(:, :) = reshape([&
        & [0, 0], [2, 0], [1, 1], [2, 1], [2, 2],&
        & [0, 0], [1, 1], [0, 1], [0, 2], [1, 0], [2, 0]], shape(moves))

    do i = 1, size(moves, 1)
        call solve(moves(i, :), grid, winner)
        write(*, *) 'Move ', i, ':', moves(i, :)
        write(*, *) 'Grid:'
        do j = 1, size(grid, 1)
            write(*, '(3A)') ((grid(j, k), k = 1, size(grid, 2)), new_line(''))
        end do
        write(*, *) 'Winner: ', winner
    end do

contains

    subroutine solve(move, grid, winner)
        implicit none
        integer, intent(in) :: move(2)
        character(len=1), intent(inout) :: grid(3, 3)
        character(len=1), intent(out) :: winner

        integer :: row, col
        logical :: found

        row = move(1)
        col = move(2)

        if (grid(row, col) /= ' ') then
            stop 'Invalid move'
        end if

        grid(row, col) = 'X'

        found = .false.
        do i = 1, size(grid, 1)
            if (all(grid(i, :) == 'X')) then
                winner = 'A'
                found = .true.
                exit
            else if (all(grid(:, i) == 'X')) then
                winner = 'A'
                found = .true.
                exit
            end if
        end do

        if (.not. found) then
            do i = 1, size(grid, 1) - 2
                if (grid(i, i) == 'X' .and. grid(i + 1, i + 1) == 'X' .and. grid(i + 2, i + 2) == 'X') then
                    winner = 'A'
                    found = .true.
                    exit
                else if (grid(i, i) == 'X' .and. grid(i + 1, i + 1) == 'X' .and. grid(i + 2, i + 2) == 'X') then
                    winner = 'A'
                    found = .true.
                    exit
                end if
            end do
        end if

        if (.not. found) then
            do i = 1, size(grid, 1)
                if (all(grid(i, :) == 'O')) then
                    winner = 'B'
                    found = .true.
                    exit
                else if (all(grid(:, i) == 'O')) then
                    winner = 'B'
                    found = .true.
                    exit
                end if
            end do
        end if

        if (.not. found) then
            do i = 1, size(grid, 1) - 2
                if (grid(i, i) == 'O' .and. grid(i + 1, i + 1) == 'O' .and. grid(i + 2, i + 2) == 'O') then
                    winner = 'B'
                    found = .true.
                    exit
                else if (grid(i, i) == 'O' .and. grid(i + 1, i + 1) == 'O' .and. grid(i + 2, i + 2) == 'O') then
                    winner = 'B'
                    found = .true.
                    exit
                end if
            end do
        end if

        if (.not. found) then
            if (all
❌ Compiled
❌ Executed
❌ Correct
PROGRAM TIC_TAC_TOE
  IMPLICIT NONE

  INTEGER, PARAMETER :: N = 3
  INTEGER, DIMENSION(N, N) :: grid
  INTEGER, DIMENSION(N, N) :: moves
  INTEGER :: i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
  INTEGER :: row, col
  INTEGER :: count
  INTEGER :: winner

  ! Initialize the grid
  grid = 0

  ! Read the moves
  DO i = 1, SIZE(moves, DIM=1)
    row = moves(i, 1)
    col = moves(i, 2)
    grid(row, col) = i
  END DO

  ! Check for a winner
  winner = 0
  DO i = 1, N
    ! Check rows
    count = 0
    DO j = 1, N
      IF (grid(i, j) /= 0) THEN
        count = count + 1
        IF (count == 3) THEN
          winner = grid(i, j)
          EXIT
        END IF
      END IF
    END DO
    IF (winner /= 0) EXIT

    ! Check columns
    count = 0
    DO j = 1, N
      IF (grid(j, i) /= 0) THEN
        count = count + 1
        IF (count == 3) THEN
          winner = grid(j, i)
          EXIT
        END IF
      END IF
    END DO
    IF (winner /= 0) EXIT

    ! Check diagonals
    count = 0
    DO j = 1, N
      IF (grid(j, j) /= 0) THEN
        count = count + 1
        IF (count == 3) THEN
          winner = grid(j, j)
          EXIT
        END IF
      END IF
    END DO
    IF (winner /= 0) EXIT

    count = 0
    DO j = 1, N
      IF (grid(j, N-j+1) /= 0) THEN
        count = count + 1
        IF (count == 3) THEN
          winner = grid(j, N-j+1)
          EXIT
        END IF
      END IF
    END DO
    IF (winner /= 0) EXIT
  END DO

  ! Check for a draw
  IF (winner == 0) THEN
    count = 0
    DO i = 1, N
      DO j = 1, N
        IF (grid(i, j) == 0) THEN
          count = count + 1
        END IF
      END DO
    END DO
    IF (count == 0) winner = -1
  END IF

  ! Print the winner
  IF (winner == 1) THEN
    PRINT *, "A "
  ELSE IF (winner == 2) THEN
    PRINT *, "B "
  ELSE IF (winner == -1) THEN
    PRINT *, "Draw "
  ELSE
    PRINT *, "Pending "
  END IF

END PROGRAM TIC_TAC_TOE
🌐 Data from online sources
def validateBinaryTreeNodes(n, leftChild, rightChild):
    parent = [-1] * n
    for i in range(n):
        if leftChild[i] != -1:
            if parent[leftChild[i]] != -1:
                return False
            parent[leftChild[i]] = i
        if rightChild[i] != -1:
            if parent[rightChild[i]] != -1:
                return False
            parent[rightChild[i]] = i

    root = -1
    for i in range(n):
        if parent[i] == -1:
            if root != -1:
                return False
            root = i

    return root != -1
  1. Create an array parent to keep track of the parent of each node. Initialize each element to -1.
  2. Iterate through each node i: a. Check the left child of i. If it's not -1, check if it already has a parent. If it does, return false (two parents for a node makes it an invalid tree). Set the parent of the left child to i. b. Do the same for the right child.
  3. Iterate through the parent array to find a node without a parent (root). If a root is found and another node without a parent is found later, return false (more than one tree).
  4. If a root is found, return true (a valid tree). Otherwise, return false (no tree found).
🌐 Data from online sources
bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
    vector<int> parent(n, -1);
    for (int i = 0; i < n; ++i) {
        if (leftChild[i] != -1) {
            if (parent[leftChild[i]] != -1) return false;
            parent[leftChild[i]] = i;
        }
        if (rightChild[i] != -1) {
            if (parent[rightChild[i]] != -1) return false;
            parent[rightChild[i]] = i;
        }
    }
    int root = -1;
    for (int i = 0; i < n; ++i) {
        if (parent[i] == -1) {
            if (root != -1) return false;
            root = i;
        }
    }
    return root != -1;
}
  1. Create an array parent to keep track of the parent of each node. Initialize each element to -1.
  2. Iterate through each node i: a. Check the left child of i. If it's not -1, check if it already has a parent. If it does, return false (two parents for a node makes it an invalid tree). Set the parent of the left child to i. b. Do the same for the right child.
  3. Iterate through the parent array to find a node without a parent (root). If a root is found and another node without a parent is found later, return false (more than one tree).
  4. If a root is found, return true (a valid tree). Otherwise, return false (no tree found).