Задание № 2: Играем в жизнь
В ходе разработки я написал программу, которая играет сама с собой в жизнь Конвея (http://ru.wikipedia.org/wiki/Жизнь_(игра)). К моему глубочайшему сожалению, часть файлов затёрлась, а именно ключевая часть программы, где реализованы 3 важные функции. Я не помню, что это за функции, и как они работали.
Ваша задача: восстановить утерянные куски кода.
Пример работы программы
Программа меняет своё состояние по правилам, описанным по ссылке. Дальше я привожу пример того, как выглядело поле после смены трёх эпох:
Эпоха 1 Эпоха 2 Эпоха 3 | | | * | | * *| | | | | | | | * | => | | => | | | *| | * *| | *| | * * *| | * *| | * *| -------------------------------------------- | | | * | | * *| <- Дополнительная строка для наглядности, вообще, она сверху ;-)
Исходный код
Обратите внимание, что в некоторых случаях код может отличаться в зависимости от вашей платформы и используемого компилятора. Так, например, вместо time.h необходимо использовать unistd.h, если вы работаете под OS X Maverics с компилятором clang.
main.cpp
#include "game.h"
#include "console.h"
#include <time.h>
// Start program
int main()
{
// Set rows and cols of the future field
size_t rows = 20, cols = 40;
// Get a blank field
matrix *field = Game::getBlankField(rows, cols);
// Some magic things for getting random numbers
srand(time(NULL));
// Set randomly alive or dead cell
for (uint i = 0; i < rows; i++) {
for (uint j = 0; j < cols; j++) {
field->at(i).at(j) = rand() % 2;
}
}
// 1000 times will be shown
for (uint i = 0; i < 1000; i++) {
// Clear console
Console::clearUnix();
// Draw the field into console
Console::drawField(*field);
// Save the current field...
matrix *oldField = Game::getBlankField(rows, cols);
Game::copy(*oldField, *field);
// ...and update field
Game::step(*field);
// Check if life is frozen. If so break the loop
if (Game::isEqual(*oldField, *field))
break;
// Sleep time
usleep(250 * 1000);
}
return 0;
}
console.h
#include <iostream>
#include <cstdlib>
#include <vector>
typedef std::vector<std::vector<bool> > matrix;
typedef unsigned int uint;
/* Utils for working with console */
namespace Console {
// Clear console in *nix
void clearUnix() {
system("clear");
}
// Clear console in Windows™
void clearWin() {
system("cls");
}
// Let's draw the field into console space!
void drawField(matrix &field) {
// For each row...
for (uint i = 0; i < field.size(); i++) {
// ...draw first '|'...
std::cout << '|';
// ...then for each value in row...
for (uint j = 0; j < field[0].size(); j++) {
// ...draw '*' if the cell is alive, ' ' otherwise...
std::cout << (field[i][j] ? '*' : ' ') << ' ';
}
// ...close row with '|'
std::cout << "|\n";
}
}
}
game.h
#include <vector>
typedef std::vector<std::vector<bool> > matrix;
typedef unsigned int uint;
/* Functions implement game logic */
namespace Game {
// Returns blaaaank field where nobody is alive
matrix *getBlankField(size_t rows, size_t cols) {
matrix *field = new matrix();
// Add rows...
for (uint i = 0; i < rows; i++) {
field->push_back(std::vector<bool>());
// ... and values into the row
for (uint j = 0; j < cols; j++) {
(field->at(i)).push_back(false);
}
}
return field;
}
// Returns rows number
size_t getRows(const matrix &field) {
return field.size();
}
// Returns cols number
size_t getCols(const matrix &field) {
if (getRows(field) != 0) {
return field[0].size();
}
return -1;
}
// ======================= YOUR CODE HERE =======================
// ==============================================================
}
Makefile
all: g++ main.cpp -o ./life
Результат выглядит примерно так
Дополнительный материал
Написание Makefile: http://habrahabr.ru/post/155201