cconways-game-of-life

The program just stoped working when i type in the percentage


my problem is that in the following C-CODE nothing happens after i type in what percentage of cells should live at the start

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#pragma warning (disable: 4996)

#define MAX_ROWS 20
#define MAX_COLS 30

typedef struct {
    char data[MAX_ROWS][MAX_COLS];
    int rows;
    int cols;
} Matrix;

char neighbor_count(Matrix* m, int row, int col) {
    int count = 0;
    for (int i = row - 1; i <= row + 1; i++) {
        if (i < 0 || i >= m->rows) {
            continue;
        }
        for (int j = col - 1; j <= col + 1; j++) {
            if (j < 0 || j >= m->cols) {
                continue;
            }
            if (m->data[i][j] == '*' && (i != row || j != col)) {
                count++;
            }
        }
    }
    return count;
}

void check_cell(Matrix* m, int row, int col) {
    char neighbors_count = neighbor_count(m, row, col);
    char current_cell = m->data[row][col];

    if (neighbors_count < 2) { //Die Zelle stirbt an Vereinsamung
        m->data[row][col] = ' ';
    }
    else if (neighbors_count > 3 && current_cell == '*') { //Die Zelle stirbt an Übervölkerung
        m->data[row][col] = ' ';
    }
    else if (neighbors_count == 3 && current_cell == ' ') { //Aus der toten Zelle wird eine neue lebende Zelle
        m->data[row][col] = '*';
    }
    else if (neighbors_count == 2 || neighbors_count == 3) { //Die Zelle lebt weiter
        m->data[row][col] = '*';
    }
}

void load_from_file(Matrix* m, const char* filename) {
    FILE* f = fopen(filename, "r");

    if (f == NULL) {
        printf("File not found\n");
        exit(-1);
    }

    int row_idx = 0;
    char ch;
    while ((ch = fgetc(f)) != EOF && row_idx < MAX_ROWS) {
        if (ch == '\n') {
            row_idx++;
            continue;
        }
        #
            m->data[row_idx][m->cols] = ch;
        m->cols++;
    }
    m->rows = row_idx;
    fclose(f);
}

void randomize(Matrix* m, int percent) {
    m->rows = MAX_ROWS;
    m->cols = MAX_COLS;
    int cells = (m->rows * m->cols) * (percent / 100.0f);
    srand(time(NULL));
    while (cells > 0) {
        int row = rand() % m->rows;
        int col = rand() % m->cols;
        if (m->data[row][col] == ' ') {
            m->data[row][col] = '*';
            cells--;
        }
    }
}

