Conway's Game of Life command line program in C++ I have programmed Conway's Game of Life in C++.

/*
    Any live cell with fewer than two live neighbors dies, as if by under population.
    Any live cell with two or three live neighbors lives on to the next generation.
    Any live cell with more than three live neighbors dies, as if by overpopulation.
    Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
*/

#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;array&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;stdlib.h&gt;

#define EXTRA_SPACE 1
#define GRID_SIZE 35

#define ALIVE_CELL '#'
#define DEAD_CELL ' '

struct CellCoords { int y, x; };

void setup_grid();
void generation();
void display_grid();
void sleep(int);

std::array&lt;std::array&lt;char, GRID_SIZE + EXTRA_SPACE * 2&gt;, GRID_SIZE + EXTRA_SPACE * 2&gt; grid;

int main() {

    setup_grid();

    int gen = 1;

    do {
        system("cls");
        std::cout &lt;&lt; std::endl &lt;&lt; "Generation " &lt;&lt; gen &lt;&lt; std::endl;
        display_grid();
        sleep(100);
        generation();
        gen++;
    } while (true);

    std::cin.get();
    return 0;
}

void setup_grid() {

    std::ifstream file("grid.txt");
    std::string line;
    int i = EXTRA_SPACE;

    while (std::getline(file, line)) {
        for (int j = EXTRA_SPACE; j &lt; GRID_SIZE; j++) {
            if (line[j] == '1')
                grid[i][j] = ALIVE_CELL;
            else
                grid[i][j] = DEAD_CELL;
        }
        i++;
    }

    file.close();
}

void generation() {

    std::vector&lt;CellCoords&gt; cells_to_kill;
    std::vector&lt;CellCoords&gt; cells_to_be_born;

    int neighbors;

    for (int y = EXTRA_SPACE; y &lt; GRID_SIZE; y++) {
        for (int x = EXTRA_SPACE; x &lt; GRID_SIZE; x++) {

            neighbors = 0;

            if (grid[y - 1][x    ] == ALIVE_CELL) neighbors++;
            if (grid[y - 1][x + 1] == ALIVE_CELL) neighbors++;
            if (grid[y    ][x + 1] == ALIVE_CELL) neighbors++;
            if (grid[y + 1][x + 1] == ALIVE_CELL) neighbors++;
            if (grid[y + 1][x    ] == ALIVE_CELL) neighbors++;
            if (grid[y + 1][x - 1] == ALIVE_CELL) neighbors++;
            if (grid[y    ][x - 1] == ALIVE_CELL) neighbors++;
            if (grid[y - 1][x - 1] == ALIVE_CELL) neighbors++;

            if (grid[y][x] == ALIVE_CELL) {
                if (neighbors &lt; 2 || neighbors &gt; 3)
                    cells_to_kill.push_back({ y, x });
            } else if (neighbors == 3) {
                    cells_to_be_born.push_back({ y, x });
            }
        }
    }

    for (int i = 0; i &lt; cells_to_kill.size(); i++) {
        CellCoords cell = cells_to_kill[i];
        grid[cell.y][cell.x] = DEAD_CELL;
    }

    for (int i = 0; i &lt; cells_to_be_born.size(); i++) {
        CellCoords cell = cells_to_be_born[i];
        grid[cell.y][cell.x] = ALIVE_CELL;
    }
}

void display_grid() {

    std::cout &lt;&lt; std::endl;

    for (int y = EXTRA_SPACE; y &lt; GRID_SIZE; y++) {
        for (int x = EXTRA_SPACE; x &lt; GRID_SIZE; x++) {
            std::cout &lt;&lt; grid[y][x] &lt;&lt; ' ';
        }
        std::cout &lt;&lt; std::endl;
    }
    std::cout &lt;&lt; std::endl;
}

void sleep(int time) {
    for (int i = 0; i &lt; time; i++);
}


