life-sfml/main.cpp

186 lines
6.2 KiB
C++
Raw Permalink Normal View History

2024-08-28 21:18:40 +03:00
#include <SFML/Window.hpp>
#include <vector>
#include <SFML/Graphics.hpp>
#define ZOOM 10
using namespace std;
using namespace sf;
struct crd {
int x, y;
};
int countNeighbors (int x, int y, vector<vector<int>>* board);
bool willItSurvive (vector<int> survive, int neighborCount);
bool willItBeBorn (vector<int> birth, int neighborCount);
void check (int width, int height, vector<crd>* willBeBorn, vector<crd>* willBeDead, vector<vector<int>>* board);
void render (vector<vector<int>>* board, RenderWindow* win);
void nextStep (vector<crd>* willBeBorn, vector<crd>* willBeDead, vector<vector<int>>* board);
int main (int argc, char* argv[]) {
if (argc < 3) {
printf("Usage: %s [width] [height]", argv[0]);
exit(-1);
}
const int width = atoi(argv[1]);
const int height = atoi(argv[2]);
int fps = 60;
bool pause = false;
vector<vector<int>> board = {};
vector<crd> willBeBorn = {};
vector<crd> willBeDead = {};
for (int i = 0; i < height / ZOOM; i ++) {
board.push_back({});
for (int j = 0; j < width / ZOOM; j ++) {
board[i].push_back(0);
}
}
RenderWindow win(VideoMode(width, height), "Conway's game of life sfml");
win.setFramerateLimit(fps);
win.display();
while (win.isOpen()) {
if (!pause) {
check(width / ZOOM, height / ZOOM, &willBeBorn, &willBeDead, &board);
render(&board, &win);
nextStep(&willBeBorn, &willBeDead, &board);
} else {
render(&board, &win);
}
Event e;
while(win.pollEvent(e)) {
switch (e.type) {
case Event::Closed:
win.close();
break;
case Event::MouseWheelMoved:
if (e.mouseWheel.delta < 0 && fps > 1) fps --;
if (e.mouseWheel.delta > 0) fps ++;
break;
case Event::KeyPressed:
if (e.key.code == sf::Keyboard::P) {
pause = !pause;
}
if (e.key.code == sf::Keyboard::C) {
for (int i = 0; i < (int)board.size(); i ++) {
for (int j = 0; j < (int)board[0].size(); j ++) {
board[i][j] = 0;
}
}
}
if (e.key.code == sf::Keyboard::R) {
for (int i = 0; i < (int)board.size(); i ++) {
for (int j = 0; j < (int)board[0].size(); j ++) {
if (i % 2 != 0 || j % 2 != 0) {
board[i][j] = 1;
} else {
// board[i][j] = 0;
}
}
}
}
break;
}
}
if (Mouse::isButtonPressed(Mouse::Left)) {
int mouseX = Mouse::getPosition(win).x / ZOOM, mouseY = Mouse::getPosition(win).y / ZOOM;
if (!(mouseX < 0
|| mouseX > (int)board[0].size()
|| mouseY < 0
|| mouseY > (int)board.size())
) board[mouseY][mouseX] = 1;
}
if (Mouse::isButtonPressed(Mouse::Right)) {
int mouseX = Mouse::getPosition(win).x / ZOOM, mouseY = Mouse::getPosition(win).y / ZOOM;
if (!(mouseX < 0
|| mouseX > (int)board[0].size()
|| mouseY < 0
|| mouseY > (int)board.size())
) board[mouseY][mouseX] = 0;
}
win.setFramerateLimit(fps);
win.display();
win.clear(Color::Black);
}
return 0;
}
int countNeighbors (int x, int y, vector<vector<int>>* board) {
int count = 0;
for (int i = -1; i <= 1; i ++) {
for (int j = -1; j <= 1; j ++) {
if (i == 0 && j == 0) continue;
if (
x + i <= 0 ||
x + i >= (int)(*board)[0].size() ||
y + j <= 0 ||
y + j >= (int)(*board).size()
) continue;
if ((*board)[y + j][x + i] == 1) count ++;
}
}
return count;
}
bool willItSurvive (vector<int> survive, int neighborCount) {
for (int i = 0; i < (int)survive.size(); i ++) {
if (neighborCount == survive[i]) return true;
}
return false;
}
bool willItBeBorn (vector<int> birth, int neighborCount) {
for (int i = 0; i < (int)birth.size(); i ++) {
if (neighborCount == birth[i]) return true;
}
return false;
}
void check (int width, int height, vector<crd>* willBeBorn, vector<crd>* willBeDead, vector<vector<int>>* board) {
for (int i = 0; i < height; i ++) {
for (int j = 0; j < width; j ++) {
int neighborCount = countNeighbors(j, i, board);
if ((*board)[i][j] == 1) {
if (!willItSurvive({2,3}, neighborCount)) {
(*willBeDead).push_back({.x = j, .y = i});
}
} else if ((*board)[i][j] == 0) {
if (willItBeBorn({3}, neighborCount)) {
(*willBeBorn).push_back({.x = j, .y = i});
}
}
}
}
}
void render (vector<vector<int>>* board, RenderWindow* win) {
for (int i = 0; i < (int)(*board).size(); i ++) {
for (int j = 0; j < (int)(*board)[0].size(); j ++) {
if ((*board)[i][j] == 1) {
RectangleShape* rectangle = new RectangleShape(Vector2f(j * ZOOM, i * ZOOM));
rectangle->setPosition(Vector2f(j * ZOOM, i * ZOOM));
rectangle->setSize(Vector2f(ZOOM, ZOOM));
rectangle->setFillColor(Color::White);
win->draw(*rectangle);
delete rectangle;
}
}
}
}
void nextStep (vector<crd>* willBeBorn, vector<crd>* willBeDead, vector<vector<int>>* board) {
for (int i = 0; i < (int)(*willBeBorn).size(); i ++)
(*board)[(*willBeBorn)[i].y][(*willBeBorn)[i].x] = 1;
willBeBorn->clear();
for (int i = 0; i < (int)(*willBeDead).size(); i ++)
(*board)[(*willBeDead)[i].y][(*willBeDead)[i].x] = 0;
willBeDead->clear();
}