Search code examples
cconways-game-of-life

I cant build a border around the array in this program Game of Life in C language


I have the simulation Game of Life in C language as my assignment. I've tried and failed many times to build a border of asterisks around the final printed array. Also I've used a few goto statements, which caused another problem: if i restart the game from the menu the last generating function namely "generation_printer" does not exit and as a result two patters appear on the grid instead of one.This is my progress so far

#include "stdio.h" //for all basic functions
#include "stdlib.h"//for exit function
#include "time.h" //for random seed
#include "windows.h" //
#include "conio.h" //
#define scanf_s scanf

void neighbour_manager();//custom function to calculate neighbours and make a cell alive or dead accordingly
void generation_printer();//custom function to print the generations after selecting seed type

//initializing all variables
int generation;
char fill_char;
char array[35][85];
char array1[35][85];
char live = '+';
char dead = ' ';
char n;
//SEEDS
char block[2][2] = {{'+','+'}, {'+','+'}};
char boat[3][3] = {{'+','+',' '}, {'+',' ','+'}, {' ','+',' '}};
char loaf[4][4] = {{' ','+','+',' '},{'+', ' ', ' ', '+'},{' ', '+', ' ', '+'},{' ', ' ', '+', ' '}};
char beehive[3][4] = {{' ','+','+',' '},{'+', ' ', ' ', '+'},{' ', '+', '+', ' '}};
char blinker[1][3] = {{'+', '+','+'}};
char beacon[4][4] = {{'+','+',' ',' '},{'+',' ',' ',' '},{' ',' ',' ','+'},{' ',' ','+','+'}};
char toad[2][4] = {{' ','+','+','+'},{'+','+','+',' '}};
char pulsar[15][15] = {
                           {' ',' ',' ',' ','+',' ',' ',' ',' ',' ','+',' ',' ',' ',' '},
                           {' ',' ',' ',' ','+',' ',' ',' ',' ',' ','+',' ',' ',' ',' '},
                           {' ',' ',' ',' ','+','+',' ',' ',' ','+','+',' ',' ',' ',' '},
                           {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
                           {'+','+','+',' ',' ','+','+',' ','+','+',' ',' ','+','+','+'},
                           {' ',' ','+',' ','+',' ','+',' ','+',' ','+',' ','+',' ',' '},
                           {' ',' ',' ',' ','+','+',' ',' ',' ','+','+',' ',' ',' ',' '},
                           {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
                           {' ',' ',' ',' ','+','+',' ',' ',' ','+','+',' ',' ',' ',' '},
                           {' ',' ','+',' ','+',' ','+',' ','+',' ','+',' ','+',' ',' '},
                           {'+','+','+',' ',' ','+','+',' ','+','+',' ',' ','+','+','+'},
                           {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
                           {' ',' ',' ',' ','+','+',' ',' ',' ','+','+',' ',' ',' ',' '},
                           {' ',' ',' ',' ','+',' ',' ',' ',' ',' ','+',' ',' ',' ',' '},
                           {' ',' ',' ',' ','+',' ',' ',' ',' ',' ','+',' ',' ',' ',' '}
                          };
char glider[3][3] = {{' ','+',' '},{' ',' ','+'},{'+','+','+'}};
char spaceship[4][5] = {{'+',' ',' ','+',' '},{' ',' ',' ',' ','+'},{'+',' ',' ',' ','+'},{' ','+','+','+','+',}};
char gosper_glider_gun[15][38] = {
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', '+', '+', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ' },
                                    { ' ', '+', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', '+', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', '+', ' ', '+', ' ', ' ', '+', ' ', ' ', ' ', '+', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', '+', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', ' ', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
                                    { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }
                                 };


//main function starts here
int main(void)
{
    system("title CONWAY'S GAME OF LIFE");//to change the console title
    _flushall();//to remove garbage values
    printf("\t\t\t\t\tWelcome to Conway's Game of Life\n");//welcome note
    Sleep(2000);//for dramatic purposes
    system("cls");
    printf("Please make sure the console is maximized for optimal simulation.");//whole grid is not visible if console is not maximized
    Sleep(2000);//to create a pause to maximize screen before proceeding
    start:
    system("cls");
    int i = 0, j = 0;
    int a = 0, b = 0, seed_type = 0;
    printf("Select the seed type\nSTILL LIFE PATTERNS\nEnter 1 for Block \nEnter 2 for Loaf \nEnter 3 for Boat\nEnter 4 for Beehive\n\nOSCILLATORS\nEnter 5 for Blinker\nEnter 6 for Beacon\nEnter 7 for Toad\nEnter 8 for Pulsar\n\nGLIDERS AND SPACSHIPS\nEnter 9 for Glider\nEnter 10 for Spaceship\n\nGOSPER GLIDER GUN\nEnter 11 for Gosper Glider Gun\nYour choice: ");
    retake_seed_type: //For invalid choice

            scanf_s("%d", &seed_type);

    srand(time(NULL));
    a = 1 + rand() % 35;
    b = 1 + rand() % 85;
    switch (seed_type)
    {
    case 1: //for block
        for (i = a; i < a + 2; i++){
            for (j = b; j < b + 2; j++){

                array[i][j] = block[i - a][j - b];
            }
        }
        break;
    case 2://for loaf
        for (i = a; i <a + 4; i++){
            for (j = b; j <b + 4; j++){

                array[i][j] = loaf[i - a][j - b];
            }
        }
        break;
    case 3://for boat
        for (i = a; i <a + 3; i++){
            for (j = b; j <b + 3; j++){

                array[i][j] = boat[i - a][j - b];
            }
        }
        break;
    case 4://beehive
        for(i = a; i <a + 3; i++){
          for(j = b; j <b + 4; j++){
            array[i][j] = beehive[i-a][j-b];
          }
        }
        break;
    case 5://blinker
        for(i=a;i<a+1;i++){
          for(j=b;j<b+3;j++){
            array[i%35][j%85] = blinker[i-a][j-b];
          }
        }
        break;
    case 6://beacon
        for(i=a;i<a+4;i++){
          for(j=b;j<b+4;j++){
            array[i%35][j%85] = beacon[i-a][j-b];
          }
        }
        break;
    case 7://Toad
        for(i=a;i<a+2;i++){
          for(j=b;j<b+4;j++){
            array[i%35][j%85] = toad[i-a][j-b];
          }
        }
        break;
    case 8://Pulsar
        for(i=a;i<a+15;i++){
          for(j=b;j<b+15;j++){
            array[i%35][j%85] = pulsar[i-a][j-b];
          }
        }
        break;
        case 9://glider
        for(i=a;i<a+3;i++){
          for(j=b;j<b+3;j++){
            array[i%35][j%85] = glider[i-a][j-b];
          }
        }
        break;
        case 10://spaceship
        for(i=a;i<a+4;i++){
          for(j=b;j<b+5;j++){
            array[i%35][j%85] = spaceship[i-a][j-b];
          }
        }
        break;
        case 11://gosper glider gun
        for(i=a;i<a+15;i++){
          for(j=b;j<b+38;j++){
            array[i][j] = gosper_glider_gun[i-a][j-b];
          }
        }
        break;

    default:
            printf("Enter a valid choice i.e. from 1 to 11: ");
            goto retake_seed_type;
    }
    printf("\nEnter the number of generations(-1 for infinite): ");
    scanf_s("%d", &generation);
    for (i = 1; i <= generation; i++){
        system("cls");
        neighbour_manager();
        printf("GENERATION NUMBER: %d\n", i);
        generation_printer();
        Sleep(1500);
    }
    if (generation == -1)
    {int z=0;
        while (!_kbhit())
            {
            system("cls");
            neighbour_manager();
            generation_printer();
            z++;
            printf("GENERATION NUMBER: %d\n", z);
            printf("Press any key to stop.\n\n\n\n\n");
            Sleep(1500);
            }

    }
    int choice_after_execution=0;
   printf("\n\nAll generations have been generated.\nPress 1 to Restart.\nPress 2 to Exit.\nYour Choice: ");
   after_generation_valid_choice:
   scanf("%d",&choice_after_execution);
   if(choice_after_execution==1)
    goto start;
   if(choice_after_execution==2)
        {
            printf("Thank you for using this program.");
            Sleep(2000);//for dramatic purposes
            goto exit;//if user decides to exit the program then skip system pause and just exit
        }
   else
    {
        printf("Enter a valid choice: ");
        goto after_generation_valid_choice;
    }

    exit:
    exit(0);
}

void neighbour_manager(){
    int i, j;

    int neighbour;
    for ( i = 0; i < 35; i++){
        for ( j = 0; j < 85; j++){

            neighbour = 0;
            if (array[i - 1 < 0 ? 34 : i - 1][j - 1 < 0 ? 84 : j - 1] == live)   neighbour = neighbour + 1;
            if (array[i - 1 < 0 ? 34 : i - 1][j] == live)    neighbour = neighbour + 1;
            if (array[i - 1 < 0 ? 34 : i - 1][(j + 1) % 85] == live)    neighbour = neighbour + 1;
            if (array[i][j - 1 < 0 ? 84 : j - 1] == live)     neighbour = neighbour + 1;
            if (array[i][(j + 1) % 85] == live)     neighbour = neighbour + 1;
            if (array[(i + 1) % 35][j - 1 < 0 ? 84 : j - 1] == live) neighbour = neighbour + 1;
            if (array[(i + 1) % 35][j] == live) neighbour = neighbour + 1;
            if (array[(i + 1) % 35][(j + 1) % 85] == live) neighbour = neighbour + 1;


            if(neighbour == 3)
            {
                array1[i][j] = live;
            }
            else if (neighbour < 2 || neighbour > 3)
            {
                array1[i][j] = dead;
            }
            else
            {
                array1[i][j] = array[i][j];
            }
        }
    }
    for(i=0; i<35; i++){
        for(j=0; j<85; j++){
            array[i][j] = array1[i][j];
            array1[i][j] = ' ';
        }
    }
    return;
}


void generation_printer()
{
    int i,j;
    for (i = 0; i < 35; i++) {
        for (j = 0; j < 85; j++) {
            printf("%c", array[i][j]);
        }
        printf("\n");
    }

}

Solution

  • Here's a slight modification of your generation_printer() function that should print a little border around the output:

    // It's a good idea to extract the size of your grid to constants that you
    // can easily tweak.
    const int kLineWidth = 85;
    const int kLineHeight = 35;
    
    void generation_printer()
    {
        int i, j;
        // Top border
        for (i = 0; i < kLineWidth + 2; i++) {
            printf("*");
        }
        printf("\n");
        for (i = 0; i < kLineHeight; i++) {
            // Star to the beginning of the line
            printf("*");
            // Contents of the line
            for (j = 0; j < kLineWidth; j++) {
                printf("%c", array[i][j]);
            }
            // Star at the end of the line
            printf("*\n");
        }
        // Bottom border
        for (i = 0; i < kLineWidth + 2; i++) {
            printf("*");
        }
        printf("\n");
    }
    

    Regarding the goto statement, there are much cleaner ways to handle control flow! Start by splitting your main() into several smaller functions, and use while or do... while loops to repeat sections in case of invalid choices.

    Also, _kbhit() is a Windows-specific function and should be replaced so that your code is more portable (i.e. can run on several operating systems).