104 lines
2.6 KiB
C++
104 lines
2.6 KiB
C++
#include "CellularAutomaton.h"
|
|
|
|
CellularAutomaton::CellularAutomaton(int width, int height, bool fillWithRandom, BoundaryCondition boundaryCondition)
|
|
: m_fieldWidth(width), m_fieldHeight(height), m_boundaryCondition(boundaryCondition)
|
|
{
|
|
m_field.resize(m_fieldHeight, std::vector<int>(m_fieldWidth, 0));
|
|
m_fieldNextState.resize(m_fieldHeight, std::vector<int>(m_fieldWidth, 0));
|
|
|
|
if (fillWithRandom) initializeRandom();
|
|
else initializeManual();
|
|
}
|
|
|
|
|
|
void CellularAutomaton::initializeRandom()
|
|
{
|
|
std::random_device rd;
|
|
std::mt19937 gen(rd());
|
|
std::uniform_int_distribution<> dis(0, 1);
|
|
|
|
for (int y = 0; y < m_fieldHeight; ++y)
|
|
{
|
|
for (int x = 0; x < m_fieldWidth; ++x)
|
|
{
|
|
m_field[y][x] = dis(gen);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CellularAutomaton::initializeManual()
|
|
{
|
|
std::cout << "Ââåäèòå íà÷àëüíîå ñîñòîÿíèå ïîëÿ (" << m_fieldWidth << " x " << m_fieldHeight << ").\n";
|
|
std::cout << "Ââåäèòå 0 èëè 1 äëÿ êàæäîé êëåòêè.\n";
|
|
|
|
for (int y = 0; y < m_fieldHeight; ++y)
|
|
{
|
|
for (int x = 0; x < m_fieldWidth; ++x)
|
|
{
|
|
std::cout << "Êëåòêà (" << x << ", " << y << "): ";
|
|
int cellValue = inputNumber(0, 1);
|
|
|
|
m_field[y][x] = cellValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
int CellularAutomaton::getCellState(int x, int y) const
|
|
{
|
|
if (x < 0 || x >= m_fieldWidth || y < 0 || y >= m_fieldHeight)
|
|
{
|
|
switch (m_boundaryCondition)
|
|
{
|
|
case BOUNDARY_ONES:
|
|
return 1;
|
|
case BOUNDARY_ZEROS:
|
|
return 0;
|
|
case BOUNDARY_TOROIDAL:
|
|
x = (x + m_fieldWidth) % m_fieldWidth;
|
|
y = (y + m_fieldHeight) % m_fieldHeight;
|
|
return m_field[y][x];
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
return m_field[y][x];
|
|
}
|
|
|
|
int CellularAutomaton::getNeighborhoodIndex(int x, int y) const
|
|
{
|
|
int s0 = getCellState(x, y);
|
|
int s1 = getCellState(x, y - 1);
|
|
int s2 = getCellState(x, y + 1);
|
|
int s3 = getCellState(x - 1, y);
|
|
int s4 = getCellState(x + 1, y);
|
|
|
|
int index = (s0 << 4) | (s1 << 3) | (s2 << 2) | (s3 << 1) | s4;
|
|
|
|
return index;
|
|
}
|
|
|
|
void CellularAutomaton::update()
|
|
{
|
|
for (int y = 0; y < m_fieldHeight; ++y)
|
|
{
|
|
for (int x = 0; x < m_fieldWidth; ++x)
|
|
{
|
|
int neighborhood = getNeighborhoodIndex(x, y);
|
|
m_fieldNextState[y][x] = (m_functionValues >> neighborhood) & 1;
|
|
}
|
|
}
|
|
|
|
m_field.swap(m_fieldNextState);
|
|
}
|
|
|
|
void CellularAutomaton::displayField() const
|
|
{
|
|
for (const auto& row : m_field)
|
|
{
|
|
for (const auto& cell : row)
|
|
{
|
|
std::cout << (cell ? '1' : '0') << ' ';
|
|
}
|
|
std::cout << '\n';
|
|
}
|
|
} |