Описание класса CellularAutomaton
This commit is contained in:
@@ -144,6 +144,209 @@
|
||||
|
||||
\section {Математическое описание}
|
||||
|
||||
|
||||
\newpage
|
||||
\section{Особенности реализации}
|
||||
\subsection{Класс CellularAutomaton}
|
||||
В листинге~\ref{lst:CellularAutomaton} представлен код объявления класса \texttt{CellularAutomaton}.
|
||||
|
||||
Класс содержит следующие атрибуты:
|
||||
\begin{itemize}
|
||||
\item \texttt{static const unsigned int m\_functionValues} -- хранит число, соответствующее номеру варианта лабораторной работы, его битовое представление соответствует функции переходов двумерного клеточного автомата;
|
||||
\item \texttt{int m\_fieldWidth} -- ширина поля клеточного автомата;
|
||||
\item \texttt{int m\_fieldHeight} -- высота поля клеточного автомата;
|
||||
\item \texttt{std::vector<std::vector<int> > m\_field} -- двумерный вектор, представляющий текущее состояние клеточного автомата;
|
||||
\item \texttt{std::vector<std::vector<int> > m\_fieldNextState} -- двумерный вектор для хранения следующего состояния клеточного автомата;
|
||||
\item \texttt{BoundaryCondition m\_boundaryCondition} -- граничные условия, задаются значением из перечисления \texttt{BoundaryCondition}.
|
||||
\end{itemize}
|
||||
|
||||
Перечисление \texttt{BoundaryCondition} имеет три возможных значения:
|
||||
\begin{itemize}
|
||||
\item \texttt{BOUNDARY\_ONES} -- единичные граничные условия;
|
||||
\item \texttt{BOUNDARY\_ZEROS} -- нулевые граничные условия;
|
||||
\item \texttt{BOUNDARY\_TOROIDAL} -- тороидальные граничные условия.
|
||||
\end{itemize}
|
||||
|
||||
Методы класса описываются в последующих разделах.
|
||||
|
||||
\begin{lstlisting}[caption={Код объявления класса CellularAutomaton.}, label={lst:CellularAutomaton}]
|
||||
enum BoundaryCondition {
|
||||
BOUNDARY_ONES,
|
||||
BOUNDARY_ZEROS,
|
||||
BOUNDARY_TOROIDAL
|
||||
};
|
||||
|
||||
class CellularAutomaton
|
||||
{
|
||||
static const unsigned int m_functionValues = 25 * 11 * 2003 * 18 * 11;
|
||||
|
||||
int m_fieldWidth, m_fieldHeight;
|
||||
std::vector<std::vector<int>> m_field;
|
||||
std::vector<std::vector<int>> m_fieldNextState;
|
||||
BoundaryCondition m_boundaryCondition;
|
||||
|
||||
void initializeRandom();
|
||||
void initializeManual();
|
||||
|
||||
int getCellState(int x, int y) const;
|
||||
int getNeighborhoodIndex(int x, int y) const;
|
||||
public:
|
||||
CellularAutomaton(int width, int height, bool fillWithRandom, BoundaryCondition boundaryCondition);
|
||||
|
||||
void update();
|
||||
void displayField() const;
|
||||
};
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Конструктор CellularAutomaton}
|
||||
|
||||
Конструктор класса CellularAutomaton, код которого представлен в листиге~\ref{lst:CellularAutomatonConstructor}, принимает следующие параметры:
|
||||
\begin{itemize}
|
||||
\item \texttt{int width} -- ширина поля клеточного автомата;
|
||||
\item \texttt{int height} -- высота поля клеточного автомата;
|
||||
\item \texttt{bool fillWithRandom} -- флаг, определяющий, инициализировать ли поле случайными значениями;
|
||||
\item \texttt{BoundaryCondition boundaryCondition} -- условие на границе поля.
|
||||
\end{itemize}
|
||||
|
||||
Конструктор создает объект \texttt{CellularAutomaton} с заданными размерами и граничными условиями. Если \texttt{fillWithRandom} равно \texttt{true}, то поле инициализируется случайным образом с помощью метода \texttt{initializeRandom}, иначе пользователь может вручную ввести начальное состояние с помощью метода \texttt{initializeManual}.
|
||||
|
||||
\begin{lstlisting}[caption={Код конструктора CellularAutomaton.}, label={lst:CellularAutomatonConstructor}]
|
||||
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();
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Метод initializeRandom}
|
||||
В листинге~\ref{lst:initializeRandom} представлен код метода \texttt{initializeRandom}. Метод явно ничего не принимает и не возвращает, а работает только с атрибутами класса \texttt{CellularAutomaton}. В результате его работы атрибут \texttt{m\_field} заполняется нулями и единицами случайным образом, для этого используется равномерное распределение.
|
||||
|
||||
\begin{lstlisting}[caption={Код метода initializeRandom.}, label={lst:initializeRandom}]
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Метод initializeManual}
|
||||
В листинге~\ref{lst:initializeManual} представлен код метода \texttt{initializeManual}. Метод не принимает аргументов и ничего не возвращает. Он позволяет пользователю вручную ввести начальное состояние поля клеточного автомата. Для каждой клетки запрашивается значение 0 или 1, которые сохраняются в атрибуте \texttt{m\_field}.
|
||||
|
||||
\begin{lstlisting}[caption={Код метода initializeManual.}, label={lst:initializeManual}]
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Метод getCellState}
|
||||
В листинге~\ref{lst:getCellState} представлен код метода \texttt{getCellState}. Метод принимает на вход координаты клетки \texttt{int x} и \texttt{int y}. Возвращает \texttt{int} -- состояние клетки по указанным координатам. Если координаты выходят за пределы поля, то поведение определяется граничными условиями, заданными атрибутом \texttt{m\_boundaryCondition}.
|
||||
|
||||
\begin{lstlisting}[caption={Код метода getCellState.}, label={lst:getCellState}]
|
||||
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];
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Метод getNeighborhoodIndex}
|
||||
В листинге~\ref{lst:getNeighborhoodIndex} представлен код метода \texttt{getNeighborhoodIndex}. Метод принимает на вход координаты клетки \texttt{int x} и \texttt{int y}. Возвращает \texttt{int} -- индекс конфигурации окрестности фон Неймана клетки. Индекс вычисляется на основе состояний центральной клетки и её четырёх соседей (сверху, снизу, слева и справа), где каждый сосед соответствует одному биту в индексе. Этот индекс используется для определения следующего состояния клетки по функции переходов в методе \texttt{update}.
|
||||
|
||||
\begin{lstlisting}[caption={Код метода getNeighborhoodIndex.}, label={lst:getNeighborhoodIndex}]
|
||||
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;
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Метод update}
|
||||
В листинге~\ref{lst:update} представлен код метода \texttt{update}. Метод не принимает аргументов и ничего не возвращает. Он обновляет состояние клеточного автомата на следующий временной шаг. Для каждой клетки вычисляется новое состояние на основе текущего состояния и функции переходов, значения которой хранятся в битах числа \texttt{m\_functionValues}. После вычисления новое состояние сохраняется в \texttt{m\_fieldNextState}, а затем происходит обмен содержимого \texttt{m\_field} и \texttt{m\_fieldNextState}.
|
||||
|
||||
\begin{lstlisting}[caption={Код метода update.}, label={lst:update}]
|
||||
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);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Метод displayField}
|
||||
В листинге~\ref{lst:displayField} представлен код метода \texttt{displayField}. Метод не принимает аргументов и ничего не возвращает. Он выводит текущее состояние поля клеточного автомата в консоль, отображая каждую клетку как '0' или '1'.
|
||||
|
||||
\begin{lstlisting}[caption={Код метода displayField.}, label={lst:displayField}]
|
||||
void CellularAutomaton::displayField() const
|
||||
{
|
||||
for (const auto& row : m_field)
|
||||
{
|
||||
for (const auto& cell : row)
|
||||
{
|
||||
std::cout << (cell ? '1' : '0') << ' ';
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\subsection{Функция main}
|
||||
|
||||
\subsection{Пользовательский ввод}
|
||||
Одним из требований к лабораторным работам являлась защита от некорректного пользовательского ввода. Для реализации такой защиты и большей читаемости кода все функции связанные с пользовательским вводом были вынесены в отдельный файл. Все функции проверяют данные вводимые пользователем и, если что-то не так, печатают информацию о неверном выводе.
|
||||
|
||||
@@ -153,10 +356,6 @@
|
||||
\item {\tt bool userApprove()} - возвращает true, если пользователь ввёл <<yes>> или <<y>> и false, если пользователь ввёл <<no>> или <<n>>.
|
||||
\item {\tt void waitForEnter()} - останавливает выполнение программы пока пользователь не нажмёт на клавишу <<Enter>>.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
|
||||
\subsection{Функция main}
|
||||
|
||||
|
||||
\newpage
|
||||
|
||||
Reference in New Issue
Block a user