0

I'm trying to make a tic-tac-toe game and I'm using a separate method that would update the board after each turn. However, I can't seem to be able to access the 2D array board, which was initialised in main(). I've tried making it public, like you would in Java, but it doesn't seem to work. Any help would be greatly appreciated.

#include <stdio.h>
#include <stdlib.h>

#define public
#define static
#define private static

int main(void) {
    public char board[5][8] = { "  |  |  ", "--+--+--", "  |  |  ", "--+--+--", "  |  |  " };
    int turn = 0;
    public static int base = 0;

    for (size_t row = 0; row < sizeof(board) / sizeof(board[0]); row++) {
        for (size_t col = 0; col < sizeof(board[0]) / sizeof(board[0][0]); col++)
            printf("%c", board[row][col]);
        printf("\n");
    }

    printf("Player1's turn\n ");
    fflush(stdout);
    scanf("%i", &turn);
    updateBoard(&turn);
}

void updateBoard(int a){
    switch (a) {
        case 1:
            board[0][0] = 'X';
            break;

        case 2:
            board[0][4] = 'X';
            break;

        case 3:
            board[0][6] = 'X';
            break;

        case 4:
            board[2][0] = 'X';
            break;

        case 5:
            board[2][4] = 'X';
            break;

        case 6:
            board[2][6] = 'X';
            break;

        case 7:
            board[4][0] = 'X';
            break;

        case 8:
            board[4][4] = 'X';
            break;

        case 9:
            board[4][6] = 'X';
            break;

        default:
            printf("Please input a correct value (1-9)");
        }

    for (size_t row = 0; row < sizeof(board) / sizeof(board[0]); row++) {
        for (size_t col = 0; col < sizeof(board[0]) / sizeof(board[0][0]); col++)
            printf("%c", board[row][col]);
        printf("\n");
    }

    base = 1;
}
3
  • 2
    send board as an argument for the function updateBoard. Commented Sep 3, 2021 at 16:23
  • Or declare it "globally" outside of the main function. Commented Sep 3, 2021 at 16:32
  • 3
    #define private static seems bad. static has multiple meanings in c. It can either mean "scope to this translation unit (eg *.c file) only" if it is on a declaration outside the scope of a function, and inside a function scope it means (simplifying) "retain the value of this variable on repeated calls of this function." Also by doing #define static, you could be breaking a lot of things without even knowing it, eg if the header files have static in them anywhere. Commented Sep 3, 2021 at 16:37

1 Answer 1

1

The simplest solution is to declare board (and base, assuming it will be used for something in the future) at file scope, often referred to as "global scope":

static int base = 0;
static char board[5][9] = { "  |  |  ", "--+--+--", "  |  |  ", "--+--+--", "  |  |  " };

void updateBoard(int a);

int main(void)
{
    int turn = 0;

    // ...

They are declared static, meaning that they will only be visible to code within this file, and cannot be accessed from other files of the same program.
I have removed the #define's. The keywords public and private do not exist in C; they are generally only used in languages which support object-oriented (or class-based) programming. The keyword static does exist, but has a different meaning depending on the context. It is best not re-defined.
Note that the second dimension should be 9: 8 characters and 1 null-terminator.

The downside of having variables at file scope is that they are visible in the entire file, and with multiple functions modifying their contents it can become difficult to oversee and reason about the behavior of the program.

Perhaps the best solution is to keep board and base declared in main, and to pass them to updateBoard. Although this immediately introduces some more advanced C-concepts. Adding the necessary additional arguments/parameters to the function prototype and function call is probably familiar to you. The problem is that array arguments convert to pointers (see here, often called "array-to-pointer decay"). This means that sizeof no longer provides the size of the entire array, but the size of the pointer to the first element of the array. In the solution below, this is resolved by obtaining the dimensions once in main, storing these in variables and passing these values to the function. This is, arguably, a better solution than using the sizeof calculation everywhere. And once the variables are set, this will work with dynamically allocated arrays as well.

// Forward declaring the function, so main knows it exists
void updateBoard(char board[5][9], size_t nRows, size_t nCols, int base, int a);

int main(void)
{
    int base = 0;

    // Note the 9 for the second dimension
    char board[5][9] = { "  |  |  ", "--+--+--", "  |  |  ", "--+--+--", "  |  |  " };
    int turn = 0;

    // Initializing the variables for the dimensions...
    size_t nRows = sizeof(board) / sizeof(board[0]);
    size_t nCols = sizeof(board[0]) / sizeof(board[0][0]);

    // ...which we can now use here as well...
    for (size_t row = 0; row < nRows; row++) {
        for (size_t col = 0; col < nCols; col++)
            printf("%c", board[row][col]);
        printf("\n");
    }
    printf("Player1's turn\n ");
    fflush(stdout);
    scanf("%i", &turn);

    // ... and here, along with passing board and base.
    updateBoard(board, nRows, nCols, base, turn);
}

void updateBoard(char board[5][9], size_t nRows, size_t nCols, int base, int a){
    switch (a) {
        // ... code omitted for brevity ...
    }

    // Use the passed dimension values here
    for (size_t row = 0; row < nRows; row++) {
        for (size_t col = 0; col < nCols; col++)
            printf("%c", board[row][col]);
        printf("\n");
    }
    base = 1;
}

With passing variables like this, there is an important distinction between passing variables by reference and passing them by value. Perhaps this is a good next topic to look into on your C journey, along with static and "string literal"/"null-terminator".

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.