I need my program to sleep AFTER I run cout, for some reason it doesn’t work. I’m using OnlineGDB editor, too [duplicate]

Before anyone says it, yes, I know this is HORRIBLY written. I’m not a professional. What I am is frustrated, since for some reason in the main function, after telling the program you don’t want to use the preset you’ve selected, it messes up. Try it. Follow the instructions, go to presets, choose any preset and say no. The line “cancelling…” will display after the program waits and at the start of the next frame, despite there being a system("clear"); in between (inside of DrawPlaySpace();). I have no clue what’s happening here.

NOTE: there are a few unfinished features here, like the stable loop detection and the randomized preset. If I can’t figure those out myself either, expect another question here lol

ANOTHER NOTE: please don’t steal this, I neglected my classwork so much for this and I’m very proud of my silly little stupid Conway’s Game of Life son, as frustrated as I may be

EDIT: I added comments (yay)

#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <chrono>
#include <thread>

using namespace std::this_thread; // sleep_for, sleep_until
using namespace std::chrono; // nanoseconds, system_clock, seconds
using namespace std;

bool lastInputBad = false; //true if you input something invalid at the setup menu, so the text for it can be at the bottom of the screen

bool lastFrame = false; //allows the system to actually display the final frame if it is ended by either a total wipe or [WIP] an infinite loop

int iterations = 0; //records how many times the sim has updated

int similaritiesToCurrent[25][25]; //stores how many of the last 10 frames have the living tiles in each spot

bool stableLock = false; //decides whether the sim is locked in a stable loop forever

bool stableDetection[10][25][25]; //stores the last 10 25x25 frames

bool playSpace[25][25]; //the current frame

bool nextGen[25][25]; //the place we store the next frame while we're computing it so it doesn't mess with the computations

bool setup = true; //used to decide if certain text should be displayed when drawing the current frame

string userInput; //records the user's input in the main menu

string presetSelection; //records which preset the user has selected at the main menu

string confirmation; //records the Y or N of the user when asked if they want the current preset

int cursor[2] {0, 0}; //position of the cursor during setup

int totalLife = 0; //total number of living cells on the board

void RecordGen() { //moves each of the last 10 frames back one spot and then records the current frame in the new lowest spot
    for (int h = 9; h >= 0; h--) {
        for (int i = 0; i < 25; i++) {
            for (int j = 0; j < 25; j++) {
                if (h == 0) {
                    stableDetection[0][i][j] = playSpace[i][j];
                } else if (h < 9) {
                    stableDetection[h + 1][i][j] = stableDetection[h][i][j];
                }
            }
        }
    }
}

void DetectStability() { //[BROKEN] uses the record of the last 10 frames to decide how many of them are identical (to decide if the sim is infinitely looping)
    stableLock = true;
    for (int i = 0; i < 25; i++) {
        for (int j = 0; i < 25; i++) {
            similaritiesToCurrent[i][j] = 0;
        }
    }
    for (int h = 1; h < 10; h++) {
        for (int i = 0; i < 25; i++) {
            for (int j = 0; j < 25; j++) {
                if (stableDetection[h][i][j] && playSpace[i][j]) {
                    similaritiesToCurrent[i][j]++;
                }
            }
        }
    }
    for (int i = 0; i < 25; i++) {
        for (int j = 0; j < 25; j++) {
            if (similaritiesToCurrent[i][j] < 6 && (stableDetection[0][i][j] || stableDetection[1][i][j])) stableLock = false;
            //cout<<"Cell at "<<i<<", "<<j<<" has "<<similaritiesToCurrent[i][j]<<" similarities to the last 10 frames\n";
            //for debugging, uncomment to use^
        }
    }
}

void ResetPlaySpace() { //resets the board to all dead cells
    for (int i = 0; i < 25; i++) {
        for (int j = 0; j < 25; j++) {
            playSpace[i][j] = 0;
            nextGen[i][j] = 0;
        }
    }
}

