im trying to make a sort of minesweeper clone in c, but i cant figure out how to create a variable length array member of a struct and initialize it.
my struct definitions
typedef struct Cell
{
Rectangle area; // The area the cell covers
bool hasMine; // If the cell covers a mine
bool covered; // If the cell is currently covered
int touching; // How many mines the cell is touching
} Cell;
typedef struct Minefield
{
int columns; // The amount of columns
int rows; // The amount of rows
int mines; // The amount of mines
Cell field[]; // An array of columns*rows Cells
} Minefield;
how im creating new instances of a Minefield
Minefield NewGame(int columns, int rows, int mines)
{
int i = 0;
Cell cells[columns*rows];
for (i=0; i < columns*rows; i ) {
int x = 0;
int y = 0;
if (i == 0) {
Rectangle area = (Rectangle){0, 0, cellsize, cellsize};
cells[i] = (Cell){area, false, true, 0};
}
else {
Cell previous = cells[i-1];
x = previous.area.x cellsize;
y = previous.area.y cellsize;
Rectangle area = (Rectangle){x, y, cellsize, cellsize};
cells[i] = (Cell){area, false, true, 0};
}
}
Minefield field = (Minefield){columns, rows, mines, cells};
return field;
}
im new to c, ive done some googling and ive come across some very similar questions, but i cant really understand them or the examples they give. i think you can do what my errendous code is trying to do (or something very similar) with a gcc extension, but i want my code to be portable. how can i have a struct have an unknown size array member?
CodePudding user response:
Yes, it's called flexible array member
. It's usually used with dynamically allocated objects. However, you cannot return Minefield
by value. The compiler will copy only sizeof(Minefield)
data what is the size of object if length of array Minefield::field
was 0
.
You can do:
Minefield* NewGame(int columns, int rows, int mines)
{
Cell cells[columns*rows];
...
// allocate memory for Minefield and cells array just after it
Minefield* minefield = malloc(sizeof(*minefield) sizeof cells);
if (!minefield) { ... error handling ... }
// set normal fields using compund literal
*minefield = (Minefield){columns, rows, mines};
// copy cells `array` to `minefield->field` array
memcpy(minefield->field, cells, sizeof cells);
return minefield;
}
The memcpy
can be avoided by first allocating Minefield
and writing directly to field
member.
Minefield* NewGame(int columns, int rows, int mines)
{
Minefield* minefield = malloc(sizeof(Minefield) rows * columns * sizeof(Cell));
if (!minefield) { ... error handling ... }
*minefield = (Minefield){columns, rows, mines};
Cell *cells = minefield->field;
...
return minefield;
}
CodePudding user response:
Unfortunately, C doesn't have any built-in dynamic array like python. However, if you want to use some dynamic array either you can implement your self or you can see the answer to that link C dynamically growing array which explains that you need to have starting array with a default size, and then you can increase the size of the array which depends on your algorithm. After you import that header file provided by @casablance, you can simply use it for your minesweeper game.