/* CONWAY'S GAME OF LIFE - An remake of Conway's game of life. Features * resizeable grid and variable amount of starting 'microbes'. */ #include /* Define some constants */ #define aliveChar '*' #define deadChar ' ' #define borderCharTop '-' #define borderCharSide '|' #define maxGridWidth 50 #define maxGridHeight 25 #define minGridSize 8 #define minPop 4 main() { /* Declare some vars. */ int gridHeight, gridWidth, startPop, maxPop, i, j, k, l, m, aliveIndex, neighbours; char grid[maxGridHeight][maxGridWidth], buff[maxGridHeight][maxGridWidth], again; /* Prototype some funtions. */ void printOut(char grid[maxGridHeight][maxGridWidth], int gridWidth, int gridHeight); /* Get the grid width (inc. border) */ do { printf("Enter width of grid including border (%d-%d): ",minGridSize,maxGridWidth); scanf("%d",&gridWidth); /* Check to see if in range. Chokes on chars */ } while (gridWidth > maxGridWidth || gridWidth < minGridSize); /* Get the grid height (inc. border) */ do { printf("Enter height of grid including border (%d-%d): ",minGridSize,maxGridHeight); scanf("%d",&gridHeight); /* Check to see if in range. Chokes on chars */ } while (gridHeight > maxGridHeight || gridHeight < minGridSize); /* Get starting population */ /* Maximum is set to half grid size (not inc. borders) */ maxPop = (int) ((gridHeight-2) * (gridWidth-2)) / 2; do { printf("Enter starting population (%d-%d): ",minPop, maxPop); scanf("%d",&startPop); /* Check to see if in range. Chokes on chars */ } while (startPop > maxPop || startPop < minPop); /* Initialise grid only with dead cells */ for (i=0; i < gridHeight; i++) { for (j=0; j < gridWidth; j++) { grid[i][j] = deadChar; } } /* Scatter the living cells */ /* This drove me crazy thiking how to do this. This is the third * solution I came up with!! */ for (i=0; i < startPop; i++) { /* Generate number between 1 and no. of dead cells in valid squares */ srandom(time(0)); /* Below is: Grid squares - alive cells - 1 square border */ aliveIndex = random() % ((gridHeight-2) * (gridWidth-2) - i); /* Increment so it is not a zero based no. This is necessary for the * loop below to work correctly */ aliveIndex++; /* Make the "aliveIndex'th" dead cell encountered alive */ for (j=1; j < (gridHeight-1); j++) { for (k=1; k < (gridWidth-1); k++) { if (grid[j][k] == deadChar) { aliveIndex--; } if (!aliveIndex) { grid[j][k] = aliveChar; goto NEXTCELL; } } } NEXTCELL: } /* Now for the action!! */ again = 'y'; for (m=0; (again == 'Y' || again == 'y'); m++) { printf("\n"); printOut(grid, gridHeight, gridWidth); for (i=1; i < (gridHeight-1); i++) { for (j=1; j < (gridWidth-1); j++) { /* Start loop to iterate over neighbours */ neighbours=0; for (k=i-1; k < (i+2); k++) { for (l=j-1; l < (j+2); l++) { if (grid[k][l] == aliveChar) { neighbours++; } } } /* Remove one if itself is alive */ if (grid[i][j] == aliveChar) { neighbours--; } /* The Conway rules */ /* Is there really no 'elseif' statement?! */ /* Birth */ if (grid[i][j] == deadChar && neighbours == 3) { buff[i][j] = aliveChar; } else { /* Death */ if (grid[i][j] == aliveChar && (neighbours < 2 || neighbours > 3)) { buff[i][j] = deadChar; } else { /* Survival */ if (grid[i][j] == aliveChar) { buff[i][j] = aliveChar; } else { /* Dormant */ buff[i][j] = deadChar; } } } } } /* Copy buff into grid */ for (i=1; i < (gridHeight-1); i++) { for (j=1; j < (gridWidth-1); j++) { grid[i][j] = buff[i][j]; } } /* Output some stuff to the screen */ printf("\nGeneration: %d\n", m); printf("Go again? (y/n): "); /* Type %1s appends 1 null character to char. Unsure about this but it works when %c doesn't */ scanf("%1s",&again); } /* End of main */ } /* printOut() - prints array parameter to screen */ void printOut(char grid[maxGridHeight][maxGridWidth], int gridHeight, int gridWidth) { int i, j; for (i=0; i < gridHeight; i++) { for (j=0; j < gridWidth; j++) { /* Makes sure there is a space to the side of grid at top */ if ((i==0 || i==(gridHeight-1)) && j==0) { printf(" %c",borderCharTop); } else { if (i==0 || i==(gridHeight-1)) { printf("%c%c",borderCharTop,borderCharTop); } else { if (j==0 || j==(gridWidth-1)) { printf(" %c",borderCharSide); } else { printf(" %c", grid[i][j]); } } } } printf("\n"); } }