Загрузка данных


#include <ctype.h>
#include <ncurses.h>
#include <stdio.h>

#define WIDTH 80
#define HEIGHT 25

int read_field(int field[HEIGHT][WIDTH]);
int count_neighbors(const int field[HEIGHT][WIDTH], int y, int x);
void next_generation(int field[HEIGHT][WIDTH]);
void draw_field(const int field[HEIGHT][WIDTH], int delay);
int change_speed(int key, int delay);
void play(int field[HEIGHT][WIDTH]);
int run_game(int field[HEIGHT][WIDTH]);

int main(void) {
    int field[HEIGHT][WIDTH] = {0};
    int result = 0;
    if (!read_field(field)) {
        fprintf(stderr, "Invalid input: expected 2000 cells (0 or 1).\n");
        result = 1;
    } else if (!run_game(field)) {
        fprintf(stderr, "Cannot start: terminal must be at least 80x26.\n");
        result = 1;
    }
    return result;
}

int read_field(int field[HEIGHT][WIDTH]) {
    int count = 0;
    int valid = 1;
    int ch = getchar();
    while (ch != EOF && valid) {
        if (!isspace(ch)) {
            if ((ch == '0' || ch == '1') && count < HEIGHT * WIDTH) {
                field[count / WIDTH][count % WIDTH] = ch - '0';
                count++;
            } else {
                valid = 0;
            }
        }
        if (valid) ch = getchar();
    }
    return valid && count == HEIGHT * WIDTH && !ferror(stdin);
}

int count_neighbors(const int field[HEIGHT][WIDTH], int y, int x) {
    int count = 0;
    for (int dy = -1; dy <= 1; dy++) {
        for (int dx = -1; dx <= 1; dx++) {
            if (dy != 0 || dx != 0) {
                count += field[(y + dy + HEIGHT) % HEIGHT][(x + dx + WIDTH) % WIDTH];
            }
        }
    }
    return count;
}

void next_generation(int field[HEIGHT][WIDTH]) {
    int next[HEIGHT][WIDTH] = {0};
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            int neighbors = count_neighbors(field, y, x);
            next[y][x] = neighbors == 3 || (field[y][x] && neighbors == 2);
        }
    }
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            field[y][x] = next[y][x];
        }
    }
}

void draw_field(const int field[HEIGHT][WIDTH], int delay) {
    erase();
    if (LINES >= HEIGHT + 1 && COLS >= WIDTH) {
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                mvaddch(y, x, field[y][x] ? 'O' : '.');
            }
        }
        mvprintw(HEIGHT, 0, "A: faster | Z: slower | Space: quit | Delay: %d ms", delay);
    } else {
        printw("Resize terminal to 80x26. Space: quit");
    }
    refresh();
}

int change_speed(int key, int delay) {
    if ((key == 'a' || key == 'A') && delay > 20) {
        delay -= 20;
    } else if ((key == 'z' || key == 'Z') && delay < 1000) {
        delay += 20;
    }
    return delay;
}

void play(int field[HEIGHT][WIDTH]) {
    int delay = 200;
    int key = ERR;
    while (key != ' ') {
        draw_field(field, delay);
        timeout(delay);
        key = getch();
        delay = change_speed(key, delay);
        if (key == ERR && LINES >= HEIGHT + 1 && COLS >= WIDTH) {
            next_generation(field);
        }
    }
}

int run_game(int field[HEIGHT][WIDTH]) {
    int success = 0;
    FILE *keyboard = fopen("/dev/tty", "r");
    SCREEN *screen = NULL;
    if (keyboard != NULL) screen = newterm(NULL, stdout, keyboard);
    if (screen != NULL) {
        cbreak();
        noecho();
        curs_set(0);
        if (LINES >= HEIGHT + 1 && COLS >= WIDTH) {
            play(field);
            success = 1;
        }
        endwin();
        delscreen(screen);
    }
    if (keyboard != NULL) fclose(keyboard);
    return success;
}