/************************************************
This program is a simple tic-tac-toe game.
*************************************************/
#include <stdio.h>
#include <stdlib.h>

/************************************************
 ** PROTOTYPES
 ************************************************/
char** createboard();
void print(char** Board);
int isdraw(char** Board);
char winningmove(char** Board, int i, int j);

/************************************************
 ** MAIN FUNCTION
 ************************************************/
int main() {
  char** Board = createboard();
  char winner = '\0';
  char row;
  char col;
  char turn = 'X';

  while(!winner && !isdraw(Board)) {
    print(Board);

    // Read Move
    printf("Player %c, make your move: ", turn);
    fflush(stdout);
    scanf(" %c %c", &row, &col);

    // Make move if square is free
    int rowind = row - 'A';
    int colind = col - '1';
    if (Board[rowind][colind] == ' ') {
      Board[rowind][colind] = turn;
      if (turn == 'X') {
	turn = 'O';
      } else {
	turn = 'X';
      }
      winner = winningmove(Board, rowind, colind);
    } else {
      printf("Square occupied; try again.\n");
    }
  }

  // Game over - print board & declare finish
  print(Board);
  if (winner == 'X' || winner == 'O') {
    printf("Congratulations %c!\n", winner);
  } else {
    printf("Game ends in a draw.\n");
  }

  return 0;
}

/************************************************
 ** FUNCTION DEFINITIONS
 ************************************************/
// Creates the board with all squares init to ' '
char** createboard() {
  char** B = calloc(3, sizeof(char*));
  for(int i = 0; i < 3; ++i) {
    B[i] = calloc(3, sizeof(char));
  }

  for(int j=0; j < 3; ++j) {
    for(int k=0; k < 3; ++k) {
      B[j][k] = ' ';
    }
  }

  return B;
}

// Prints the board
void print(char** Board) {
  printf(" |1|2|3|\n");
  for(int i = 0; i < 3; ++i) {
    printf("%c|", 'A' + i);
    for(int j = 0; j < 3; ++j) {
      printf("%c|", Board[i][j]);
    }
    printf("\n");
  }
}

// Returns true if the game is a draw
int isdraw(char** Board) {
  for(int i = 0; i < 3; ++i) {
    for(int j = 0; j < 3; ++j) {
      if (Board[i][j] == ' ') {
        // empty square, so game ain't over yet
        return 0;
      }
    }
  }
  // no empty squares, so it's a draw
  return 1;
}

// Returns 'X' if (i,j) was a winning move for X
// Returns 'Y' if (i,j) was a winning move for Y
// Retruns ASCII value 0 otherwise
char winningmove(char** Board, int i, int j) {
  if (Board[i][j] == Board[i][(j+1)%3]
   && Board[i][j] == Board[i][(j+2)%3])
  {
    // got a column
    return Board[i][j];
  }
  else if (Board[i][j] == Board[(i+1)%3][j]
          && Board[i][j] == Board[(i+2)%3][j])
  {
    // got a row
    return Board[i][j];
  }
  else if (i == j && Board[i][j] == Board[(i+1)%3][(j+1)%3]
                  && Board[i][j] == Board[(i+2)%3][(j+2)%3])
  {
    // got the forward diagonal
    return Board[i][j];
  }
  else if (i+j == 2 && Board[i][j] == Board[(i+2)%3][(j+1)%3]
                    && Board[i][j] == Board[(i+1)%3][(j+2)%3])
  {
    // got the reverse diagonal
    return Board[i][j];
  }
  else {
    // got nothing
    return 0;
  }
}