Search code examples
cmultidimensional-arraystructvoid-pointers

How can i fill and then display this void*** matrix in C?


Context: I need to create a board game with a 2D array using void***, in each slot i have to initially put a Struct "Tierra" and then in later turns i can put a Struct "Bomba"

The 2D array is a global variable, and i kinda have something

Here is the struct Tierra:

typedef struct Tierra{
    int vida; // random health (1-3)
    int es_tesoro; // 1 or 0 (5% chance of having a treasure)
} Tierra;

Here is the function to create the array, this function can only recieve dimension as a parameter and has to be void():

void*** tablero;
int dimension;
const int chance[5]={1,2,3,4,5};

void IniciarTablero(int n){
    tablero = malloc(n*sizeof(void**));
    if(tablero == NULL){
        printf("%s", "error con la memoria \n");
        exit(1);
    }   
    for( int i=0 ; i<n ; i++){
        tablero[i] = malloc(n*sizeof(void*));
        if (tablero[i] == NULL){
            printf("%s", "error con la memoria \n");
            exit(1);
        }
        for( int j=0 ; j<n ; j++){
            Tierra* tierra;
            tierra->vida = (rand() % 3) + 1;
            int probabilidad = (rand() % 100);
            int contenido = 0;
            for (int c=0 ; c<5 ; c++){
                if(probabilidad==chance[c]){
                    contenido = 1;
                }
            }
            tierra->es_tesoro = contenido;
            tablero[i][j] = tierra;
        }
    }
}

and here is my function to display it:

void MostrarTablero(){
    for (int i=0 ; i<dimension ; i++){
        for (int j=0 ; j<dimension ; j++){
            Tierra* imprimir = (Tierra*)tablero[i][j];
            printf("%d | ",imprimir->vida);
        }
        printf("\n");
    }
    return;
}

Whenever i try calling IniciarTablero() and then MostrarTablero in main, it gives me Segmentation Fault error, and it doesn't even get in MostrarTablero(). I think the problem might be in how i give a value to tablero[i][j] but i'm new in c and i don't know how to use pointers yet.

Thank you in advance and hope you have a good day/night. <3


Solution

  • As commented by @paddy, you should not use void * as a pointer type in this case. Besides you are not allocating the memory for each entity of struct Tierra.
    Would you please try instead:

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    typedef struct Tierra {
        int vida; // random health (1-3)
        int es_tesoro; // 1 or 0 (5% chance of having a treasure)
    } Tierra;
    
    Tierra ***tablero;
    int dimension;
    const int chance[5] = {1, 2, 3, 4, 5};
    
    void IniciarTablero(int n)
    {
        tablero = malloc(n * sizeof(Tierra ***));
        for (int i = 0; i < n; i++) {
            tablero[i] = malloc(n * sizeof(Tierra **));
            for (int j = 0; j < n; j++) {
                Tierra *tierra = malloc(sizeof(Tierra));    // missing in the original code
                tierra->vida = (rand() % 3) + 1;
                int probabilidad = (rand() % 100);
                int contenido = 0;
                for (int c = 0; c < 5; c++) {
                    if (probabilidad == chance[c]) {
                        contenido = 1;
                    }
                }
                tierra->es_tesoro = contenido;
                tablero[i][j] = tierra;
            }
        }
    }
    
    void MostrarTablero()
    {
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j < dimension; j++) {
                Tierra *imprimir = tablero[i][j];
                printf("%d | ", imprimir->vida);
            }
            printf("\n");
        }
    }
    
    int main()
    {
        dimension = 4;              // just for example
        IniciarTablero(dimension);
        MostrarTablero();
    
        // don't forget to free() memory after use
    
        return 0;
    }
    

    Please note it is omitted to check the return values of malloc() just for simplicity to focus on the essentials.

    Btw if the value dimension is fixed (not dynamically assigned), it will be better to use simple 2-D array of struct Tierra.