Search code examples
c++arraysscreenmodulus

Screen wrap a 2-D array in C++


I am finishing up a Conway's Game of Life assignment. I created a function to generate a random array of 1s and 0s; the 1s represent a living cell and the zero an empty space.

I created a separate function to inspect the neighborhood and make a count to determine how the game progresses.

The rules: if a cell has 2 or 3 neighbors it survives, more than 3 or less than 2 it dies, and if an empty space has 3 neighbors it is "born". My "planet" is 79 x 24 characters but it's not a real planet yet until I wrap the screen.

Here is the function:

void life (int master[24][79]) //generates/kills cells based on neighborhood
{
    int temp[24][79]; //temporary array for manipulating data
    copy (master, temp); //copy array onto temp
    for(int j = 0; j < h; j++) //height loop
    {

        for (int i = 0; i < w; i++) //width loop
        {
            int count = 0; //intialize neighbor count variable
            count = master[j-1][i] + //searches down
            master[j-1][i-1] + //down left
            master[j][i-1] + //left
            master[j+1][i-1] + //up left
            master[j+1][i] + //up
            master[j+1][i+1] + //up right
            master[j][i+1] + //right
            master[j-1][i+1]; //down right
            //cell dies if count falls below 2 or rises above 3
            if(count < 2 || count > 3)
                temp[j][i] = 0;
            //cell stays alive if it has two neighbors
            if(count == 2)
                temp[j][i] = master[j][i];
            //cell either stays alive or gets born if three neighbors
            if(count == 3)
                temp[j][i] = 1;
        } //end width loop
    }//end height loop
    copy(temp, master); //copy temp back to main array
} //end life function

Im sure that I am supposed to use the modulus but nothing that I try seems to work. I have tried using while loops to bring the maximum values back to zero, but I can tell that has the effect of wrapping gradually downwards similar to how threads wrap around a screw. Should I just mod-ify (sorry) search part of the code to look like this?

int count = 0; //intialize neighbor count variable
            count = master[(j-1)%h][i%w] + //searches down
            master[(j-1)%h][(i-1)%w] + //down left
            master[j%h][(i-1)%w] + //left
            master[(j+1)%h][(i-1)%w] + //up left
            master[(j+1)%h][i%w] + //up
            master[(j+1)%h][(i+1)%w] + //up right
            master[j%h][(i+1)%w] + //right
            master[(j-1)%h][(i+1)%w]; //down right

Solution

  • To stay in range [0-w[ you have to use modulus and make sure than your number is positive, so, something like

    master[(j - 1 + h) % h][i % w]
    + master[(j - 1 + h) % h][(i - 1 + w) % w]
    // ...
    

    and so on.

    I suggest to add a accessor function, something like

    int& get(int master[24][79], int i, int j)
    {
        return master[(j - 1 + 24) % 24][(i - 1 + 79) % 79]
    }
    

    and then simply use

    get(master, i, j - 1)
    + get(master, i - 1, j - 1)
    // ...
    

    I suggest to wrap your data in a class:

    class WorldMap
    {
    public:
        int  get(int i, int j) const { return cells[(i + 24) % 24][(j + 79) % 79]; }
        int& get(int i, int j)       { return cells[(i + 24) % 24][(j + 79) % 79]; }
    private:
        int cells[24][79] = {};
    };
    

    And then

    void life (WorldMap& worldMap)
    {
        WorldMap next;
        // ... initialize next according to rules of life
        worldMap = next;
    }