How can I improve the code? Was making an extra 2 rows and columns in the grid array a good idea?
Overall, this is pretty good. You've avoided the most common mistakes I see, like bad naming, using magic numbers, passing bare values that really belong together in a data structure. Nice job! I appreciate the comment at the top that explains the rules, too.
To answer your question, I think that using the extra rows and columns is a great idea. They're 2 characters per row, and 2 extra rows. It's not a lot of memory, and it makes the code much cleaner.
Here are some thoughts on some things that could be improved.
Avoid Globals
Your game board is a global variable. You've structured the code nicely, so it only ever gets modified in generation(), but small programs have a tendency to become large programs, and global variables in large programs have a tendency to get modified all over the place. I'd move the grid variable into main() and pass a reference to it into the various functions that use it.
Always Name Your Arguments
Your definition of the sleep() function looks like this:
void sleep(int);

What is the int? A function prototype with unnamed arguments is close to useless. Now I have to read through the function to get any useful information about what the parameter means. If it was named something like iterations or time like in the actual function it would be infinitely better.
Things in main()
The gen variable is set up, and it's incremented, but it's never checked. It's just busywork for your CPU. If you were going to use it to bail out of the loop after so many iterations, it would be useful, but you've made an infinite loop. So I'd just get rid of it.
You're using std::endl at the end of every line you print. That's pretty heavy-weight. It flushes the output buffer. I'd say in most cases you want to just use &quot;\n&quot; instead. Maybe you could use std::endl after printing the last character of the board.
Your command to clear the screen is non-standard. My system doesn't have a command named cls on it, so that just outputs an ugly error message. I don't do a lot of console programming, so I'm not sure if there's a universal way to clear the screen, but you might look into ANSI escape codes.
The sleep() Function
Likewise, your sleep() function has some issues. There's a standard POSIX function named sleep() that is often used to sleep the process for an amount of time. I don't know whether it exists on Windows or not. But regardless of that, the way you've implemented it, it will sleep for a different amount of time on different machines. So a 1GHz machine will probably take twice as long to complete that loop as a 2GHz machine. You probably don't want that. I recommend finding a more standard method for performing sleep on your target system. Something that at least checks the clock rather than just counting.
According to the comments, you can use:
#include &lt;chrono&gt;
#include &lt;thread&gt;
...
std::this_thread::sleep_for(std::chrono::milliseconds(500));

setup_grid()
For the most part, setup_grid() looks pretty decent. If any errors occur, you will end up with a partially uninitialized grid, though. You might want to at least clear it all to DEAD_CELL to start with so you have something sensible in there. Better yet, if any errors occur, return them to the caller and let the caller decide how to handle them (tell the user, exit the program, whatever).
You don't need the file.close() at the end. The destructor for std::ifstream will call it for you when the function ends.
generation()
This function is pretty well written, too. I didn't have time to do timing trials, but I have to wonder if using the same grid for input and output is fastest? (Not that it matters given your sleep() function!) Another way to handle it would be to pass in 2 grids - the current state and the next state. Rather than noting which cells changed and then overwriting them, you'd simply fill in the new cells given the state of the old cells. It might be a wash, though. You could code it up and profile it to be sure.
There's nothing wrong with the set of if statements you have for checking the cells. In fact, some would argue that you've done loop unrolling which could theoretically improve performance. I think it would be easier to read, though, if it were done in a loop like this:
for (int cell_y = y - 1; cell_y &lt; y + 1; ++cell_y) {
    for (int cell_x = x - 1; cell_x &lt; x + 1; ++cell_x) {
        if (grid[cell_y][cell_x] == ALIVE_CELL) {
            neighbors++;
        }
    }
}

As noted, this will count the current cell, so you can subtract it out at the end with:
if (grid[y][x] == ALIVE_CELL) {
    neighbors--;
}

At the very least, you should avoid writing the condition and the statement it executes on the same line, as it makes it impossible to tell whether the statement executed or not when stepping through with a debugger. Not a big deal here, but it can be in larger programs, so it's a good habit to avoid putting it all on one line.
I recommend always using braces in if statements, even if they're only one line as that avoids another common error, which is adding a line to an if without realizing you didn't actually add it. Like this:
 if (someCondition)
    doSomething();
    doSomethingElse();

In this case, doSomethingElse(); will be called regardless of whether someCondition is true or false because there are no braces around the intended body of the if statement.