Thread: stuck : conways game of life (lots of code)

  1. #16
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Make a simple program that does the following:

    1. Has a function that takes ROWS and COLS, and returns char **, a grid that the function creates of the appropriate size.

    2. Has a function that takes char** grid, and the number of rows, and frees the grid.

    3. Has a function that can rotate the grid passed to it, and return it as a new grid. (Hint: You can use the two functions I've just described above to help with this one.)

    You basically need a nice small clean program to get this working correctly, before you do anything else with your program.

    Quzah.
    Hope is the first step on the road to disappointment.

  2. #17
    Registered User
    Join Date
    Mar 2011
    Posts
    57
    Code works now, had some freeing of memory whilst still using it going on so that mucked up things.
    Last edited by play_fetch; 03-24-2011 at 08:07 AM.

  3. #18
    Registered User
    Join Date
    Mar 2011
    Posts
    57
    Hmms rotate may not work..
    Last edited by play_fetch; 03-24-2011 at 09:28 AM.

  4. #19
    Registered User
    Join Date
    Mar 2011
    Posts
    57
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    #include "rotate.h"
    
    /* Rorate the arena by 90 degrees clockwise. The pwidth and pheight
     * parameters should be pointers to the width and height of the arena
     * and these are changed by the function to the new width and height.
     * The new arena is returned and the old arena is freed. Any empty
     * columns in the new arena are represented by NULL pointers.
     */
    char **rotate(char **arena, int *pwidth, int *pheight)
    {
    	int x, y;
    	char** newarena;
    			
    	newarena = (char**) malloc((*pheight) * sizeof(char*));
    	for(x = 0; x < *pwidth; x++)
    	{
    			//newarena[x] = malloc(*pheight * sizeof(*newarena[x]));
    			newarena[x] = (char*) malloc((*pwidth) * sizeof(*newarena[x]));
    	}
    
    	for(x = 0; x < *pwidth; x++)
    	{
    		if(arena[x] != NULL)
    		{
    			for(y =0; y < *pheight; y++)
    			{
    				newarena[*pheight - (y+1)][x] = (arena[x][y] != NULL) ? arena[x][y] : 0;
    							
    			}
    		}
    		else
    		{
    			newarena[y] = NULL;
    		}
    		
    	}	
    
    	
    	free(arena);
    	int temp = *pheight;
    	*pheight = *pwidth;
    	*pwidth = temp;
    	return newarena;
    }
    getting seg faults, any ideas?

  5. #20
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Just a guess here, but usually you have the row/height as the first index and col/width as the second index: arena[row][col] or arena[y][x]. That makes me think that you should be doing the following:
    Code:
    for (y = 0; y < *pheight; y++) {
        for (x = 0; x < *pwidth; x++) {
            newarena[*pwidth - x + 1][y] = arena[y][x];
        }
    }
    When you rotate 90 degrees clockwise, your old y value becomes the new x value, and the old x value becomes the negative y value.

    EDIT: You shouldn't need any if checks inside there if you allocated your newarena correctly, which it looks like you did.

  6. #21
    Registered User
    Join Date
    Mar 2011
    Posts
    57
    Quote Originally Posted by anduril462 View Post
    Just a guess here, but usually you have the row/height as the first index and col/width as the second index: arena[row][col] or arena[y][x]. That makes me think that you should be doing the following:
    Code:
    for (y = 0; y < *pheight; y++) {
        for (x = 0; x < *pwidth; x++) {
            newarena[*pwidth - x + 1][y] = arena[y][x];
        }
    }
    When you rotate 90 degrees clockwise, your old y value becomes the new x value, and the old x value becomes the negative y value.

    EDIT: You shouldn't need any if checks inside there if you allocated your newarena correctly, which it looks like you did.
    If I do, according to what I understand by your suggestion..
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    #include "rotate.h"
    
    /* Rorate the arena by 90 degrees clockwise. The pwidth and pheight
     * parameters should be pointers to the width and height of the arena
     * and these are changed by the function to the new width and height.
     * The new arena is returned and the old arena is freed. Any empty
     * columns in the new arena are represented by NULL pointers.
     */
    char **rotate(char **arena, int *pwidth, int *pheight)
    {
    	int x, y;
    	char** newarena;
    			
    	newarena = (char**) malloc((*pheight) * sizeof(char*));
    	for(x = 0; x < *pwidth; x++)
    	{
    			newarena[x] = (char*) malloc((*pwidth) * sizeof(*newarena[x]));
    	}
    
    //	for(x = 0; x < *pwidth; x++)
    
    	for(y = 0; y < *pheight; y++)
    	{
    		if(arena[x] != NULL)
    		{
    		//	for(y =0; y < *pheight; y++)
    			for(x = 0; x < *pwidth; x++)
    			{
    				//newarena[*pheight - (y+1)][x] = (arena[x][y] != NULL) ? arena[x][y] : 0;
    			        newarena[*pwidth - x + 1][y] = arena[y][x];
    				
    							
    			}
    		}
    		else
    		{
    			newarena[y] = NULL;
    		}
    		
    	}	
    
    	
    	free(arena);
    	int temp = *pheight;
    	*pheight = *pwidth;
    	*pwidth = temp;
    	return newarena;
    }
    Either or without checks always still gives a seg fault.

  7. #22
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Noticed one more thing. I think *pwidth - x + 1 is wrong. Let's assume you have a width of 10. Your loop gives x values of 0 to 9. Then, 10 - 9 + 1 == 2 which is not the smallest index, and 10 - 0 + 1 == 11, which is an invalid index. Try
    *pwidth - x - 1.

  8. #23
    Registered User
    Join Date
    Mar 2011
    Posts
    57
    Quote Originally Posted by anduril462 View Post
    Noticed one more thing. I think *pwidth - x + 1 is wrong. Let's assume you have a width of 10. Your loop gives x values of 0 to 9. Then, 10 - 9 + 1 == 2 which is not the smallest index, and 10 - 0 + 1 == 11, which is an invalid index. Try
    *pwidth - x - 1.
    Still no... doesn't work. Think that might be more for rotating 180.. but anyway it doesn't matter because it still seg faults
    Code:
    int x, y;
    	char** newarena;
    			
    	newarena = (char**) malloc((*pheight) * sizeof(char*));
    	for(x = 0; x < *pwidth; x++)
    	{
    			newarena[x] = (char*) malloc((*pwidth) * sizeof(*newarena[x]));
    	}
    
    //	for(x = 0; x < *pwidth; x++)
    
    	for(y = 0; y < *pheight; y++)
    	{
    		//if(arena[y] != NULL)
    		//{
    		//	for(y =0; y < *pheight; y++)
    			for(x = 0; x < *pwidth; x++)
    			{
    				//newarena[*pheight - (y+1)][x] = (arena[x][y] != NULL) ? arena[x][y] : 0;
    			        newarena[*pwidth - x - 1][y] = arena[y][x];
    				
    							
    			}
    		//}
    		//else
    		//{
    		//	newarena[x] = NULL;
    		//}
    		
    	}	
    
    	
    	free(arena);
    	int temp = *pheight;
    	*pheight = *pwidth;
    	*pwidth = temp;
    	return newarena;

  9. #24
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Okay, so I wrote a wrapper around your rotate function to make sure it works. Compile and run the following for me and make sure this doesn't seg fault on your system. Admittedly, the rotation is a little strange, but no seg fault.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define W   5
    #define H   10
    
    char **rotate(char **arena, int *pwidth, int *pheight)
    {
        int x, y;
        char** newarena;
    
        newarena = malloc((*pheight) * sizeof(char*));
        for (x = 0; x < *pwidth; x++) {
            newarena[x] = malloc((*pwidth) * sizeof(*newarena[x]));
        }
    
        for (y = 0; y < *pheight; y++) {
            for (x = 0; x < *pwidth; x++) {
                newarena[*pwidth - x - 1][y] = arena[y][x];
            }
        }
    
        free(arena);
    
        int temp = *pheight;
        *pheight = *pwidth;
        *pwidth = temp;
    
        return newarena;
    }
    
    void print_arena(char **arena, int width, int height)
    {
        int i, j;
    
        printf("width = %d\t\theight = %d\n", width, height);
        for (i = 0; i < height; i++) {
            for (j = 0; j < width; j++) {
                printf("%c ", arena[i][j]);
            }
            putchar('\n');
        }
        putchar('\n');
    }
    
    int main(void)
    {
        int i, j;
        int width, height;
        char **arena;
    
        width = W;
        height = H;
        arena = malloc(height * sizeof(*arena));
        for (i = 0; i < height; i++) {
            arena[i] = malloc(width * sizeof(*arena[i]));
        }
    
        for (i = 0; i < height; i++) {
            for (j = 0; j < width; j++) {
                arena[i][j] = '0' + i * width + j;
            }
        }
    
        print_arena(arena, width, height);
        arena = rotate(arena, &width, &height);
        print_arena(arena, width, height);
    
        return 0;
    The only thing I noticed in there that was weird is your call to free(arena). That's the only other thing in there that seems suspicious. How is arena declared? If it's a regular 2-d array, then you can't free it. If you do it with a sequence of mallocs, similar to how you allocate newarena, then you aren't freeing all the memory. You have to free each row with free(arena[i]), then call free(arena). Has anything else in your code changed? How do you know it seg faults when you call rotate? Can I get a full listing to see if the problem actually lies elsewhere?

  10. #25
    Registered User
    Join Date
    Mar 2011
    Posts
    57
    I still need to be checking for NULL columns. I need to set columns with nothing in any of the rows to point to null... or my code won't work. So yes it is giving me a problem.. I will post the rest of the code...

    Quote Originally Posted by anduril462 View Post
    Okay, so I wrote a wrapper around your rotate function to make sure it works. Compile and run the following for me and make sure this doesn't seg fault on your system. Admittedly, the rotation is a little strange, but no seg fault.

    The only thing I noticed in there that was weird is your call to free(arena). That's the only other thing in there that seems suspicious. How is arena declared? If it's a regular 2-d array, then you can't free it. If you do it with a sequence of mallocs, similar to how you allocate newarena, then you aren't freeing all the memory. You have to free each row with free(arena[i]), then call free(arena). Has anything else in your code changed? How do you know it seg faults when you call rotate? Can I get a full listing to see if the problem actually lies elsewhere?
    Here is the main prog:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include "life.h"
    #include "load.h"
    #include "rotate.h"
    #include "evolve.h"
    
    #define MAX_CYCLES 100
    #define ROTATE	20
    
    
    /*  Display the arena in a vt100 (xterm) terminal with the given width and height.
     */
    static void
    show(char **arena, int width, int height)
    {
    	int x, y;
    
    	printf("\033[2J");
    
    	for (x = 0; x < width; x++)
    		if (arena[x] != NULL) 
    			for (y = 0; y < height; y++) {
    				if (arena[x][y] & 1)
    					printf("\033[%d;%dH*", y, x);
    	}
    	printf("\033[H");
    	fflush(stdout);
    }
    
    int main(int argc, char **argv)
    {
    	char **arena;
    	int width = WIDTH, height = HEIGHT;
    	int cycle;
    
    	if (argc != 2 && argc != 4) {
    		fprintf(stderr,"usage is %s filename [ width height ]\n",argv[0]);
    		exit(1);
    	}
    	if (argc == 4) {
    		width = atoi(argv[2]);
    		height = atoi(argv[3]);
    		if (width < MINSIZE || width > MAXSIZE || height < MINSIZE || height > MAXSIZE) {
    			fprintf(stderr, "%s: width and height must be in the range %d to %d\n",
    					argv[0], MINSIZE, MAXSIZE);
    			exit(1);
    		}
    	}
    	if ((arena = load(argv[1], width, height)) == NULL) {
    		fprintf(stderr,"%s: Cannot open %s\n",argv[0],argv[1]);
    		exit(1);
    	}
    	for (cycle = 1; cycle <= MAX_CYCLES; cycle++) {
    		show(arena, width, height);
    		evolve(arena, width, height);
    		if (cycle % ROTATE == 0)
    			arena = rotate(arena, &width, &height);
    		/*  Add a 1/10 sec delay so that we can see what is happening.
    		 */
    		usleep(100000);
    	}
    	int x;
    	for (x = 0; x < width; x++)
    		if (arena[x] != NULL)
    			free(arena[x]);
    	free(arena);
    	return 0;
    }
    and there is nothing implemented in evolve yet so...
    Last edited by play_fetch; 03-24-2011 at 12:26 PM.

  11. #26
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You'd be done by now if you had listened to me. I told you in post 12 how to rotate it, and if you had written the functions I suggested in post 16, you'd have a better board setup.

    Furthermore, since you are working off of a grid that will have things arriving and leaving from it (living and dying), why would you have empty rows and columns in your grid? That's just going to be a pain when you need to suddenly put something there. Just allocate the whole thing at once and don't worry about constant row/column NULL checks.


    Quzah.
    Hope is the first step on the road to disappointment.

  12. #27
    Registered User
    Join Date
    Mar 2011
    Posts
    57
    Quote Originally Posted by quzah View Post
    You'd be done by now if you had listened to me. I told you in post 12 how to rotate it, and if you had written the functions I suggested in post 16, you'd have a better board setup.
    I really don't think so, don't think that I didn't take your advice. If you are referring to the whole
    for each old row
    for each old col
    new[ /* normally rows / col ][ / normally col */ row ] = old[ row ][ col ]
    The last bit will just be a reflection rather than 90 degree turn. This WOULD work if it was just rotating 180.

    Quote Originally Posted by quzah View Post
    Furthermore, since you are working off of a grid that will have things arriving and leaving from it (living and dying), why would you have empty rows and columns in your grid? That's just going to be a pain when you need to suddenly put something there. Just allocate the whole thing at once and don't worry about constant row/column NULL checks.
    Quzah.
    I don't decide what I have to do for this exercise unfortunately but this is how it is, there can be empty rows and empty columns. If a column is empty then the entire thing has to point to null. If a row doesn't have anything in it but the entire column it is in does, then it points to 0.

  13. #28
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by play_fetch View Post
    I really don't think so, don't think that I didn't take your advice. If you are referring to the whole
    for each old row
    for each old col
    new[ /* normally rows / col ][ / normally col */ row ] = old[ row ][ col ]
    The last bit will just be a reflection rather than 90 degree turn. This WOULD work if it was just rotating 180.
    Ah. I see.

    A B C
    D E F

    A D
    B E
    C F
    Quote Originally Posted by play_fetch View Post
    I don't decide what I have to do for this exercise unfortunately but this is how it is, there can be empty rows and empty columns. If a column is empty then the entire thing has to point to null. If a row doesn't have anything in it but the entire column it is in does, then it points to 0.
    So it's a requirement of the project that you have null rows or columns? That's really odd. It's terribly inefficient.


    Quzah.
    Hope is the first step on the road to disappointment.

  14. #29
    Registered User
    Join Date
    Mar 2011
    Posts
    57
    Quote Originally Posted by quzah View Post
    Ah. I see.

    A B C
    D E F

    A D
    B E
    C FSo it's a requirement of the project that you have null rows or columns? That's really odd. It's terribly inefficient.


    Quzah.
    Yeah.. so... it is a bit more complicated unfortunately. A lot of people are doing [x][y] = [y][x] and I have been getting a lot of requests for help but unfortunately I am unable to do it myself so... lol.

    Yeah it is very efficient.... but requirements are requirements I guess!

  15. #30
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by play_fetch View Post
    I don't decide what I have to do for this exercise unfortunately but this is how it is, there can be empty rows and empty columns. If a column is empty then the entire thing has to point to null. If a row doesn't have anything in it but the entire column it is in does, then it points to 0.
    I'm with Quzah here. Unless you can show me the specs from your assignment that say empty rows have to be null, then they don't. And they shouldn't be. It just complicates things. You can have a column with all 0's down it if there are no creatures living anywhere in that column. Why can't you have a row with all 0 elements if nothing lives there?

    Also, I've worked the rotate function into the rest of your code and removed the load and evolve calls since I don't have those functions, and reworked your crazy show function to not use strange escape sequences (I'm not running an xterm window). I don't get a seg fault with this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define MAX_CYCLES 1
    #define ROTATE  20
    
    #define HEIGHT  10
    #define WIDTH   5
    #define MINSIZE 5
    #define MAXSIZE 20
    
    char **rotate(char **arena, int *pwidth, int *pheight)
    {
        int x, y;
        char** newarena;
    
        newarena = malloc((*pheight) * sizeof(char*));
        for (x = 0; x < *pwidth; x++) {
            newarena[x] = malloc((*pwidth) * sizeof(*newarena[x]));
        }
    
        for (y = 0; y < *pheight; y++) {
            for (x = 0; x < *pwidth; x++) {
                newarena[*pwidth - x - 1][y] = arena[y][x];
            }
        }
    
        for (y = 0; y < *pwidth; y++) {
            free(arena[y]);
        }
        free(arena);
    
        int temp = *pheight;
        *pheight = *pwidth;
        *pwidth = temp;
    
        return newarena;
    }
    
    void show(char **arena, int width, int height)
    {
        int i, j;
    
        putchar('+');
        for (j = 0; j < width; j++) {
            putchar('-');
        }
        puts("+");
        for (i = 0; i < height; i++) {
            putchar('|');
            for (j = 0; j < width; j++) {
                putchar(arena[i][j] ? '*' : ' ');
            }
            puts("|");
        }
        putchar('+');
        for (j = 0; j < width; j++) {
            putchar('-');
        }
        puts("+");
        putchar('\n');
    }
    
    int main(int argc, char **argv)
    {
        int i, j;
        char **arena;
        int width = WIDTH, height = HEIGHT;
        int cycle;
    
        if (argc != 2 && argc != 4) {
            fprintf(stderr,"usage is %s filename [ width height ]\n",argv[0]);
            exit(1);
        }
        if (argc == 4) {
            width = atoi(argv[2]);
            height = atoi(argv[3]);
            if (width < MINSIZE || width > MAXSIZE || height < MINSIZE || height > MAXSIZE) {
                fprintf(stderr, "%s: width and height must be in the range %d to %d\n",
                        argv[0], MINSIZE, MAXSIZE);
                exit(1);
            }
        }
    
        arena = malloc(height * sizeof(*arena));
        for (i = 0; i < height; i++) {
            arena[i] = malloc(width * sizeof(*arena[i]));
            for (j = 0; j < width; j++) {
                arena[i][j] = ((rand() % 5) < 2) ? 1 : 0;
            }
        }
    
        show(arena, width, height);
        arena = rotate(arena, &width, &height);
        show(arena, width, height);
    
        for (i = 0; i < height; i++)
            free(arena[i]);
        free(arena);
    
        return 0;
    }
    So compile that for me, with debugging symbols (gcc -g life.c). Then, run it in gdb and find the exact line where it fails. If you need a gdb tutorial, check here: Cprogramming.com - Tutorials - An Introduction to GDB

    Actually, we're really close with the rotate code. We somehow managed to rotate -90 degrees (1/4 turn counter-clockwise) instead.
    Last edited by anduril462; 03-24-2011 at 03:41 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A Simple Life Game Code - Near the end ?
    By apolochaves in forum C Programming
    Replies: 6
    Last Post: 08-05-2010, 03:32 AM
  2. Conways Game using Pointers
    By NewUser in forum C Programming
    Replies: 10
    Last Post: 03-22-2010, 04:15 PM
  3. 'Business code' vs 'Game code'
    By VirtualAce in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-09-2007, 03:33 AM
  4. Game of life
    By JoshR in forum C++ Programming
    Replies: 30
    Last Post: 04-03-2005, 02:17 PM
  5. game code
    By The WaRped OnE in forum Game Programming
    Replies: 1
    Last Post: 02-28-2002, 08:46 PM