Minefieldin C matrix [duplicate] - c

This question already has an answer here:
Minesweeper revealing cells in C
(1 answer)
Closed 1 year ago.
I want to make a minefield. First I made a matrix, asked the user to enter with the rows and columns.
I need to:
put the bombs
indicate the amount of bombs nearby.
#include <stdio.h>
#include <stdlib.h>
int main(){
int rows, columns, i, j, bombs, **matrix;
printf("\Enter the rows: ");
scanf("%d", &rows);
printf("Enter the columns:");
scanf("%d", &columns);
printf("Enter the bombs:");
scanf("%d", &bombs);
if (bombs>= (rows*colums)){
printf("Error");
}
if (bombs<= 0){
printf("Error);
}
for (i = 0; i < rows; i++){
for (j = 0; j < columns; j++){
matrix[i][j] = rand() % 10;
}
}
// show the map //
for (i = 0; i < rows; i++){
for (j = 0; j < columns; j++) {
printf("%d", matrix[i][j]);
}
printf("\n\n");
}
return 0;
}
``

Data Structures
Instead of using an int then remembering magical numbers like -1 indicates a mine, it's more natural to say what these mean explicitly. Then you can change your mind or add to it without worrying about rewriting your whole programme. In the whole minefield, it's useless to have int **m without cols and rows. This interdependence is a sign that you should also package them in a structure to pass as one variable.
struct tile { unsigned nearby : 4, is_mine : 1, is_revealed : 1; };
struct map { size_t x, y; struct tile **tile; };
These definitions are very similar to what you had before, but they express the intent of the code much better.
Arrays
I would forget your complicated alocMatrix and just use one allocation, but then you have to use tiles[y * map->x + x]. Personal preference; I think it's easier to have a constructor that returns one allocated block.
struct map { size_t x, y; struct tile *tile; };
...
if(!(map = malloc(sizeof *map + sizeof *tile * x * y)))
{ if(!errno) errno = ERANGE; return 0; }
...
map->tile = (struct tile *)(map + 1);
memset(map->tile, 0, sizeof *tile * x * y);
Mines
A method of laying mines uniformly at random is to repeatedly choose a random tile, throwing out the tiles you've seen. Another method is to visit all the tiles and calculate the probability of each, P(mines left / tiles left). It depends on the number of mines which will be faster.
const size_t x1 = map->x, y1 = map->y;
size_t x, y, squares = x1 * y1;
assert(map && mines < squares);
for(x = 0; x < x1; x++) {
for(y = 0; y < y1; y++) {
struct tile *tile = &map->tile[y * x1 + x];
tile->is_revealed = 0;
tile->is_mine = rand() < RAND_MAX / squares * mines;
mines -= tile->is_mine;
squares--;
}
}
for(x = 0; x < x1; x++) for(y = 0; y < y1; y++)
map->tile[y * x1 + x].nearby =
(x && y && map->tile[(y-1) * x1 + (x-1)].is_mine) +
...
(x && y < y1 - 1 && map->tile[(y+1) * x1 + (x-1)].is_mine);

How about using this function to place the bombs? Call it by passing the address of m. Keep in mind that marking the rest of the squares with the appropriate number has to happen after the bombs have been placed (and it shouldn't depend on a call to rand). Also, the map has to be initialized to avoid surprises.
void placeBombs(int*** map, int numOfRows, int numOfColumns, int numOfBombs)
{
while (numOfBombs > 0) {
int column = rand() % numOfColumns;
int row = rand() % numOfRows;
if ((*map)[row][column] != -1) {
(*map)[row][column] = -1;
--numOfBombs;
}
/* Else, if a bomb already exists in the cell,
* we iterate without placing a bomb
*/
}
}

Related

Am I initializing correctly the state of a matrix in C language?

I'm simulating a square surface that "traps" molecules in C and, I don't know if it's correctly initialized. I want in the beginning of the whole simulation that the grid is totally empty (without any molecule on it) so that it can start to trap the mentioned molecules.
But, when I generate randomly the coordinates of an entry and start checking if the lattice is empty ( to attempt adding molecules to it later on), it seems that every entry the program choose is already "occupied" and I can't see why since I haven't added anything so far.
The following is my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//define the dimensions of the latice
#define xmax 2
#define ymax 2
//Define parameters to obtain both the x and y coordinates of a site in the lattice at random
#define LOWER 0
#define UPPER xmax-1
#define ALTO ymax-1
#define CONTAR 1
//we define the Monte Carlo steps
#define MCSS 100
//define the "empty" and "occupied" states
#define empty 0
#define occupied 1
//define the grid or lattice we will working with
int grid[xmax][ymax];
//Function that selects the x-coordinate of the chosen site randomly
int printrandomx(int lower, int upper, int cuenta)
{
int m, num1;
for (m = 0; m < cuenta ; m++) {
num1 = (rand() % (upper - lower + 1)) + lower;
}
return num1;
}
//Function that selects the y-coordinate of the chosen site randomly
int printrandomy(int bajo, int alto, int contar)
{
int n,num2;
for (n = 0; n < contar; n++) {
num2 = (rand() % (alto - bajo + 1)) + bajo;
}
return num2;
}
//Function that generates the random coordinates of a site in the lattice
int generate_coords(int red[xmax][ymax]){
int x_coord, y_coord;
int count = 1;
for (int i = 0; i < xmax; i++) {
for (int j = 0; j < ymax; j++) {
red[i][j] = count++;
printf("%d ", red[i][j]);
}
printf("\n");
}
x_coord = printrandomx(LOWER, UPPER, CONTAR);
y_coord = printrandomy(LOWER, ALTO, CONTAR);
printf("(x,y)=(%d,%d)\n\n", y_coord, x_coord);
for (int i = 0; i < xmax; i++)
{
for (int j = 0; j < ymax; j++ )
{
if(x_coord == i && y_coord == j){
red[y_coord][x_coord] == count;
}
}
}
printf("The coordinates are (%d,%d) and the solicited matrix entry is: %d\n\n", y_coord, x_coord, grid[y_coord][x_coord]);
if (x_coord > xmax || x_coord < 0 || y_coord > ymax || y_coord < 0) {
printf ("Invalid coordinates given\n");
return 1;
}
}
//Here starts the main function
int main(){
srand(time(0));
int N = xmax*ymax;
int x = 0, y = 0;
// Initialize lattice to be empty
for (int i = 0; i < xmax; i++) {
for (int j = 0; j < ymax; j++) {
grid[j][i] = empty;
}
}
//LOCATE AN ENTRY OF THE MATRIX RANDOMLY
generate_coords(grid);
//EVALUATE IF THE CHOSEN SITE IS EITHER EMPTY OR OCCUPIED
printf("IS IT OCCUPIED???\n\n");
if (grid[y][x] == empty){
printf("It's empty. Let's fill it with a molecule\n\n");
printf("Here I will specify other conditions :)\n\n");
}else{
printf("It's occupied, the trial ends. Choose another site again\n\n");
generate_coords(grid);
}
return 0;
}
The chunk of the code that must set the initial array as empty is the following:
// Initialize lattice to be empty
for (int i = 0; i < xmax; i++) {
for (int j = 0; j < ymax; j++) {
grid[j][i] = empty;
}
}
However, it seems doesn't work and I don't know why.
Yes, you are doing it right. In this case it's a global variable so it's already initializes and you overwrite all the values in generate_coords() so it doesn't really matter.
As grid is a global variable it's implicitly zero initialized. You don't have to do anything. I recommend you avoid global variables, though, it makes your code harder to change.
If grid was a local variable (recommended) you can zero initialize it because xmax and ymax are constants:
int grid[xmax][ymax] = { 0 };
If grid xmax and ymax are variables (opposed to constants), grid would be a vla, and you now assign values to it with memset() (or memcpy() etc):
memset(grid, 0, sizeof grid);
Or, as you did, an double loop. Consider using more descriptive index variables, in this case, perhaps x and y?
for (size_t x = 0; x < xmax; x++) {
for (size_t y = 0; y < ymax; y++) {
grid[x][y] = empty;
}
}
That answers the question you asked, however, I don't know wat question you meant to ask.
I refactored your code which will probably be surprising to you. Left out most of the printf() calls as they x and y when accessing the grid. Also left out the 2nd call to generate_corrds() as it seems like you wanted to run part of main() in a loop anyways.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define xmax 2
#define ymax 2
int rand_min_max(int min, int max) {
return rand() % (max - min) + min;
}
void grid_print(int grid[xmax][ymax]) {
for (int x = 0; x < xmax; x++)
for (int y = 0; y < ymax; y++)
printf("%d%s", grid[x][y], y + 1 < ymax ? " " : "\n");
}
void generate_coords(int grid[xmax][ymax]) {
memcpy(grid, (int [xmax][ymax]) {{1,2}, {3,4}}, sizeof(int [xmax][ymax]));
int x = rand_min_max(0, xmax);
int y = rand_min_max(0, ymax);
grid[x][y] = xmax + ymax + 1; // x and y swapped in original code, doesn't matter here but if xmax != ymax it would matter.
}
int main() {
srand(time(0));
int grid[xmax][ymax];
generate_coords(grid);
grid_print(grid);
printf("IS IT OCCUPIED???\n\n");
printf("It's occupied, the trial ends. Choose another site again\n\n");
}
and here is sample output:
1 5
3 4
IS IT OCCUPIED???
It's occupied, the trial ends. Choose another site again

Game of Life problem with board update function in C

I need help with my Game of Life implementation in C. Other posts on Stackoverflow lead me to believe that my problem was to do with dangling pointers, but after modifying my program to use a global 2D array for the game grid instead of passing it to functions which return new 2D arrays, I realized that it was a problem with my update function.
I have tried hard-coding a number of simple patterns, including gliders and oscillators, and the grid doesn't update correctly. The patterns do update the same way every time the program is run, so I don't think it's a problem of uninitialized memory causing problems. I also know that there are no cells which contain values greater than 1. Therefore, the problem must lie in my mechanisms for updating the grid.
Can someone help me find the problem? I can't find anything wrong with my code and I believe I have programmed the rules correctly.
Here are my neighbors and update functions, along with the relevant variable and constant declarations.
#define MAX_Y 10 /* height */
#define MAX_X 30 /* width */
int grid[MAX_Y][MAX_X];
int neighbors(int x, int y) {
int dx, dy, dstx, dsty;
int n = 0;
for (dy = -1; dy <= 1; ++dy) {
for (dx = -1; dx <= 1; ++dx) {
dsty = y + dy;
dstx = x + dx;
if (dsty >= 0 && dsty < MAX_Y && dstx >= 0 && dstx < MAX_X)
n += !!grid[dsty][dstx]; /* use !! so that non-zero values eval to 1 */
}
}
/* (n > 0) ? printf("Point (%d,%d) has %d neighbors!\n", x, y, n) : 0; */
return n;
}
void update(void) {
int new[MAX_Y][MAX_X];
memset(new, 0, sizeof(int) * MAX_Y * MAX_X);
int i, j, n;
for (i = 0; i < MAX_Y; ++i) {
for (j = 0; j < MAX_X; ++j) {
n = neighbors(i, j);
/* alive, 2 or 3 neighbors -> alive!
* dead, 3 neighbors -> alive!
* anything else -> dead :(
*/
if (grid[i][j] && (n == 2 || n == 3))
new[i][j] = 1;
else if (!grid[i][j] && n == 3)
new[i][j] = 1;
else
new[i][j] = 0;
}
}
memcpy(grid, new, sizeof grid);
}
In your neighbors function, you need to think carefully about the loop iteration where dx and dy are both zero. Conway's Game of Life does not consider a cell to be neighbor of itself, so you need to avoid counting it.
You're also confusing yourself by using the letters i and j. You're allowing j to go all the way up to MAX_X, but then you are using j as the y coordinate when you call neighbors, so that will cause overflows and incorrect calculations. (Starting with the easier case of a 10x10 grid would sometimes save you from bugs like this.)
You should adjust the neighbors() function to omit the cell itself.
Here is a modified version:
#define MAX_Y 10 /* height */
#define MAX_X 30 /* width */
unsigned char grid[MAX_Y][MAX_X];
int neighbors(int x, int y) {
int n = -!!grid[y][x];
for (int dy = -1; dy <= 1; ++dy) {
for (int dx = -1; dx <= 1; ++dx) {
int dsty = y + dy;
int dstx = x + dx;
if (dsty >= 0 && dsty < MAX_Y && dstx >= 0 && dstx < MAX_X && grid[dsty][dstx])
n++;
}
}
return n;
}
void update(void) {
int new[MAX_Y][MAX_X] = { 0 };
for (int y = 0; y < MAX_Y; ++y) {
for (int x = 0; x < MAX_X; ++x) {
int n = neighbors(y, x);
/* alive, 2 or 3 neighbors -> alive!
* dead, 3 neighbors -> alive!
* anything else -> dead :(
*/
new[y][x] = (grid[y][x] && n == 2) || n == 3;
}
}
memcpy(grid, new, sizeof grid);
}
The neighbors() function can be simplified with fewer tests:
int neighbors(int x, int y) {
int n = -(grid[y][x] != 0);
int x1 = x - (x > 0);
int x2 = x + (x < MAX_X - 1);
int y1 = y - (y > 0);
int y2 = y + (y < MAX_Y - 1);
for (y = y1; y <= y2; y++) {
for (x = x1; x <= x2; x++) {
n += grid[y][x] != 0;
}
}
return n;
}

What is wrong with my breadth first search algorithm, it crashes with a segmentation fault?

When I run my code it throws a segmentation fault and I have tried rewriting the code several times. Still to no avail, it won't even run. The segmentation fault happens as soon as my program is launched. What it's supposed to do is print a path on screen using the ncurses library in Linux, from the given coordinates. Here is the problematic snippet with the lines where gdb said the segmentation fault was, also it (snippet) reproduces the problem.
EDIT: This will help explain what I'm trying to do, but using dynamic arrays. Breadth First Search
EDIT 2: The variable frontier is supposed to keep track of the X and Y values at a specific index. The add_neighbors function is there to add all four neighbors (providing they aren't already added) to the frontier and came_from arrays.
frontier[index][0] is X value.
frontier[index][1] is Y value.
The before the first while loop I set the start position x1 and y1. During the first while loop, it increments getting the new coordinates from the frontier, then processing and adding to came_from array.
For example:
(x1,y1) (x1+1,y1)
(x1,y1+1) (x1+1,y1+1)
(x1,y2) (x2,y2)
I'm trying to get from (x1,y1) to (x2,y2). Sure hope that explains it better. What I'm trying to implement is a Breadth First Search (BFS) algorithm. Using two arrays, one is frontier (keeps track of visited positions) and came_from (keeps track of X and Y the path from x1,y1 to x2,y2). Updated the code to reflect the first answer. Plus added a comment to explain where the error might be, not really sure but I've been debugging it. It looks like the came_from array never gets set with x and y.
The Code:
/*
* pathfind.c - Simple Breadth First Search algorithm implementation.
*
* Author: Philip R. Simonson
* Date : 05/17/2021
*
****************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ncurses.h>
#define MAXHEIGHT 24
#define MAXWIDTH 80
/* Add neighboring positions to the arrays.
*/
int add_neighbors(int **frontier, int ***came_from, int count, int x, int y)
{
// North
if(y > 0 && came_from[y - 1][x][0] < 0) {
frontier[count][0] = x;
frontier[count][1] = y;
count++;
came_from[y - 1][x][0] = x;
came_from[y - 1][x][1] = y;
}
// South
if(y < MAXHEIGHT-1 && came_from[y + 1][x][0] < 0) {
frontier[count][0] = x;
frontier[count][1] = y;
count++;
came_from[y + 1][x][0] = x;
came_from[y + 1][x][1] = y;
}
// West
if(x > 0 && came_from[y][x - 1][0] < 0) {
frontier[count][0] = x;
frontier[count][1] = y;
count++;
came_from[y][x - 1][0] = x;
came_from[y][x - 1][1] = y;
}
// East
if(x < MAXWIDTH-1 && came_from[y][x + 1][0] < 0) {
frontier[count][0] = x;
frontier[count][1] = y;
count++;
came_from[y][x + 1][0] = x;
came_from[y][x + 1][1] = y;
}
return count; // Return counter for frontier
}
/* Simple BFS algorithm for path finding.
*/
void path_finding(int x1, int y1, int x2, int y2)
{
int **frontier, ***came_from;
int index, count;
int i, j;
index = 0;
count = 0;
// Initialise frontier array
frontier = malloc(sizeof(int *) * MAXHEIGHT * MAXWIDTH);
for(i = 0; i < (MAXHEIGHT * MAXWIDTH); i++) {
frontier[i] = malloc(sizeof(int) * 2);
}
// Create came_from array
came_from = malloc(sizeof(int **) * MAXHEIGHT);
for(i = 0; i < MAXHEIGHT; i++) {
came_from[i] = malloc(sizeof(int *) * MAXWIDTH);
for(j = 0; j < MAXWIDTH; j++) {
came_from[i][j] = malloc(sizeof(int) * 2);
came_from[i][j][0] = -1;
came_from[i][j][1] = -1;
}
}
// Add start to came_from
came_from[y1][x1][0] = -9;
came_from[y1][x1][1] = -9;
// Add start to frontier
frontier[count][0] = x1;
frontier[count][1] = y1;
count++;
while(index < count) {
int x = frontier[index][0];
int y = frontier[index][1];
index++;
if(x == x2 && y == y2)
break;
count = add_neighbors(frontier, came_from, count, x, y);
}
// Set temp position variables to end position
{
int x = x2;
int y = y2;
while(x != x1 || y != y1) {
int tempy = y;
mvprintw(y, x, "*");
// Segmentation fault because came_from[tempy][x][1] and came_from[tempy][x][0]
// always equals -1 which is out of bounds. Not sure how to fix it, something
// is wrong with add_neighbors function I think.
y = came_from[tempy][x][1];
x = came_from[tempy][x][0];
}
}
// TODO: Return came_from array!
// Free all resources from both arrays
for(i = 0; i < MAXHEIGHT; i++) {
for(j = 0; j < MAXWIDTH; j++) {
free(came_from[i][j]);
}
free(came_from[i]);
}
free(came_from);
for(i = 0; i < (MAXHEIGHT * MAXWIDTH); i++) {
free(frontier[i]);
}
free(frontier);
}
int main(void)
{
initscr();
noecho();
clear();
path_finding(0, 2, 7, 8);
refresh();
getch();
endwin();
return 0;
}
Compile with: cc -o test test.c -lncurses
GDB output:
[philip#darkstar temp]$ gdb --batch --ex r --ex bt --ex q temp
Program received signal SIGSEGV, Segmentation fault.
0x000055555555599d in path_finding (x1=0, y1=2, x2=7, y2=8) at src/pathfind.c:117
117 y = came_from[tempy][x][1];
#0 0x000055555555599d in path_finding (x1=0, y1=2, x2=7, y2=8) at src/pathfind.c:117
#1 0x00005555555551ff in main () at src/main.c:11
A debugging session is active.
Inferior 1 [process 65294] will be killed.
Quit anyway? (y or n) [answered Y; input not from terminal]
[philip#darkstar temp]$
Some of the allocation sizes are incorrect:
frontier = malloc(sizeof(frontier) * MAXHEIGHT * MAXWIDTH); should be
frontier = malloc(sizeof(*frontier) * MAXHEIGHT * MAXWIDTH);
frontier[i] = malloc(sizeof(*frontier) * 2); should read:
frontier[i] = malloc(sizeof(frontier[i][0]) * 2);
These accesses are not properly protected:
if(y <= MAXHEIGHT && came_from[y + 1][x][0] < 0) should be
if (y < MAXHEIGHT-1 && came_from[y + 1][x][0] < 0)
if(x <= MAXWIDTH && came_from[y][x + 1][0] < 0) should be
if(x < MAXWIDTH-1 && came_from[y][x + 1][0] < 0)
the frontier array is not initialized. You should use calloc() to intialize the int arrays to 0 or run an initialization loop.
in the while (x != x1 || y != y1) loop, when you read y = came_from[tempy][x][1] you do not check that y >= 0. Since you initialized came_from[y1][x1][0] = -9; it way be negative and cause an out of bounds access during the next iteration as you set tempy = y.
the algorithm is not obvious from the code, you might want to comment more for the reader's sake.

Cannot print out the values of a dynamic 2D array of structs

This program is supposed to ask the user for two values, then generate and print a table using the two values as the number of rows and columns respectively. Each cell of the table has two values, denoted as cellX and cellY. The x-value and y-value of each cell of the table is 1 and 2 respectively.
So in short, it's a dynamic 2D array of structs. The problem is, the program seems to be skipping the last for loop, so it's not printing the contents of the array of structs. No errors were generated.
#include <stdio.h>
#include <stdlib.h>
typedef struct // one cell of a table holding two int values
{
int *cellX;
int *cellY;
} Table;
int main()
{
char dump;
int row, col, y, x;
printf("Enter number of rows and columns (r,c): ");
scanf("%d%c%d", &row, &dump, &col);
Table **grid;
grid = (Table **)malloc(row * col * sizeof(Table));
for (y = 0; y < row; y++) // assigns values to the table
{
for (x = 0; x < col; x++)
{
*grid[x][y].cellX = 1; // all x-values will be 1
*grid[x][y].cellY = 2; // all y-values will be 2
}
}
for (y = 0; y < row; y++) // displays the table
{
for (x = 0; x < col; x++)
{
printf("%d, %d\t", *grid[x][y].cellX, *grid[x][y].cellY);
}
}
free(grid);
return 0;
}
grid = (Table **)malloc(row * col * sizeof(Table));
This is not how you allocate a 2D array, Table** is an array of pointers (Table*) to an array of Table, so you have to allocate all those separate sub-arrays.
Table **grid = malloc(sizeof(*grid) * row);
for (int y = 0; y < row; ++y)
grid[y] = malloc(sizeof(*grid[0]) * col);
And then remember to free all those arrays as well.
In many cases this is not really wanted, so you can make a 1D array and then index it as-if 2D. For example with array[y * width + x].
Table *grid = malloc(sizeof(*grid) * row * col);
for (y = 0; y < row; y++) // assigns values to the table
{
for (x = 0; x < col; x++)
{
grid[y * col + x].cellX = 1; // all x-values will be 1
grid[y * col + x].cellY = 2; // all y-values will be 2
}
}
Also your struct contains pointers, but I don't really see why, and you never allocated them. Just store values.
typedef struct
{
int cellX;
int cellY;
} Table;

C - create 3D array of ints and initialize it to zeros

I'm trying to create a 3D array of ints initialized to zeros each of fixed size denoted as "dim".
For example, for dim=3, it will have 27 cells for ints.
I tried this:
int ***board;
int **rows;
int *tried;
board = calloc(dim,sizeof(int**));
rows = calloc(dim*dim, sizeof(int*));
tried = calloc(dim*dim*dim, sizeof(int));
int i;
int j;
int k;
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim*dim;
for (j=0 ; j<dim ; j++) {
board[i][j] = tried + j*dim + i*dim*dim;
}
}
for (i=0 ; i<dim ; i++) {
for (j=0 ; j<dim ; j++) {
for (k=0 ; k<dim ; k++) {
board[i][j][k] = 0;
}
}
}
Trying to debug it, I found that it works until:
board[1][1][0] = 0
And then the program gets stuck and i just can't find the reason.
Can someone explain this please?
Thanks!
First about the error in your code. Compare this:
rows = calloc(dim*dim, sizeof(int*));
to this:
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim*dim;
The entire size of the array allocated to rows is dim*dim elements. So, already in the second iteration of this loop, you access it out of bounds. You probably meant:
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim;
As I already mentioned in the comment, this is not a 3D array. It mimics the usage in code by using pointers and you're using a kind-of clever trick here, so you only need 3 allocations in total. This might be a good idea under the following conditions:
your dim is variable at runtime, so you can't know it in advance, and
you have to write code for compilers that don't support VLAs1) (variable-length-arrays).
If one of this conditions is not true, it's much better to use a real 3D array. If the array doesn't have to live after leaving your function and the size isn't huge, just use a simple variable with automatic storage duration like
int board[3][3][3] = { 0 }; // possibly #define the dimension
or, for a variable dim, requiring a compiler supporting VLAs
int board[dim][dim][dim] = { 0 };
If on the other hand, the array will be huge and/or you need to return it from your function, you indeed have to allocate it dynamically. Then just use the following:
int (*board)[3][3] = calloc(3, sizeof *board); // static size
int (*board)[dim][dim] = calloc(dim, sizeof *board); // dynamic case, with VLA suppport
Also note that calloc() already sets your allocated memory to 0, so no need for looping all over it.
Side notes:
with sizeof, prefer the expression form, so instead of writing
int *a = calloc(5, sizeof(int));
better write
int *a = calloc(5, sizeof *a);
this avoids errors when you later change the type of a.
always check the return value of malloc() and friends -- they might return a null pointer (e.g. when you're running out of memory).
1) VLAs don't exist in the oldest standards C89/C90 -- they were introduced in C99 as a mandatory feature, but later made optional in C11. This allows C11 compilers to omit them, which might make sense when e.g. targeting embedded systems. In practice, you can safely assume a C11 compliant compiler supports them if it isn't special purpose.
I rewrote your code to show how allocation of a 3D array could look like. And as pointed out in the comments, there's no need to initialize the array to 0 since calloc does that for you. Had you used malloc the array would not have been initialized.
#include <stdlib.h>
#include <stdio.h>
#define dim (3u)
int main() {
int x;
int y;
int z;
int ***cube;
cube = calloc(dim, sizeof(int**));
for (z = 0; z < dim; z++) {
cube[z] = calloc(dim, sizeof(int*));
for (y = 0; y < dim; y++) {
cube[z][y] = calloc(dim, sizeof(int));
}
}
for (z = 0; z < dim; z++) {
for (y = 0; y < dim; y++) {
for (x = 0; x < dim; x++) {
cube[z][y][x] = z + y + x;
}
}
}
for (z = 0; z < dim; z++) {
for (y = 0; y < dim; y++) {
for (x = 0; x < dim; x++) {
printf("%d ", cube[z][y][x]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
What you want to store in it is up to you, in my example I wrote the sum of the counter to each index.
Code below is Unlicense.
I will suggest something different. Just create a 1D array and set some boundaries to interpret it as 3D. I added some test cases for you to better visualize how it works. Do not forget to look at how easy 'calloc' call is. Here is the code:
#include <stdlib.h>
#include <stdio.h>
int getindex(int dim, int x, int y, int z) {
return z * dim * dim + y * dim + x;
}
void printarray(int* tdarray, int dim) {
printf("[\n");
for (int i = 0; i < dim; i++) {
printf("\t[\n");
for (int j = 0; j < dim; j++) {
printf("\t\t[");
for (int k = 0; k < dim; k++) {
if (k == 0) printf("%d", *(tdarray + getindex(dim, k, j, i)));
else printf(",\t %d", *(tdarray + getindex(dim, k, j, i)));
}
printf("]\n");
}
printf("\n\t]\n");
}
printf("]\n");
}
int main() {
int dim = 10;
size_t arraysize = sizeof (int) * dim * dim * dim;
int lookupindex = getindex(dim, 7, 5, 4); /* Numbers picked randomly */
int* tdarray = (int*) malloc(arraysize);
calloc(*tdarray, arraysize);
/* Below is test code and visualizations, all magic happens above.*/
if (*(tdarray + lookupindex) == 0) *(tdarray + lookupindex) = 7;
printf("tdarray[x:%d, y:%d, z:%d]:\t%d\n\n", 7, 5, 4, *(tdarray + lookupindex));
printarray(tdarray, dim);
printf("\n\n\n\n\n\n\n\n\n\n");
for (int i = 0; i < getindex(dim, 9, 9, 9) + 1; i++) *(tdarray + i) = i;
printarray(tdarray, dim);
free(tdarray);
}

Resources