HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Optimizing Conway's Game of Life code to run faster

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
conwaycodefastergameoptimizingliferun

Problem

How could I take this code and optimize it so that I could possibly run Conway's Game of Life on a large grid at 15 frames per second?

```
public partial class MainWindow : Window
{

Cell[,] activeCells;
//List nextGenCells;

static Timer time;
bool onOff = true;

int columnNum = 10;
int rowNum = 10;
int codeColumn;
int codeRow;

public MainWindow()
{
InitializeComponent();
createGrid(10, 10);
}

public void createGrid(int width, int height)
{
if (cellPanel != null)
{
cellPanel.Children.Clear();
codeColumn = width;
codeRow = height;

cellPanel.Columns = width;
cellPanel.Rows = height;

activeCells = new Cell[width, height];

for (int i = 0; i nextGenCells;
nextGenCells = new List();

for (int i = 0; i 3)
{
nextGenCells.Add(c);
}

if (!c.IsAlive && neighbors == 3)
{
nextGenCells.Add(c);
}

}
}

foreach (Cell cell in nextGenCells)
{
cell.IsAlive = !cell.IsAlive;
}
}

private void oneGenerationButton_Click(object sender, RoutedEventArgs e)
{
updateCells();
}

private void CreateBoardButton(object sender, RoutedEventArgs e)
{
rowNum = (int) heightSlider.Value;
columnNum = (int)widthSlider.Value;
createGrid(rowNum, columnNum);
}

private void randomizeButton_Click(object sender, RoutedEventArgs e)
{
Random rand = new Random();

for (int i = 0; i < codeColumn; i++)
{
for (int j = 0; j < codeRow; j++)
{
if (rand.Next(0, 3) == 1)
{
activeCells[i, j].IsAlive = true;
}
else
{
activeCells[i, j].IsAlive = false;
}
}
}
}

private void playButton_Click(object sender, RoutedEventArgs e)
{
if(onOff)
{
onOff = !onOff;
time = new Timer(1000 / speedSlider.Value);
time.Elapsed += time_Elapsed;

Solution

if (rand.Next(0, 3) == 1)
        {
            activeCells[i, j].IsAlive = true;
        }
        else
        {
            activeCells[i, j].IsAlive = false;
        }


I'd assign the variable like activeCells[i, j].IsAlive = (rand.Next(0, 3) == 1); instead. It simplifies the structure.

if (c.IsAlive && neighbors  3)
        {
            nextGenCells.Add(c);
        }

        if (!c.IsAlive && neighbors == 3)
        {
            nextGenCells.Add(c);
        }


If you use else if here, that should save you a couple cycles.

List nextGenCells;
nextGenCells = new List();


Declare this on one line, there's no reason for you to split it up like you do.

public int getLivingNeighbors(int x, int y)


This function is filled with repeated if statements containing combinations of previously tested variables. Consider storing those in temporary variables instead and reusing them. That should improve readability.

Additionally, I can think of a couple things you could try to increase performance on an algorithmic level:

  • Turn Cells into a net of objects where each object has a reference to its neighbors. This allows you to perform a for-loop over each cell's neighbors, counting isAlive. Such a thing might simplify and speed up the algorithm. Do your own benchmarking to test this.



  • Skip large sections of empty cells. This might be hard to implement in the array based implementation, but if you kept a list of live cells, you could opt to check only the live cells and their neighbors. You could even enable and disable this strategy as certain percentages of tiles are alive, or just check per 5x5 block if it contains live cells. Having some sort of class to track sections also allows you to keep some sort of hasChanged flag, only including the section in calculations if hasChanged is true.



  • Surround your actual grid with dead cells that you never check. This saves all the if-statement complexity at the cost of some memory.



  • Alter your algorithm to return early. You check for up to 8 living neighbors, but any neighbor count above 4 is irrelevant.

Code Snippets

if (rand.Next(0, 3) == 1)
        {
            activeCells[i, j].IsAlive = true;
        }
        else
        {
            activeCells[i, j].IsAlive = false;
        }
if (c.IsAlive && neighbors < 2)
        {
            nextGenCells.Add(c);
        }


        if (c.IsAlive && neighbors > 3)
        {
            nextGenCells.Add(c);
        }



        if (!c.IsAlive && neighbors == 3)
        {
            nextGenCells.Add(c);
        }
List<Cell> nextGenCells;
nextGenCells = new List<Cell>();
public int getLivingNeighbors(int x, int y)

Context

StackExchange Code Review Q#58982, answer score: 2

Revisions (0)

No revisions yet.