Advertisement
Kienan

Игра в жизнь <3

Jul 18th, 2025
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.42 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h> // нужно для рандома. Удалить, когда будет готова загрузка из файлов
  4. #include <unistd.h>
  5.  
  6. #define TRUE 1
  7. #define FALSE 0
  8.  
  9. #define WIDTH 80
  10. #define HEIGHT 25
  11.  
  12. #define ALIVE 'O'
  13. #define DEAD ' '
  14.  
  15. #define MIN_NEIGHBORS_TO_SURVIVE 2    // Мин. соседей для выживания (≥ 2)
  16. #define MAX_NEIGHBORS_TO_SURVIVE 3    // Макс. соседей для выживания (≤ 3)
  17. #define NEIGHBORS_TO_REBORN 3    // Точно 3 соседа для рождения
  18.  
  19. #define MAX_SPEED_RATIO 3 // максимум ускоряемся до 3x
  20. #define MIN_SPEED_RATIO 0.25f  // минимум замедляемся до 0.25x
  21. #define SPEED_RATIO_STEP 0.25f  // шаг ускорения
  22. #define BASE_GENERATION_DELAY 100000
  23.  
  24. void initialize_grid_randomly(char grid[HEIGHT][WIDTH]); // временное рандомное заполнение. Удалить, когда будет готова загрузка из файлов
  25. void load_grid_from_file(char grid[HEIGHT][WIDTH]);
  26. void draw_grid(char grid[HEIGHT][WIDTH]);
  27. void update_grid(char grid[HEIGHT][WIDTH]);
  28. int get_alive_neighbors_count(char grid[HEIGHT][WIDTH], int x, int y);
  29. char update_cell_status(char current_status, int neighbors_count);
  30. void update_input(int *need_simulate, float *speed_ratio);
  31.  
  32. int main() {
  33.     char grid[HEIGHT][WIDTH];
  34.     initialize_grid_randomly(grid); // временное рандомное заполнение. Удалить, когда будет готова загрузка из файлов
  35.     // load_grid_from_file(grid);
  36.  
  37.     float speed_ratio = 1;
  38.     int need_simulate = TRUE;
  39.  
  40.     while (need_simulate == TRUE) {
  41.         draw_grid(grid);
  42.         update_grid(grid);
  43.  
  44.         int generation_delay = (int) (speed_ratio * BASE_GENERATION_DELAY);
  45.         usleep(generation_delay);
  46.  
  47.         update_input(&need_simulate, &speed_ratio);
  48.     }
  49.  
  50.     return 0;
  51. }
  52.  
  53. void initialize_grid_randomly(char grid[HEIGHT][WIDTH]) { // временное рандомное заполнение. Удалить, когда будет готова загрузка из файлов
  54.     srand(time(0));
  55.     for (int y = 0; y < HEIGHT; y++) {
  56.         for (int x = 0; x < WIDTH; x++) {
  57.             grid[y][x] = (rand() % 5 == 0) ? ALIVE : DEAD;
  58.         }
  59.     }
  60. }
  61.  
  62. void load_grid_from_file(char grid[HEIGHT][WIDTH]) {
  63.     // TODO: Сделать логику загрузки поля из файла
  64. }
  65.  
  66. void update_input(int *need_simulate, float *speed_ratio) {
  67.     // TODO: Если нажат Space, то need_simulate = false
  68.  
  69.     // TODO: Если нажат A, то *speed_ratio += SPEED_RATIO_STEP
  70.     // TODO: Если нажат Z, то *speed_ratio -= SPEED_RATIO_STEP
  71.  
  72.     if (*speed_ratio < MIN_SPEED_RATIO) {
  73.         *speed_ratio = MIN_SPEED_RATIO;
  74.     } else if (*speed_ratio > MAX_SPEED_RATIO) {
  75.         *speed_ratio = MAX_SPEED_RATIO;
  76.     }
  77. }
  78.  
  79.  
  80. void draw_grid(char grid[HEIGHT][WIDTH]) {
  81.     printf("\n\n===================================================\n\n");
  82.  
  83.     for (int y = 0; y < HEIGHT; y++) {
  84.         for (int x = 0; x < WIDTH; x++) {
  85.             printf("%c", grid[y][x]);
  86.         }
  87.         printf("\n");
  88.     }
  89. }
  90.  
  91. int get_alive_neighbors_count(char grid[HEIGHT][WIDTH], int x, int y) {
  92.     int alive_neighbors_count = 0;
  93.     for (int delta_y = -1; delta_y <= 1; delta_y++) {
  94.         for (int delta_x = -1; delta_x <= 1; delta_x++) {
  95.  
  96.             // Пропускаем текущую клетку
  97.             if (delta_x == 0 && delta_y == 0)
  98.                 continue;
  99.  
  100.             int neighbor_x = x + delta_x;
  101.             int neighbor_y = y + delta_y;
  102.  
  103.             // Проверка границ (тороидальная вселенная). Благодаря этому мир "зациклен" по краям
  104.             if (neighbor_x < 0) neighbor_x = WIDTH - 1;
  105.             if (neighbor_x >= WIDTH) neighbor_x = 0;
  106.             if (neighbor_y < 0) neighbor_y = HEIGHT - 1;
  107.             if (neighbor_y >= HEIGHT) neighbor_y = 0;
  108.  
  109.             if (grid[neighbor_y][neighbor_x] == ALIVE)
  110.                 alive_neighbors_count++;
  111.         }
  112.     }
  113.     return alive_neighbors_count;
  114. }
  115.  
  116. void update_grid(char grid[HEIGHT][WIDTH]) {
  117.     char updated_grid[HEIGHT][WIDTH];
  118.  
  119.     for (int y = 0; y < HEIGHT; y++) {
  120.         for (int x = 0; x < WIDTH; x++) {
  121.             int neighbors = get_alive_neighbors_count(grid, x, y);
  122.             updated_grid[y][x] = update_cell_status(grid[y][x], neighbors);
  123.         }
  124.     }
  125.  
  126.     for (int y = 0; y < HEIGHT; y++) {
  127.         for (int x = 0; x < WIDTH; x++) {
  128.             grid[y][x] = updated_grid[y][x];
  129.         }
  130.     }
  131. }
  132.  
  133. // TODO: подумать, как это отрефакторить, мб стоит разбить этот метод на подметоды CanDie и CanReborn
  134. char update_cell_status(char current_status, int neighbors_count) {
  135.     char new_status = current_status;
  136.  
  137.     int should_die = current_status == ALIVE &&
  138.                     (neighbors_count < MIN_NEIGHBORS_TO_SURVIVE ||
  139.                      neighbors_count > MAX_NEIGHBORS_TO_SURVIVE);
  140.  
  141.     int should_reborn = current_status == DEAD && neighbors_count == NEIGHBORS_TO_REBORN;
  142.  
  143.     if (should_die == TRUE) {
  144.         new_status = DEAD;
  145.     } else if (should_reborn == TRUE) {
  146.         new_status = ALIVE;
  147.     }
  148.  
  149.     return new_status;
  150. }
  151.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement