Werks
This commit is contained in:
parent
cc2ce40642
commit
226bc2b340
123
src/life.cpp
123
src/life.cpp
@ -12,6 +12,8 @@
|
||||
const char *const FORMAT_UNDERSCORE = "\033[4m";
|
||||
const char *const END_FORMATTING = "\033[0m";
|
||||
|
||||
const int ANIMATION_SLEEP_MS = 100, ANIMATION_N_GENERATIONS = 20;
|
||||
|
||||
void printWelcome() {
|
||||
std::cout << "Welcome to the TDDD86 Game of Life,\n"
|
||||
<< "a simulation of the lifecycle of a bacteria colony.\n"
|
||||
@ -52,17 +54,19 @@ std::string fileRead(const char *filePath) {
|
||||
return content;
|
||||
}
|
||||
|
||||
enum UserAction { NO_ACTION, ACTION, TICK, QUIT };
|
||||
enum UserAction { ANIMATE, TICK, QUIT };
|
||||
|
||||
UserAction askUserForAction() {
|
||||
std::string userInput = input("a)nimate, t)ick, q)uit? ");
|
||||
if (userInput == "a")
|
||||
return UserAction::ACTION;
|
||||
else if (userInput == "t")
|
||||
return UserAction::TICK;
|
||||
else if (userInput == "q")
|
||||
return UserAction::QUIT;
|
||||
return UserAction::NO_ACTION;
|
||||
UserAction askUserForANIMATE() {
|
||||
while (true) {
|
||||
std::string userInput = input("a)nimate, t)ick, q)uit? ");
|
||||
if (userInput == "a")
|
||||
return UserAction::ANIMATE;
|
||||
else if (userInput == "t")
|
||||
return UserAction::TICK;
|
||||
else if (userInput == "q")
|
||||
return UserAction::QUIT;
|
||||
std::cout << "The input '" << userInput << "' is an invalid option!\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string &s, const char at) {
|
||||
@ -81,6 +85,75 @@ std::vector<std::string> split(const std::string &s, const char at) {
|
||||
|
||||
enum Cell { ALIVE, DEAD };
|
||||
|
||||
void gridPrint(Grid<Cell> &grid) {
|
||||
std::stringstream ss;
|
||||
|
||||
for (int idxRow = 0; idxRow < grid.numRows(); idxRow++) {
|
||||
for (int idxCol = 0; idxCol < grid.numCols(); idxCol++) {
|
||||
char sign = grid.get(idxRow, idxCol) == Cell::ALIVE ? 'X' : '-';
|
||||
ss << sign;
|
||||
}
|
||||
if (idxRow == grid.numRows() - 1)
|
||||
ss << std::endl;
|
||||
else
|
||||
ss << '\n';
|
||||
}
|
||||
|
||||
std::cout << ss.str();
|
||||
}
|
||||
|
||||
int gridAliveNeighbors(Grid<Cell> &grid, int row, int col) {
|
||||
int alive = 0;
|
||||
for (int rowDelta = -1; rowDelta <= 1; rowDelta++) {
|
||||
int checkRow = row + rowDelta;
|
||||
// Skip out of bounds
|
||||
if (checkRow < 0 || checkRow >= grid.numRows())
|
||||
continue;
|
||||
|
||||
for (int colDelta = -1; colDelta <= 1; colDelta++) {
|
||||
// Don't check the original piece
|
||||
if (rowDelta == 0 && colDelta == 0)
|
||||
continue;
|
||||
int checkCol = col + colDelta;
|
||||
// Skip out of bounds
|
||||
if (checkCol < 0 || checkCol >= grid.numCols())
|
||||
continue;
|
||||
if (grid.get(checkCol, checkRow) == Cell::ALIVE)
|
||||
alive++;
|
||||
}
|
||||
}
|
||||
|
||||
return alive;
|
||||
}
|
||||
/**
|
||||
* Run one Game of Life tick.
|
||||
* Cells (X) live and die by the following rules:
|
||||
* - A cell with 1 or fewer neighbours dies.
|
||||
* - Locations with 2 neighbours remain stable.
|
||||
* - Locations with 3 neighbours will create life.
|
||||
* - A cell with 4 or more neighbours dies.
|
||||
*/
|
||||
Grid<Cell> gridTick(Grid<Cell> &grid) {
|
||||
Grid<Cell> nextGrid = grid;
|
||||
|
||||
for (int row = 0; row < grid.numRows(); row++) {
|
||||
for (int col = 0; col < grid.numCols(); col++) {
|
||||
int alive = gridAliveNeighbors(grid, row, col);
|
||||
|
||||
if (alive == 1)
|
||||
nextGrid.set(row, col, Cell::DEAD);
|
||||
else if (alive == 2)
|
||||
nextGrid.set(row, col, grid.get(row, col));
|
||||
else if (alive == 3)
|
||||
nextGrid.set(row, col, Cell::ALIVE);
|
||||
else if (alive == 4)
|
||||
nextGrid.set(row, col, Cell::DEAD);
|
||||
}
|
||||
}
|
||||
|
||||
return nextGrid;
|
||||
}
|
||||
|
||||
int main() {
|
||||
printWelcome();
|
||||
|
||||
@ -103,10 +176,10 @@ int main() {
|
||||
std::cerr << "No column, row header, in the file!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
int columns, rows;
|
||||
int rows, columns;
|
||||
try {
|
||||
columns = std::stoi(lines[0]);
|
||||
rows = std::stoi(lines[1]);
|
||||
rows = std::stoi(lines[0]);
|
||||
columns = std::stoi(lines[1]);
|
||||
} catch (const std::invalid_argument &e) {
|
||||
std::cerr << "Column or row wasn't a number" << std::endl;
|
||||
return 1;
|
||||
@ -122,7 +195,7 @@ int main() {
|
||||
|
||||
Grid<Cell> grid(columns, rows);
|
||||
for (int x = 0; x < rows; x++) {
|
||||
std::string &row = lines[x];
|
||||
std::string &row = lines[x + 2];
|
||||
if (columns < row.size()) {
|
||||
std::cerr << "There's less columns, than described in the header!"
|
||||
<< std::endl;
|
||||
@ -146,6 +219,28 @@ int main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
gridPrint(grid);
|
||||
|
||||
UserAction ANIMATE;
|
||||
while ((ANIMATE = askUserForANIMATE()) != UserAction::QUIT) {
|
||||
// We don't have to handle QUIT, since we do in the while check
|
||||
switch (ANIMATE) {
|
||||
case UserAction::TICK:
|
||||
grid = gridTick(grid);
|
||||
gridPrint(grid);
|
||||
break;
|
||||
case UserAction::ANIMATE:
|
||||
for (int i = 0; i < ANIMATION_N_GENERATIONS; i++) {
|
||||
grid = gridTick(grid);
|
||||
clearConsole();
|
||||
gridPrint(grid);
|
||||
pause(ANIMATION_SLEEP_MS);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Have a nice Life!" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user