Tic-Tac-Toe for the terminal I recently started learning C, and this is my first fairly large (to me) program. It's a basic Tic Tac Toe game for the console. There's no AI, it's just a 2-player game. Is there anything I can improve?

Some problems I've been told elsewhere:


There's no case for tying/drawing.
I should split the place function into two.


I also think it would be better to use global variables for board and player, since they're used so often.

// Tic Tac Toe in C. V1.0 by James 26/05/2019

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdbool.h&gt;

#define SIZE 3

// Draws the board along with rows/cols, numbered.
void draw_board(char board[])
{
    system("clear");
    printf("# 1 2 3\n");

    // Rows
    for (int i = 0, n = 0; i &lt; SIZE; i++)
    {
        // Columns
        printf("%d ", i + 1);
        for (int j = 0; j &lt; SIZE; j++)
        {
            printf("%c ", board[n]);
            n++;
        }
        printf("\n");
    }
}

// Initializes board to '-' characters.
void init_board(char board[])
{
    for (int i = 0; i &lt;  SIZE * SIZE; i++)
    {
        board[i] = '-';
    }
}

// Returns true if the piece was successfully placed,
// false if the position was invalid or already taken.
bool place(char board[], char player)
{
    char posinput[64];

    printf("%c, pick your position (xy, rc): ", player);
    scanf("%s", posinput); // &lt;-- I realise that this is potentially bad, but realistically, 
                           // the user would have to be trying to break something, and
                           // this is just a little program I made for practice.

    int row = (posinput[0] - '0') - 1;
    int col = (posinput[1] - '0') - 1;

    int pos = col + row * SIZE;

    if (pos &gt;= 0 &amp;&amp; pos &lt; SIZE * SIZE)
    {
        if (board[pos] == 'x' || board[pos] == 'o')
            return false;

        board[pos] = player;
        return true;
    }

    return false;
}

// Returns true if there are three of the same chars in a row.
// b = board, p = player. Shortened for readability.
bool check(char b[], char p) 
{
    // Check rows
    if (b[0] == p &amp;&amp; b[1] == p &amp;&amp; b[2] == p)
        return true;
    if (b[3] == p &amp;&amp; b[4] == p &amp;&amp; b[5] == p)
        return true;
    if (b[6] == p &amp;&amp; b[7] == p &amp;&amp; b[8] == p)
        return true;


    // Check columns
    if (b[0] == p &amp;&amp; b[3] == p &amp;&amp; b[6] == p)
        return true;
    if (b[1] == p &amp;&amp; b[4] == p &amp;&amp; b[7] == p)
        return true;
    if (b[2] == p &amp;&amp; b[5] == p &amp;&amp; b[8] == p)
        return true;


    // Check diagonals
    if (b[0] == p &amp;&amp; b[4] == p &amp;&amp; b[8] == p)
        return true;
    if (b[2] == p &amp;&amp; b[4] == p &amp;&amp; b[6] == p)
        return true;

    // If no one won, return false
    return false;
}

int main(void)
{
    char board[SIZE * SIZE];
    char player = 'x';
    init_board(board);

    while (true)
    {
        draw_board(board);

        if (place(board, player))
        {
            if (check(board, player))
                break;

            if (player == 'x')
                player = 'o';
            else
                player = 'x';
        }
    }

    draw_board(board);
    printf("-----------------------------\n");
    printf("Player %c wins!!!\n", player);
    printf("-----------------------------\n");
}
First of all: nice work! It's easy to read and understand.

Program organization

It's very good that you split the task to small functions.
Reading the body of main reveals nicely the overall flow.

Ideas for further improvement:


place does two things: it reads input from user and updates the state of the board. It would be good to separate these logically distinct steps to different functions. A new function, say read_next_move could return boolean just like place, and take parameters board and pointers to x and y, whose values will be used when updating the board state.
The name check is too generic. How about is_game_over or has_player_won.
Printing the winner would be good to move to a dedicated function, as you did with other steps.


Use more constants

The special symbols -, x and o would be good to define as constants.
So that instead of if (board[pos] == 'x' || board[pos] == 'o'),
you could write more descriptively if (board[pos] == PLAYER_X || board[pos] == PLAYER_O), and if ever needed change the values easily.
By the way, in this particular example I would replace the condition with if (board[pos] != AVAILABLE).