void DrawPlaySpace(bool isSetup) { //draws the board to the terminal. Lots of use of the isSetup boolean since it decides how some things look (and then I can use the same rendering function no matter what)
    system("clear");
    if (isSetup) cout<<"This is the setup.\nBelow you can see the board.\nType 'w', 'a', 's', or 'd' and press enter to move the cursor around.\nTo toggle the selected cell, type ' ' and hit enter.\nOnce you are happy with the board, type 'start' and hit enter, and watch the cells do their thing!\nAlternatively, type 'presets' and hit enter to view the list of pre-made boards";
    if (!isSetup) {
        cout<<"\n\n    __________________________________________________\n";
    } else {
        cout<<"\n    ";
        for (int i = 0; i < 25; i++) {
            if (i < 9) cout<<"0";
            cout<<i + 1<<" ";
        }
        cout<<"\n";
    }
    
    for (int i = 0; i < 25; i++) {
        if (!isSetup) {
            cout<<"   |";
        } else {
            if (i < 9) {
                cout<<" 0";
            } else {
                cout<<" ";
            }
            cout<<i + 1<<" ";
        }
        for (int j = 0; j < 25; j++) {
            if (i == cursor[0] && j == cursor[1] && isSetup) { //some bits that control how the cursor looks
                if (playSpace[i][j]) {
                    cout<<"%";
                } else {
                    cout<<"_";
                }
            } else if (playSpace[i][j]) { //draws differently based on each tile of the playSpace array
                cout<<"#";
            } else {
                cout<<" ";
            }
            cout<<" ";
            if (isSetup) cout<<" ";
        }
        if (!isSetup) cout<<"|";
        cout<<"\n";
    }
    if (!isSetup) cout<<"   |__________________________________________________|\n";
    if (isSetup && lastInputBad) { //this is why we need that boolean to draw this message at the bottom of the screen
        lastInputBad = false;
        cout<<"Invalid input! Try again.";
    }
}

void EvalCell(int i, int j) { //figures out if the cell at the input coords needs to change states
    int rowAbove = j - 1;
    int rowBelow = j + 1;
    int colLeft = i - 1;
    int colRight = i + 1;
    int numNeighbors = 0;
   
    if (rowAbove == -1) rowAbove = 24; //screen wrapping
    if (rowBelow == 25) rowBelow = 0;
    if (colLeft == -1) colLeft = 24;
    if (colRight == 25) colRight = 0;
   
    if (playSpace[colLeft][rowAbove]) {
        numNeighbors++;
    }
    if (playSpace[i][rowAbove]) {
        numNeighbors++;
    }
    if (playSpace[colRight][rowAbove]) {
        numNeighbors++;
    }
    if (playSpace[colLeft][j]) {
        numNeighbors++;
    }
    if (playSpace[colRight][j]) {
        numNeighbors++;
    }
    if (playSpace[colLeft][rowBelow]) {
        numNeighbors++;
    }
    if (playSpace[i][rowBelow]) {
        numNeighbors++;
    }
    if (playSpace[colRight][rowBelow]) {
        numNeighbors++;
    }
    if (playSpace[i][j] == 0 && numNeighbors == 3) { //store the eval results in nextGen
        nextGen[i][j] = 1;
    }
    if (playSpace[i][j] == 1 && numNeighbors < 2) {
        nextGen[i][j] = 0;
    }
    if (playSpace[i][j] == 1 && numNeighbors > 3) {
        nextGen[i][j] = 0;
    }
    if (playSpace[i][j] == 1 && (numNeighbors == 2 || numNeighbors == 3)) {
        nextGen[i][j] = 1;
    }
}

void CalculateNextGen() {
    totalLife = 0;
    for (int i = 0; i < 25; i++) {
        for (int j = 0; j < 25; j++) {
            EvalCell(i, j); //evaluate all the cells
        }
    }
    for (int i = 0; i < 25; i++) {
        for (int j = 0; j < 25; j++) {
            playSpace[i][j] = nextGen[i][j]; //set the current frame to be the calculated next frame
            if (playSpace[i][j]) totalLife++; //figure out how many cells there are (and if there are 0 the program will end)
        }
    }
}

