Thread: Game of life: Initializing a struct with two 2D arrays

  1. #1
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476

    Game of life: Initializing a struct with two 2D arrays

    Hi! After working on a python version, I'm writing another Game of life. I use a struct with two 2D arrays, each representing the current and the next grid. But I don't wan't to loop over each element and setting it to zero, because, the item array[56][62] is always 2089869164. how can that be? Here is my code (it doesn't work):

    Code:
    #define GRID_SIZE 64
    typedef struct {
    	unsigned int states[GRID_SIZE][GRID_SIZE];
    	unsigned int next_states[GRID_SIZE][GRID_SIZE];
    } Cells;
    
    Cells *Cells_New()
    {
    	Cells cells;
    	unsigned int states[GRID_SIZE][GRID_SIZE] = {0};
    	unsigned int next_states[GRID_SIZE][GRID_SIZE] = {0};
    	cells.states = states;
    	cells.next_states = next_states;
    	return &cells;
    }
    Why can't I just use:
    Code:
    typedef struct {
            unsigned int states[GRID_SIZE][GRID_SIZE] = {0};
    	unsigned int next_states[GRID_SIZE][GRID_SIZE] = {0};
    } Cells;
    ???

  2. #2
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    That's because this part:
    Code:
    typedef struct {
            unsigned int states[GRID_SIZE][GRID_SIZE];
    	unsigned int next_states[GRID_SIZE][GRID_SIZE];
    is a declaration. It basically says what the struct contains.
    This part:
    Code:
    } Cells;
    actually creates an instance. I hope you'll agree that only instances can have values assigned? So you cannot assign 0 to the declaration. But you can do the following:
    Code:
    Cells cells;
    memset (&cells, 0, sizeof (Cells);
    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  3. #3
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476
    What does memset do? Set all the memory there to zero? That's a good Idea! Thanks. And What is the difference between
    Code:
    typedef struct {...} Cells
    and

    Code:
    typedef struct Cells{...} Cells
    ?

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Brafil View Post
    What does memset do? Set all the memory there to zero? That's a good Idea! Thanks. And What is the difference between
    Code:
    typedef struct {...} Cells
    and

    Code:
    typedef struct Cells{...} Cells
    ?
    The second creates a named struct ("struct Cells") and then sets the alias to be Cells, while the first creates an unnamed struct and then sets the alias. The second version would be necessary if you needed a pointer to struct inside the struct itself, as the typedef alias doesn't get set until the end.

  5. #5
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by Brafil View Post
    Hi! After working on a python version, I'm writing another Game of life. I use a struct with two 2D arrays, each representing the current and the next grid. But I don't wan't to loop over each element and setting it to zero, because, the item array[56][62] is always 2089869164. how can that be? Here is my code (it doesn't work):

    Code:
    #define GRID_SIZE 64
    typedef struct {
    	unsigned int states[GRID_SIZE][GRID_SIZE];
    	unsigned int next_states[GRID_SIZE][GRID_SIZE];
    } Cells;
    
    Cells *Cells_New()
    {
    	Cells cells;
    	unsigned int states[GRID_SIZE][GRID_SIZE] = {0};
    	unsigned int next_states[GRID_SIZE][GRID_SIZE] = {0};
    	cells.states = states;
    	cells.next_states = next_states;
    	return &cells;
    }
    You can't assign arrays to one another. You would have to copy each member over one by one.

    In this case you could loop through each element, setting the value to 0. Or as QuantumPete suggests use a more primitive function to zero out each byte.

    Why can't I just use:
    Code:
    typedef struct {
            unsigned int states[GRID_SIZE][GRID_SIZE] = {0};
    	unsigned int next_states[GRID_SIZE][GRID_SIZE] = {0};
    } Cells;
    ???
    Because C does not support default values for structs using this or any other syntax.
    Last edited by King Mir; 12-02-2008 at 12:06 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  6. #6
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by Brafil View Post
    What does memset do? Set all the memory there to zero?
    First argument is the first byte of the variable to be changed, second the bitmask you want, third the number of bytes from the start of the first argument.
    You can also memset things to 1 or 8 or 'F'. Whatever you want, but most of the time it is used to zero out memory.

    [QUOTE=King Mir;812949]
    Quote Originally Posted by King Mir View Post
    Or as QuantumPete suggests use a more primitive function to zero out each element.
    Oi! Primitive it might be, but it saves you the overhead of repeated (in this case nested) loops and the associated iteration variables. For something as simple as zero'ing out large amounts of memory I would always use memset over a loop.

    QuantumPete
    Last edited by QuantumPete; 12-02-2008 at 12:06 PM.
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  7. #7
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476
    but it's a weird BUG! It still says that array[55][62] is 2089869164! What's that? I have 512 MB of RAM, and 64 * 64 * 4 = 16 MB!

    PS: It was at [55], not at [56]!

  8. #8
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    What is actually stating this 2d array is 2089869164? Are you trying to simply print out the size of each element within the array or the whole size of this 2D array?

  9. #9
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    @QuantumPete
    I totally agree that memcpy is the best solution in this case. It is however not a generic solution to this problem, and so I left it as an aside.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  10. #10
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476
    It's simply a
    Code:
    printf("... %d\n", array[x][y]);
    operation. It ALWAYS says 280... (i don't remember, look for my previous post)


    And wth does SDL change stdout to stdout.txt so it writes everything into this file rather than on the screen?
    Last edited by Brafil; 12-03-2008 at 08:52 AM.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Show us the code containing the printf statement.
    My guess is you forgot arrays begin at 0 and not 1.

    > And wth does SDL change stdout to stdout.txt so it writes everything into this file rather than on the screen?
    Because SDL is a window, and there is no console.
    Maybe if you call AllocConsole() before initialising SDL, it will use that instead?
    Maybe this as well - http://clusty.com/search?query=SDL+s...Mozilla-search
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476
    Well, now Im using pointers rather than 2D arrays... It still says the SAME with malloc()!
    (And maybe the stdout text file is better as a log file)

    cells.h
    Code:
    #include <SDL\SDL.h>
    #include <stdio.h>
    
    #define GRID_SIZE 64
    typedef struct {
    	int *states;
    	int *next_states;
    } Cells;
    
    int Array_Get(int *array, int position)
    {
    	return *(array + position);
    }
    
    void Array_Set(int *array, int position, int value)
    {
    	 *(array + position) = value;
    }
    
    Cells *Cells_New()
    {
    	Cells *cells;
    	cells->states = malloc(GRID_SIZE * GRID_SIZE * sizeof(int));
    	cells->next_states = malloc(GRID_SIZE * GRID_SIZE * sizeof(int));
    	memset(cells, 0, sizeof(*cells));
    	return cells;
    }
    
    int Cells_Get(Cells *cells, int x, int y)
    {
    	return *(cells->states + x * GRID_SIZE + y);
    }
    
    int Cells_GetNext(Cells *cells, int x, int y)
    {
    	return *(cells->next_states + x * GRID_SIZE + y);
    }
    
    void Cells_Set(Cells* cells, int x, int y, int value)
    {
    	*(cells->states + x * GRID_SIZE + y) = value;
    }
    
    void Cells_SetNext(Cells *cells, int x, int y, int value)
    {
    	*(cells->next_states + x * GRID_SIZE + y) = value;
    }
    
    int *Cells_GetRow(Cells *cells, int x)
    {
    	return cells->states + x * GRID_SIZE;
    }
    
    int *Cells_GetNextRow(Cells *cells, int x)
    {
    	return cells->next_states + x * GRID_SIZE;
    }
    PS: I'm very Python-oriented, but I want to make it fast, so there is room for optimizations later, f.e. macros instead of Set, Get(Next) etc...
    Last edited by Brafil; 12-03-2008 at 10:58 AM.

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    *(cells->states + (x * GRID_SIZE + y) * sizeof(int)
    Unless you only want every fourth cell to actually contain soemthing, you should remvoe the sizeof(int) - you are after all dealing with a int*, and C will automatically scale your pointer addition or subtraction by the size of the pointer element.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476
    Oh! Thanks! So I remove all sizeofs except those in malloc, but it still doesnt work. Wait! It doesnt go till there. Im looking now...

    PS: Are you sure? Because it now hangs at the first loop! It seems like there is no pointer to array[0][0]?

    Well, here the whole code:

    gof.h:
    Code:
    #include <SDL\SDL.h>
    #include <stdio.h>
    
    SDL_Surface *screen;
    SDL_Event *event;
    SDL_Color *color;
    SDL_Rect *rect;
    
    int init()
    {
    	int red, green, blue;
    
    	if (SDL_Init(SDL_INIT_EVERYTHING)) {
    		fprintf(stderr, "Couldn't initialize SDL: &#37;s\n", SDL_GetError());
    		return 1;
    	}
    	atexit(SDL_Quit);
    
    	screen = SDL_SetVideoMode(512, 512, 0, SDL_SWSURFACE);
    	if (!screen) {
    		fprintf(stderr, "Couldn't initialize the screen: %s\n", SDL_GetError());
    		return 1;
    	}
    
    	red = 0;
    	green = 255;
    	blue = 255;
    
    	color = SDL_MapRGB(screen->format, red, green, blue);
    
    	return 0;
    }
    
    #define Screen_Update(screen) SDL_UpdateRect((screen), 0, 0, 0, 0);
    #define Draw_Cell(x, y) rect->x = (x) * 8; rect->y = (y) * 8; rect->w = 8; rect->h = 8; SDL_FillRect(screen, rect, color)
    cells.h (like above)
    Code:
    #include <SDL\SDL.h>
    #include <stdio.h>
    
    #define GRID_SIZE 64
    typedef struct {
    	int *states;
    	int *next_states;
    } Cells;
    
    int Array_Get(int *array, int position)
    {
    	return *(array + position);
    }
    
    void Array_Set(int *array, int position, int value)
    {
    	 *(array + position) = value;
    }
    
    Cells *Cells_New()
    {
    	Cells *cells;
    	cells->states = malloc(GRID_SIZE * GRID_SIZE * sizeof(int));
    	cells->next_states = malloc(GRID_SIZE * GRID_SIZE * sizeof(int));
    	memset(cells, 0, sizeof(*cells));
    	return cells;
    }
    
    int Cells_Get(Cells *cells, int x, int y)
    {
    	return *(cells->states + x * GRID_SIZE + y);
    }
    
    int Cells_GetNext(Cells *cells, int x, int y)
    {
    	return *(cells->next_states + x * GRID_SIZE + y);
    }
    
    void Cells_Set(Cells* cells, int x, int y, int value)
    {
    	*(cells->states + x * GRID_SIZE + y) = value;
    }
    
    void Cells_SetNext(Cells *cells, int x, int y, int value)
    {
    	*(cells->next_states + x * GRID_SIZE + y) = value;
    }
    
    int *Cells_GetRow(Cells *cells, int x)
    {
    	return cells->states + x * GRID_SIZE;
    }
    
    int *Cells_GetNextRow(Cells *cells, int x)
    {
    	return cells->next_states + x * GRID_SIZE;
    }
    gof.c:

    Code:
    #include <SDL\SDL.h>
    #include <stdio.h>
    #include "gof.h"
    #include "cells.h"
    
    Cells *Cells_Calculate(Cells *cells)
    {
    	int x, y;
    	for (x = 0; x < GRID_SIZE; x++) {
    		printf("New Row %d\n", x);
    		int *prev_row = Cells_GetRow(cells, (GRID_SIZE + x - 1) % GRID_SIZE);
    		int *current_row = Cells_GetRow(cells, x);
    		int *next_row = Cells_GetRow(cells, (x + 1) % GRID_SIZE);
    
    		printf("Calculating row...\n");
    		for (y = 0; y < GRID_SIZE; y++) {
    			//printf("\tNew Cell (%d, %d) is \t%d\n", x, y, Cells_Get(cells, x, y));
    			printf("\tNew Cell (%d, %d)\n", x, y);
    			int prev_item = (GRID_SIZE + y - 1) % GRID_SIZE;
    			int next_item = (y + 1) % GRID_SIZE;
    			int neighbours = 0;
    
                           /* Ignore this fprintf please for now */
    			fprintf(stderr, "\n");
    			neighbours += Array_Get(prev_row, prev_item);
    			neighbours += Array_Get(prev_row, y);
    			neighbours += Array_Get(prev_row, next_item);
    
    			neighbours += Array_Get(current_row, prev_item);
    			neighbours += Array_Get(current_row, next_item);
    
    			neighbours += Array_Get(next_row, prev_item);
    			neighbours += Array_Get(next_row, y);
    			neighbours += Array_Get(next_row, next_item);
    
    			if (neighbours == 3) Cells_SetNext(cells, x, y, 1);
    			else if (neighbours != 2 && !Cells_Get(cells, x, y)) Cells_SetNext(cells, x, y, 0);
    		}
    	}
    	return cells;
    }
    
    Cells *Cells_Draw(Cells *cells)
    {
    	int x, y;
    	for (x = 0; x < GRID_SIZE; x++) {
    		printf("NewRow %d\n", x);
    		for (y = 0; y < GRID_SIZE; y++) {
    			printf("\tNewCol (%d, %d) is \t%d\n", x, y, Cells_GetNext(cells, x, y));
    			if (Cells_GetNext(cells, x, y)) {
    				Cells_Set(cells, x, y, 1);
    				Draw_Cell(x, y);
    			}
    			else {
    				Cells_Set(cells, x, y, 0);
    			}
    		}
    	}
    }
    
    int main(int argc, char **argv)
    {
    	int x, y;
    	Cells *cells = Cells_New(64, 64);
    
    	if (init()) {
    		printf("Error initializing the game. Press any key to quit...\n");
    		getchar();
    		return 1;
    	}
    	printf("Initialized\n");
    	cells = Cells_Draw(Cells_Calculate(cells));
    	printf("Calculated\n");
    	Screen_Update(screen);
    	return 0;
    }
    Last edited by Brafil; 12-03-2008 at 11:08 AM.

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Brafil View Post
    Oh! Thanks! So I remove all sizeofs except those in malloc
    Yes, they are obviously needed in malloc, since you are giving a size of something, which is in bytes. But ptr + n will give the nth element of whatever the pointer points at, no matter what size the type the pointer points at is.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Link List math
    By t014y in forum C Programming
    Replies: 17
    Last Post: 02-20-2009, 06:55 PM
  2. Assignment HELP!!
    By cprogrammer22 in forum C Programming
    Replies: 35
    Last Post: 01-24-2009, 02:24 PM
  3. Replies: 1
    Last Post: 12-03-2008, 03:10 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. 2D Game Programming Tutorials?
    By Zeusbwr in forum Game Programming
    Replies: 9
    Last Post: 11-04-2004, 08:36 AM