All pastes #1235066 Raw Edit

Game of Life in C

public c v1 · immutable
#1235066 ·published 2008-10-23 21:06 UTC
rendered paste body
#include <stdio.h>#include <stdlib.h>#include <time.h>#define LIVE_MIN 3#define LIVE_MAX 3#define STAY_ALIVE_MIN 2#define STAY_ALIVE_MAX 3#define FILE_DEAD '0'#define FILE_ALIVE '1'#define PRNT_DEAD ' '#define PRNT_ALIVE 'Q'#define CLR_SCR_LINES 0/* 0.5s sleep*//* #define SLEEP {0, 100000000} */#define MAP_CELL_TYPE int/*typedef MAP_CELL_TYPE* Map;*/typedef struct {	MAP_CELL_TYPE* map;	int width;	int height;	char live_char;	char dead_char;} Map;typedef enum {	DEAD, ALIVE} State;typedef enum {	SUCCESS, ERROR} Result;State live(int neighbours, State state);Result load_map(Map*, FILE*);State next_state(Map* map);int count_neighbours(Map map, int width, int height);void print_map(Map);void destroy_map(Map);State get_state(char file_state);MAP_CELL_TYPE* getxy(Map, int width, int height);MAP_CELL_TYPE getxy_value(Map, int width, int height);int main(int argc, char *argv[]){	int i, STEPS;	double SLEEP_TIME;		FILE * file;	Map map;	map.live_char = PRNT_ALIVE;	map.dead_char = PRNT_DEAD;	map.width = 0;	map.height = 0;	map.map = NULL;			struct timespec slp;	if (argc != 4)	{		fprintf(stderr, "Usage: life <input file> <steps (0 for inf)> <sleep time in seconds>\n");		return 1;	}		file = fopen(argv[1], "r");	if (file == NULL)	{		fprintf(stderr, "Could not open %s.\n", argv[1]);		return 1;	}		STEPS = atoi(argv[2]);	SLEEP_TIME = atof(argv[3]);	slp.tv_sec = (long)SLEEP_TIME;	slp.tv_nsec = (SLEEP_TIME-slp.tv_sec)*1e9;		if (load_map(&map, file) == ERROR)	{		/* destroy_map(map); */		fclose(file);		return 1;	}	i=0;	while (1)	{		print_map(map);		if (DEAD == next_state(&map))		{			print_map(map);			break;		}		if (STEPS && ++i>STEPS) break;		nanosleep(&slp, NULL);	}		fclose(file);	destroy_map(map);	return 0;}State live(int neighbours, State state){	switch (state)	{		case DEAD:			if (neighbours >= LIVE_MIN && neighbours <= LIVE_MAX)				return ALIVE;			return DEAD;		case ALIVE:			if (neighbours >= STAY_ALIVE_MIN && neighbours <= STAY_ALIVE_MAX)				return ALIVE;			return DEAD;	}	return DEAD; /* just in case.. */}Result load_map(Map* map, FILE* file){	int width, height, c, tmp;	map->map = NULL;	if (file == NULL) return ERROR;		width=0;	c = fgetc(file);	while (c!='\n' && c!=EOF) {		++width;		c = fgetc(file);	}	map->width = width;		fseek(file, 0, SEEK_SET);	height = 0; tmp = -1;	do {		++tmp;		c = fgetc(file);		if (c == '\n' || c == EOF)		{			++height;			/*printf("width: %d, tmp: %d\n", width, tmp);*/			if (tmp != width)			{				--height;				break;			}			if (c == EOF)			{				break;			}			tmp = -1;		}		if (tmp > width)		{	/* TODO: check if needed */			break;		}	} while (c!=EOF);	map->height = height;		printf("PUZZLE: %dx%d\n", map->width, map->height);		map->map = malloc(sizeof(MAP_CELL_TYPE)*height*width);	if (map->map == NULL) return ERROR;		fseek(file, 0, SEEK_SET);	for (height=0; height < map->height; ++height)	{		for (width=0; width < map->width; ++width)		{			*getxy(*map, width, height) = get_state(fgetc(file));			/* map[height*map->width + width] = get_state(fgetc(file)); */		}		if (fgetc(file) != '\n') fprintf(stderr, "map[%d][%d]!=\\n\n", height, width);	}		return SUCCESS;}State next_state(Map* map){	int width, height;	State main_state = DEAD;	Map map_tmp; /* make a temp map */	map_tmp.map = map->map; /* swap maps */	map_tmp.width = map->width;	map_tmp.height = map->height;	map_tmp.live_char = map->live_char;	map_tmp.dead_char = map->dead_char;		map->map = malloc(sizeof(MAP_CELL_TYPE) * map->width * map->height);	if (map->map == NULL)	{		fprintf(stderr, "Unable to allocate memory(next_state)\n");		map->map = map_tmp.map;		return DEAD;	}	for (height=0; height < map->height; ++height)	{		for (width=0; width < map->width; ++width)		{			if (live(count_neighbours(map_tmp,width,height),					*getxy(map_tmp,width, height)) == ALIVE)			{				main_state = ALIVE;				*getxy(*map,width,height) = ALIVE;			}			else			{				*getxy(*map,width,height) = DEAD;			}		}	}	free(map_tmp.map);	return main_state;}int count_neighbours(Map map, int width, int height){	int s=0;	s+=(getxy_value(map,width-1, height-1)==ALIVE?1:0);	s+=(getxy_value(map,width+0, height-1)==ALIVE?1:0);	s+=(getxy_value(map,width+1, height-1)==ALIVE?1:0);	s+=(getxy_value(map,width-1, height+0)==ALIVE?1:0);	s+=(getxy_value(map,width+1, height+0)==ALIVE?1:0);	s+=(getxy_value(map,width-1, height+1)==ALIVE?1:0);	s+=(getxy_value(map,width+0, height+1)==ALIVE?1:0);	s+=(getxy_value(map,width+1, height+1)==ALIVE?1:0);	return s;}void print_map(Map map){	int width, height;	for (height=CLR_SCR_LINES;height; --height) printf("\n");	printf("----%dx%d----\n", map.width, map.height);	for (height=0; height < map.height; ++height)	{		for (width=0; width < map.width; ++width)		{			if (*getxy(map, width, height) == DEAD) printf("%c", map.dead_char);			else printf("%c", map.live_char);			/* map[height*map.width + width] = get_state(fgetc(file)); */		}		printf("\n");	}}void destroy_map(Map map){	if (map.map == NULL) return;	free(map.map);}State get_state(char file_state){	if (file_state == FILE_DEAD) return DEAD;	else return ALIVE;}MAP_CELL_TYPE* getxy(Map map, int width, int height){	return &(map.map[height*map.width + width]);}MAP_CELL_TYPE getxy_value(Map map, int width, int height){	if (width < 0 || height < 0 || width >= map.width		|| height >= map.height) return 0;	else return *getxy(map,width,height);}