int main()
{
    ResetPlaySpace();
    cout<<"Welcome to Conway's Game of Life!\nHere you will be presented with a 25 by 25 board.\nOn this board, there are some simple rules!\nEach tile is called a \"cell\", and each cell can be either living (#) or dead ( )\nIf a living cell has 0 or 1 living cells near it, it dies on the next iteration.\nIf a living cell has 4 or more living cells near it, it also dies.\nIf a dead cell has exactly 3 living cells around it, it comes to life on the next iteration.\nIf none of these conditions are met, the cell stays as it was.\nPress enter to start!";
    cin.get();
    system("clear");
    while(setup) {
        DrawPlaySpace(true);
        getline(cin, userInput);
        if (userInput == "start") {
            setup = false;
        } else if (userInput == "w") {
            cursor[0]--;
            if (cursor[0] == -1) cursor[0] = 24;
        } else if (userInput == "s") {
            cursor[0]++;
            if (cursor[0] == 25) cursor[0] = 0;
        } else if (userInput == "a") {
            cursor[1]--;
            if (cursor[1] == -1) cursor[1] = 24;
        } else if (userInput == "d") {
            cursor[1]++;
            if (cursor[1] == 25) cursor[1] = 0;
        } else if (userInput == " ") {
            playSpace[cursor[0]][cursor[1]] = !playSpace[cursor[0]][cursor[1]];
        } else if (userInput == "presets") { //the presets system
            ResetPlaySpace();
            system("clear");
            cout<<"Which preset would you like?\nEnter the letter to select it.\na) Glider Example\nb) Stable Bread Loaf\nc) Ticking Time Bomb\nd) Party Lines\ne) Randomized Layout\n";
            getline(cin, presetSelection);
            setup = false;
            if (presetSelection == "a") { //each of these manually enables some cells to load the preset
                playSpace[11][12] = true;
                playSpace[12][13] = true;
                playSpace[13][11] = true;
                playSpace[13][12] = true;
                playSpace[13][13] = true;
                DrawPlaySpace(false);
                cout<<"    Would you like to use this preset? Y/N:\n";
                getline(cin, confirmation);
                if (confirmation == "y" || confirmation == "Y") {
                    cout<<"    Beginning simulation...";
                    sleep_for(nanoseconds(1000000)); //THESE DON'T WORK
                } else if (confirmation == "n" || confirmation == "N") {
                    cout<<"    Cancelling...";
                    setup = true;
                    sleep_for(nanoseconds(1000000)); //NONE OF THEM
                } else {
                    cout<<"    Interpreting vague answer as: YES";
                    sleep_for(nanoseconds(1000000)); //WHYYYYYYYYYYYYY
                }
            } else if (presetSelection == "b") {
                playSpace[11][13] = true;
                playSpace[12][12] = true;
                playSpace[12][14] = true;
                playSpace[13][11] = true;
                playSpace[13][14] = true;
                playSpace[14][12] = true;
                playSpace[14][13] = true;
                DrawPlaySpace(false);
                cout<<"    Would you like to use this preset? Y/N:\n";
                getline(cin, confirmation);
                if (confirmation == "y" || confirmation == "Y") {
                    cout<<"    Beginning simulation...";
                    sleep_for(nanoseconds(1000000));
                } else if (confirmation == "n" || confirmation == "N") {
                    cout<<"    Cancelling...";
                    setup = true;
                    sleep_for(nanoseconds(1000000));
                } else {
                    cout<<"    Interpreting vague answer as: YES";
                    sleep_for(nanoseconds(1000000));
                }
            } else if (presetSelection == "c") {
                playSpace[0][0] = true;
                playSpace[0][1] = true;
                playSpace[1][0] = true;
                playSpace[1][1] = true;
                playSpace[3][4] = true;
                playSpace[4][5] = true;
                playSpace[5][3] = true;
                playSpace[5][4] = true;
                playSpace[5][5] = true;
                DrawPlaySpace(false);
                cout<<"    Would you like to use this preset? Y/N:\n";
                getline(cin, confirmation);
                if (confirmation == "y" || confirmation == "Y") {
                    cout<<"    Beginning simulation...";
                    sleep_for(nanoseconds(1000000));
                } else if (confirmation == "n" || confirmation == "N") {
                    cout<<"    Cancelling...";
                    setup = true;
                    sleep_for(nanoseconds(1000000));
                } else {
                    cout<<"    Interpreting vague answer as: YES";
                    sleep_for(nanoseconds(1000000));
                }
            } else if (presetSelection == "d") {
                playSpace[0][12] = true;
                playSpace[1][12] = true;
                playSpace[2][12] = true;
                playSpace[3][12] = true;
                playSpace[4][12] = true;
                playSpace[5][12] = true;
                playSpace[6][12] = true;
                playSpace[7][12] = true;
                playSpace[8][12] = true;
                playSpace[9][12] = true;
                playSpace[10][12] = true;
                playSpace[11][12] = true;
                playSpace[12][12] = true;
                playSpace[13][12] = true;
                playSpace[14][12] = true;
                playSpace[15][12] = true;
                playSpace[16][12] = true;
                playSpace[17][12] = true;
                playSpace[18][12] = true;
                playSpace[19][12] = true;
                playSpace[20][12] = true;
                playSpace[21][12] = true;
                playSpace[22][12] = true;
                playSpace[23][12] = true;
                playSpace[24][12] = true;
                playSpace[0][13] = true;
                playSpace[1][13] = true;
                playSpace[2][13] = true;
                playSpace[3][13] = true;
                playSpace[4][13] = true;
                playSpace[5][13] = true;
                playSpace[6][13] = true;
                playSpace[7][13] = true;
                playSpace[8][13] = true;
                playSpace[9][13] = true;
                playSpace[10][13] = true;
                playSpace[11][13] = true;
                playSpace[12][13] = true;
                playSpace[13][13] = true;
                playSpace[14][13] = true;
                playSpace[15][13] = true;
                playSpace[16][13] = true;
                playSpace[17][13] = true;
                playSpace[18][13] = true;
                playSpace[19][13] = true;
                playSpace[20][13] = true;
                playSpace[21][13] = true;
                playSpace[22][13] = true;
                playSpace[23][13] = true;
                playSpace[24][13] = true;
                DrawPlaySpace(false);
                cout<<"    Would you like to use this preset? Y/N:\n";
                getline(cin, confirmation);
                if (confirmation == "y" || confirmation == "Y") {
                    cout<<"    Beginning simulation...";
                    sleep_for(nanoseconds(1000000));
                } else if (confirmation == "n" || confirmation == "N") {
                    cout<<"    Cancelling...";
                    setup = true;
                    sleep_for(nanoseconds(1000000));
                } else {
                    cout<<"    Interpreting vague answer as: YES";
                    sleep_for(nanoseconds(1000000));
                }
            } else if (presetSelection == "e") { //randome, ooh fancy, spoiler alert it doesn't work
                srand (time(NULL));
                for (int i = 0; i < 25; i++) {
                    for (int j = 0; j < 25; j++) {
                        int randomCell = rand() % 1;
                        playSpace[i][j] = randomCell;
                    }
                }
                DrawPlaySpace(false);
                cout<<"    Would you like to use this preset? Y/N:\n";
                getline(cin, confirmation);
                if (confirmation == "y" || confirmation == "Y") {
                    cout<<"    Beginning simulation...";
                    sleep_for(nanoseconds(1000000));
                } else if (confirmation == "n" || confirmation == "N") {
                    cout<<"    Cancelling...";
                    setup = true;
                    sleep_for(nanoseconds(1000000));
                } else {
                    cout<<"    Interpreting vague answer as: YES";
                    sleep_for(nanoseconds(1000000));
                }
            } else {
                cout<<"    Invalid input";
                setup = true;
                sleep_for(nanoseconds(1000000));
            }
        } else {
            lastInputBad = true; //invalid input stuff yay
        }
    }
    while (true) { //finally, the main loop
       iterations++;
       DrawPlaySpace(false);
       CalculateNextGen();
       RecordGen();
       DetectStability();
       if (lastFrame) break;
       if (iterations >= 10 && (!totalLife || stableLock)) lastFrame = true;
       /*if (stableLock) {
           cout<<"\n    STABLE";
       } else {
           cout<<"\n    UNSTABLE";
       }*/
       //more of the broken stability stuff^
       usleep(250000);
       //cin.get();
       //cin.ignore();
       //debug stuff that makes frame progression manual, uncomment to use^
    }
    return iterations; //exits with how many gens it simulated for funnies
}

