Search code examples
c#cellular-automata

For loop that evaluates all values at once?


So i have a cellular automaton, where i can place pixels on an image and they just move down one pixel each "tick". Now the problem is since the for loop is like this:

for(int x = 0; x < 100; x++){
   for(int y = 0; y < 100; y++){
     //Check if nothing below (x,y) pixel and move it down if so
   }
}

Then the pixels get teleported to the bottom because they get moved down every iteration of the y loop. I solved it by making the y loop go from 100 down to 0 instead of 0 to 100, so its iterating upwards but it wont work if i want to make my pixels move upwards in certain situations.

Maybe a double loop where it makes a list of which pixels to move and where in the first one and actually do it in the second but that seems quite performance heavy and im sure there is a better solution

PS: if you have a better title for the question, let me know


Solution

  • You need two copies of the cells. In pseudo code:

    int[] currentCells = new int[...];
    int[] nextCells = new int[...];
    
    Initialize(currentCells);
    while (true) {
        Draw(currentCells);
        Calculate next state by using currentCells as source and store result into nextCells;
    
        // exchange (this copies only references and is fast).
        var temp = currentCells;
        currentCells = nextCells;
        nextCells = temp;
    }
    

    Note that we loop through each cell of the destination (nextCells) to get a new value for it. Throughout this process we never look at the cells in nextCells, because these could be moved ones already. Our source is strictly currentCells which now represents the previous (frozen) state.

    // Calculate next state.
    for(int x = 0; x < 100; x++){
        for(int y = 0; y < 100; y++){
            if(currentCells[x, y] == 0 && y > 0) { // Nothing here
                // Take value from above
                nextCells[x, y] = currentCells[x, y - 1];
            } else {
                // Just copy
                nextCells[x, y] = currentCells[x, y];
            }
        }
    }
    

    In Conway's Game of Life, for instance, you calculate the state of a cell by analyzing the values of the surrounding cells. This means that neither working upwards nor downwards will work. By having 2 buffers, you always have a source buffer that is not changed during the calculation of the next state.