void print_matrix(Matrix* m) {
    for (int i = 0; i < m->rows; i++) {
        for (int j = 0; j < m->cols; j++) {
            printf("%c", m->data[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

void step(Matrix* m) {
    Matrix m_tmp = *m;
    for (int i = 0; i < m->rows; i++) {
        for (int j = 0; j < m->cols; j++) {
            check_cell(&m_tmp, i, j);
        }
    }
    *m = m_tmp;
}

int main() {
    Matrix m;

    // Menü zur Auswahl des Startzustands
    printf("1. Aus Datei laden\n");
    printf("2. Zufallszustand generieren\n");
    int selection;
    scanf("%d", &selection);

    switch (selection) {
    case 1: // Aus Datei laden
    {
        char  filename[20]; 
        printf("Bitte Dateinamen angeben: ");
        scanf("%s", filename);
        load_from_file(&m, filename);
        break;
    }
    case 2: // Zufallszustand generieren
    {
        int percent;
        printf("Prozentualer Anteil an lebenden Zellen: ");
        scanf("%d", &percent);
        randomize(&m, percent);
        break;
    }
    default:
        printf("Ungültige Eingabe\n");
        return 0;
    }

    // Menü zur Auswahl der Animation
    printf("1. Schrittweise Animation\n");
    printf("2. Fließende Animation\n");
    scanf("%d", &selection);

    switch (selection) {
    case 1: // Schrittweise Animation
        while (1) {
            print_matrix(&m);
            step(&m);
            getchar();
        }
        break;
    case 2: // Fließende Animation
        while (1) {
            print_matrix(&m);
            step(&m);
            Sleep(200);
        }
        break;
    default:
        printf("Ungültige Eingabe\n");
        break;
    }

    return 0;
}

Translation:

1.load from file
2.  Generate Random State
2
Percentage of living cells: 10%

enter image description here

first i tought i just choose a number that is too high but i waitet like 30 minutes an nothing happend


Solution

  • The problem is that your matrix data is not initialized. It just contains random data or zeros. Because of this if (m->data[row][col] == ' ') might never be true, leading to an infinite loop. When I modified the print routine and the chosen case like this:

    void print_matrix(Matrix* m) {
        for (int i = 0; i < MAX_ROWS; i++) {
            for (int j = 0; j < MAX_COLS; j++) {
                    printf("%d ", (int)m->data[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    

    and

    case 2: // Zufallszustand generieren
        {
            int percent;
            printf("Prozentualer Anteil an lebenden Zellen: ");
            int scanResult = scanf("%d", &percent);
            printf("scanf returned %d, percent value %d\n", scanResult, percent);
            print_matrix(&m);
            randomize(&m, percent);
            printf("randomization done\n");
            break;
        }
    

    The output in some online compiler is

    1. Aus Datei laden
    2. Zufallszustand generieren
    2
    Prozentualer Anteil an lebenden Zellen: 10%
    scanf returned 1, percent value 10
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 126 -86 85 -126 127 0 0 22 -121 64 -94 -45 102 
    0 0 0 0 0 0 0 0 0 0 -112 113 -82 85 -126 127 0 0 -8 -1 -1 -1 -1 -1 -1 -1 -128 31 -83 85 
    -126 127 0 0 -64 -38 -96 109 -3 127 0 0 -69 -57 -85 85 -126 127 0 0 0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 -44 108 56 -23 82 -86 -1 -1 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 
    1 0 0 0 0 0 0 0 0 119 -82 85 -126 127 0 0 64 -123 -86 85 -126 127 0 0 96 113 -82 85 -126 127 
    0 0 1 -39 -96 109 -3 127 0 0 -24 105 -82 85 -126 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 -78 
    -81 109 -3 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 -10 117 -82 3 1 0 
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 2 
    0 0 64 3 0 0 64 3 0 0 64 3 0 0 -128 3 0 0 -128 5 0 0 -128 9 0 0 -128 9 0 0 
    -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 
    0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 
    -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 -128 9 0 0 0 0 
    0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 64 0 0 0 0 2 0 0 0 4 0 0 
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 64 -112 -57 22 -83 85 0 0 -1 -75 -16 0 0 0 0 0 -62 0 0 0 0 0 0 0 -25 -38 
    -96 109 -3 127 0 0 -26 -38 -96 109 -3 127 0 0 -115 -86 -57 22 -83 85 0 0 -24 98 -86 85 -126 127 0 0 
    
    

    A possible solution would be to insert

    memset(m->data, (int)' ', MAX_COLS*MAX_ROWS);
    

    into randomize before entering the loop.

    This way the output up until the end of case 2 is (without the print_matrix modification)

    1. Aus Datei laden
    2. Zufallszustand generieren
    2
    Prozentualer Anteil an lebenden Zellen: 10%
    scanf returned 1, percent value 10
       *  *              *        
                            *     
    *                        *    
       *           *     *        
                 *  *        *    
                *   *         *   
                  **         *   *
                  *      *       *
             *    *       *       
    **     *          *           
              *         *    **   
        *                         
                    **  *      *  
    *  *  *   *      *       *    
             *                    
                                  
         *               *        
             *      *             
            *      **  * *  **** *
                *                 
    
    randomization done
    

    Lastly, if you typed in a percent character after the value the next scanf under // Menü zur Auswahl der Animation tries to parse this as an integer and fails. You can see this when you print the return value of scanf which will be 0 because it couldn't parse the requested integer.

    If you want the user to input a percent character you can modify the scanf request:

    printf("Prozentualer Anteil an lebenden Zellen: ");
    scanf("%d%%", &percent);
    

    But then not inputting a percent character will stall.