I’ve tried using 3 different methods of pausing the program: usleep();, std::this_thread::whatever, and sleep_for(nanoseconds());. Nothing works, which makes me think it’s a me error, but last time I checked programs are read top down and my cout line is above my delays every single time. And every time, without fail, it ouputs the text after waiting but before the next frame.

  • 3

    Better idea: Back up your program and hack it down to a tiny program that does nothing other than demonstrate the problem. Use minimal reproducible example for inspiration. You won’t have to comment much if the program is reduced to , say, 10 lines of code.

    – 

  • 2

    A side note on commenting: You should only need comments to provide a descriptive header at the top of functions, data structure definitions, important variables, and particularly thorny bits of code. The rest of the intent should be readable from the code itself. This usually means use good, descriptive names and don’t pack too much on a single line.

    – 

  • 4

    the output is probably line buffered, you’ll need to explicitly flush if you want output before the end of a line

    – 

  • 2

    std::flush or use std::endl.

    – 

  • 2

    Don’t be too put off by asking a duplicate. It’s really hard for anyone at a beginner level to ask a question in any established programming language that hasn’t already been asked and answered in the last 15 years. The real key is making sure you’ve isolated the problem. If you have the bug trapped in a small piece of code you’ve at least found the problem and sort-of know what you’re asking about. This makes it easier to find duplicates on your own, or solve the problem outright on your own, and not have to ask a question at all.

    – 

Leave a Comment