Untitled

 avatar
unknown
plain_text
a year ago
3.1 kB
3
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

void clear_terminal() {
    printf("\033[0d\033[2J");
}

void wait(int n) {
    usleep(n * 1000); // Ожидание в миллисекундах
}

char getch(void) {
    char buf = 0;
    struct termios old = {0};
    if (tcgetattr(0, &old) < 0) perror("tcgetattr()");
    old.c_lflag &= ~(ICANON | ECHO);
    old.c_cc[VMIN] = 1;
    old.c_cc[VTIME] = 0;
    if (tcsetattr(0, TCSANOW, &old) < 0) perror("tcsetattr ICANON");
    if (read(0, &buf, 1) < 0) perror("read()");
    old.c_lflag |= ICANON | ECHO;
    if (tcsetattr(0, TCSADRAIN, &old) < 0) perror("tcsetattr ~ICANON");
    return buf;
}

int create_field(int ***field, int width, int height) {
    *field = calloc(height, sizeof(int*));
    if (*field == NULL) {
        return 0;
    }
    for (int y = 0; y < height; ++y) {
        (*field)[y] = calloc(width, sizeof(int));
        if ((*field)[y] == NULL) {
            while (--y >= 0) free((*field)[y]);
            free(*field);
            return 0;
        }
    }
    return 1;
}

void free_field(int ***field, int height) {
    if (*field != NULL) {
        for (int y = 0; y < height; ++y) {
            free((*field)[y]);
        }
        free(*field);
        *field = NULL;
    }
}

void render(int **field, int width, int height) {
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            printf("%c", field[y][x] ? '*' : ' ');
        }
        printf("\n");
    }
}

void update(int ***field, int width, int height) {
    int **next_state = calloc(height, sizeof(int*));
    for (int y = 0; y < height; ++y) {
        next_state[y] = calloc(width, sizeof(int));
        for (int x = 0; x < width; ++x) {
            int alive_neighbors = 0;
            for (int i = -1; i <= 1; i++) {
                for (int j = -1; j <= 1; j++) {
                    if (i == 0 && j == 0) continue;
                    int nx = (x + i + width) % width;
                    int ny = (y + j + height) % height;
                    alive_neighbors += (*field)[ny][nx];
                }
            }
            int cell = (*field)[y][x];
            next_state[y][x] = alive_neighbors == 3 || (cell && alive_neighbors == 2);
        }
    }
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            (*field)[y][x] = next_state[y][x];
        }
        free(next_state[y]);
    }
    free(next_state);
}

void get_input(int *n) {
    char ch = getch();
    switch(ch) {
        case 'q': exit(0);
        case 'a': *n = (*n > 100 ? *n - 100 : *n); break;
        case 'z': *n += 100; break;
    }
}

int main(void) {
    int **field = NULL;
    int width = 80, height = 25, n = 1000;
    if (!create_field(&field, width, height)) {
        fprintf(stderr, "Ошибка создания поля.\n");
        return EXIT_FAILURE;
    }

    while (1) {
        clear_terminal();
        get_input(&n);
        update(&field, width, height);
        render(field, width, height);
        wait(n);
    }

    free_field(&field, height);
    return 0;
}
Leave a Comment