#include #include #include "SDL2/SDL.h" #define HEIGHT 80 #define WIDTH 130 #define SPF 1000 / 30 void wrap(int *a, int w) { if (*a < 0) *a = w - 1; else if (*a > w - 1) *a = 0; } int place(int x, int y) { wrap(&x, WIDTH); wrap(&y, HEIGHT); return x + y * WIDTH; } int neighbors(char *cells, int x, int y) { int count = 0; for (int i = -1; i <= 1; i++) for (int j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; if (cells[place(i + x, j + y)] & 2) count++; } return count; } int resize(SDL_Renderer *r) { int w, h; SDL_GetRendererOutputSize(r, &w, &h); return w / WIDTH < h / HEIGHT ? w / WIDTH : h / HEIGHT; } char inside(int n, char *v) { char result = 0; if (n >= 0 && n <= 8) for (int i = 0; i < strlen(v); i++) { result |= (n == v[i] - 48); } return result; } void init(char *cells, char random) { for (int x = 0; x < WIDTH; x++) { for (int y = 0; y < HEIGHT; y++) { if (random) cells[place(x, y)] ^= 3 * (rand() % 2); else cells[place(x, y)] = 0; } } } int main(int argc, char **argv) { if (argc != 3) exit(1); srand(time(0)); SDL_Init(SDL_INIT_VIDEO); SDL_Window *w = SDL_CreateWindow(argv[0], 0, 0, 800, 600, SDL_WINDOW_RESIZABLE); SDL_Renderer *r = SDL_CreateRenderer(w, -1, SDL_RENDERER_ACCELERATED); int cellsize = resize(r); int oldtime = 0; int newtime = 0; char paused = 0; char grid = 1; int symtime = 0; int rendertime = 0; char cells[WIDTH * HEIGHT]; init(cells, 1); SDL_Event e = {0}; int exit = 0; while (!exit) { SDL_Delay(SPF); while (SDL_PollEvent(&e)) { if (e.window.event == SDL_WINDOWEVENT_RESIZED) cellsize = resize(r); if (e.key.state == SDL_PRESSED) { if (e.key.keysym.sym == SDLK_BACKSPACE) init(cells, 0); if (e.key.keysym.sym == SDLK_RETURN) init(cells, 1); if (e.key.keysym.sym == SDLK_SPACE) paused ^= 1; if (e.key.keysym.sym == SDLK_PERIOD) { paused = 1; symtime = SPF + 1; } if (e.key.keysym.sym == SDLK_g) { grid ^= 1; } if (e.key.keysym.sym == SDLK_q) { exit = 1; } } int mx, my; int mstate = SDL_GetMouseState(&mx, &my); if (mstate & SDL_BUTTON(SDL_BUTTON_RIGHT)) { cells[place(mx / cellsize, my / cellsize)] = 0; paused = 1; } else if (mstate & SDL_BUTTON(SDL_BUTTON_LEFT)) { cells[place(mx / cellsize, my / cellsize)] = 3; paused = 1; } }; oldtime = newtime; newtime = SDL_GetTicks(); if (!paused) symtime += newtime - oldtime; if (symtime > SPF) { symtime = 0; for (int x = 0; x < WIDTH; x++) for (int y = 0; y < HEIGHT; y++) { int n = neighbors(cells, x, y); if (inside(n, argv[1]) && ~cells[place(x, y)] & 2) cells[place(x, y)] |= 1; // Birth if (!inside(n, argv[2]) && cells[place(x, y)] & 2) cells[place(x, y)] &= 2; // Death } for (int i = 0; i < WIDTH * HEIGHT; i++) cells[i] = cells[i] & 1 ? 3 : 0; } rendertime += newtime - oldtime; if (rendertime > SPF) { rendertime = 0; SDL_SetRenderDrawColor(r, 160, 160, 160, 255); SDL_RenderClear(r); for (int x = 0; x < WIDTH; x++) for (int y = 0; y < HEIGHT; y++) { SDL_Rect rect = { x * cellsize, y * cellsize, cellsize, cellsize }; if (grid && cellsize > 1) { rect.x += 1; rect.y += 1; rect.w -= 1; rect.h -= 1; } if (cells[place(x, y)]) SDL_SetRenderDrawColor(r, 0, 0, 0, 255); else SDL_SetRenderDrawColor(r, 255, 255, 255, 255); SDL_RenderFillRect(r, &rect); } SDL_RenderPresent(r); } } SDL_DestroyRenderer(r); SDL_DestroyWindow(w); SDL_Quit(); return 0; }