186 lines
6.2 KiB
C++
186 lines
6.2 KiB
C++
|
#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();
|
||
|
}
|