The first bad thing you do is a lot of string concatenations like
_outputGrid += "1";
which cause many memory reallocations. Since during one game grid size is a constant number you can save it at the constructor, and then just create array for result and set its elements by index.
_outputGrid = new char[_gridSize * _gridSize];
...
_outputGrid[currentIndex] = '0';
At the end of the CalculateNextGrid
method convert this array to string and return it:
return new string(_outputGrid);
I suggest to use array of bool
's as internal storage for result instead of a string. In my opinion true
and false
represent the state of a cell (alive or dead) more clearly.
It would be better to extract magic conditions to some methods like:
private static bool ShouldBeDeadByUnderpopulation(int count) => count < 2;
private static bool ShouldBeDeadByOverpopulation(int count) => count > 3;
and so on.
And instead of condition like
if (inputGrid[currentIndex + _up + _right] == '1')
use methods too
if (IsAlive(value))