Загрузка данных
#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 elapsed = 0;
int key = ERR;
nodelay(stdscr, TRUE);
while (key != ' ') {
draw_field(field, delay);
key = getch();
delay = change_speed(key, delay);
if (key != ' ') {
napms(20);
if (LINES >= HEIGHT + 1 && COLS >= WIDTH) {
elapsed += 20;
if (elapsed >= delay) {
next_generation(field);
elapsed = 0;
}
} else {
elapsed = 0;
}
}
}
}
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;
}