Hello. I made this program. It's designed to be a version of the game "Game of Life", except text-based and played entirely in cmd. Now, the program is working fine, but I would like to get some suggestions for things I could have done more efficiently, or anything else that I didn't do optimally, and how I should have done them. Thanks in advance. Warning: it's rather long.

By the way, i'm new on this forum so i hope i didn't break any rules that i don't know of..

// function to wait a certain amount of seconds, which is used in the "animate" part

void Wait_Secs(int secs_wait){
    time_t timevar;
    time(&timevar);
    char * timestr2 = asctime(localtime(&timevar)), timestr[26];
    for(int i = 0; i <= 25; i++){
        timestr[i] = timestr2[i];
    }
    int secs_cur = ((int)timestr[17] - 48) * 10 + (int)(timestr[18]-48);
    int secs_start = secs_cur;
    while(secs_cur - secs_start < secs_wait){
        time(&timevar);
        timestr2 = asctime(localtime(&timevar));
        for(int i = 0; i <= 25; i++){
            timestr[i] = timestr2[i];
        }
        secs_cur = ((int)timestr[17] - 48) * 10 + (int)(timestr[18]-48);
        if(secs_cur < secs_start){
            secs_cur += 60;
        }
    }
    timestr2 = 0;
}

// function to draw the field

void Life_Draw(bool field[35][35]){
    const char wall = '|';
    for(int y = 34; y >= 0; y--){
        for(int a = 1; a <= 71; a++){
            cout << "-";
        }
        cout << "\n";
        cout << wall;
        for(int x = 0; x <= 34; x++){
            if((field[x][y]) == true){
                cout << "1";
            }else{
                cout << "0";
            }
            cout << wall;
        }
        cout << "\n";
    }
    for(int a = 1; a <= 71; a++){
            cout << "-";
        }
    cout << "\n";
}

// function to determine whether a single tile should be alive or dead in the next generation.

bool Life_Calc(int x, int y, bool lives, bool field[35][35]){
    short min = 0, max = 0, neighbours = /* linksonder >*/ (x && y && field[x-1][y-1]) + /* links >*/ (x && field[x-1][y]) + /* linksboven > */ (x && y != 34 && field[x-1][y+1]) + /* boven > */(y != 34 && field[x][y+1]) + /* rechtsboven > */ (x != 34 && y != 34 && field[x+1][y+1]) + /* rechts > */ (x != 34 && field[x+1][y]) + /* rechtsonder > */ (x != 34 && y && field[x+1][y-1]) + /* onder > */ (y && field[x][y-1]);
    if(lives){
        min = 2;
        max = 3;
    }else{
        min = 3;
        max = 3;
    }
    if(x == 2 && y == 1){
        donothing();
    }
    if(neighbours >= min && neighbours <= max){
        lives = true;
    }else{
        lives = false;
    }
    return lives;
}



// ****************************** //
// The main function starts here. //
// ****************************** //



int main(){
    cout << "\n\nMaximizing the window is highly recommended.\n\n";
    int x = 0, y = 0, input, input2, gen_wait;
    double gen_do = 0;
    bool field[35][35], play = true, done = true, erase = false;
    for(int x4 = 0; x4 <= 34; x4++){
        for(int y4 = 34; y4 >= 0; y4--){
            field[x4][y4] = false;
        }
    }   
    while(play){
        cout << "Do what?\n 1) Let me edit individual squares.\n 2) Make a glider for me.\n 3) Fill the field with blinkers.\n 4) Make generations pass.\n 5) Check whether a certain square is alive or not.\n 6) Show me the field.\n 7) " << char(34) << "Animate" << char(34) << " some generations.\n 8) Clear the entire field.\n 10) Exit the game.\n: ";
        cin >> input;
        cout << "\n";
        done = true;
            switch(input){
            case 1:
                // edit start
                x = 0;
                cout << "\nEnter the x-coordinate (Start counting from 1. the max is 35.) : ";
                while(x < 1 || x > 35){
                    cin >> x;
                    if(x < 1 || x > 35){
                        cout << "\nInvalid input. Try again: ";
                    }
                }
                y = 0;
                cout << "\nEnter the y-coordinate (Start counting from 1. the max is 35.) : ";
                while(y < 1 || y > 35){
                    cin >> y;
                    if(y < 1 || y > 35){
                        cout << "\nInvalid input. Try again: ";
                    }
                }
                input2 = 2;
                cout << "\nEnter 1 for alive or 0 for dead.: ";
                while(input2 != 1 && input2 != 0){
                    cin >> input2;
                    if(input2 != 1 && input2 != 0){
                        cout << "\nInvalid input. Try again: ";
                    }
                }
                if(input2 == 1){
                    field[x-1][y-1] = true;
                }else{
                    field[x-1][y-1] = false;
                }
                // edit end
                break;
            case 2:
                // glider start
                cout << "Erase the field first? Enter 1 for yes, 0 for no: ";
                cin >> erase;
                if(erase){  
                    // Erase field start
                    for(int var = 0; var <= 34; var++){
                        for(int var2 = 0; var2 <= 34; var2++){
                            field[var][var2] = false;
                        }
                    }
                    // Erase field end
                }
                for(int x3 = 0; x3 <= 34; x3++){
                    for(int y3 = 34; y3 >= 0; y3--){
                        field[x3][y3] = false;
                    }
                }
                field[1][0] = true; field[2][1] = true; field[0][2] = true; field[1][2] = true; field[2][2] = true;
                // glider end
                break;
            case 3:
            // blinkers start
            cout << "Erase the field first? Enter 1 for yes, 0 for no: ";
                cin >> erase;
                if(erase){
                    // Erase field start
                    for(int var = 0; var <= 34; var++){
                        for(int var2 = 0; var2 <= 34; var2++){
                            field[var][var2] = false;
                        }
                    }
                    // Erase field end
                }
            for(int y2 = 0; y2 <= 34; y2++){
                for(int x2 = 0; x2 <= 34; x2++){
                    if(y2 % 4 == 1 && x2 % 4 != 3){
                        field[x2][y2] = true;
                    }
                }
            }
            // blinkers end
            break;
        case 4:
            // pass start
            cout << "how many generations?: ";
            cin >> gen_do;
            cout << "\nLoading...";
            for(int b = 1; b <= gen_do; b++){
                // calc start
                bool field2[35][35];
                for(int x = 0; x <= 34; x++){
                    for(int y = 34; y >= 0; y--){
                        field2[x][y] = field[x][y];
                    }
                }
                for(int y = 34; y >= 0; y--){
                    for(int x = 0; x <= 34; x++){
                        field[x][y] = Life_Calc(x,y,field[x][y],field2);
                    }
                }
                // calc end
            }
            cout << "\n";
            // pass end
            break;
        case 5:
            x = 0;
            while(x < 1 || x > 35){
                cout << "Enter the x-coordinate: ";
                cin >> x;
                if(x < 1 || x > 35){
                    cout << "\nInvalid input. Try again.: ";
                }
            }
            y = 0;
            while(y < 1 || y > 35){
                cout << "Enter the y-coordinate: ";
                cin >> y;
                if(y < 1 || y > 35){
                    cout << "\nInvalid input. Try again.: ";
                }
            }
            cout << "\nThe cell on (" << x << ", " << y << ") is ";
            if(field[x][y]){
                cout << "Alive";
            }else{
                cout << "Dead";
            }
            cout << ".\n";
            break;
        case 6:
            // show start
            Life_Draw(field);
            // show end
            break;
        case 7:
            // animation start
            cout << "How many generations?: ";
            cin >> gen_do;
            cout << "How many seconds between generations? (Whole numbers only.): ";
            cin >> gen_wait;
            cout << "Wait up to 1 second please...";
            Wait_Secs(1);
            for(int b = 1; b <= gen_do; b++){
                // calc start
                bool field2[35][35];
                for(int x = 0; x <= 34; x++){
                    for(int y = 34; y >= 0; y--){
                        field2[x][y] = field[x][y];
                    }
                }
                for(int y = 34; y >= 0; y--){
                    for(int x = 0; x <= 34; x++){
                        field[x][y] = Life_Calc(x,y,field[x][y],field2);
                    }
                }
                // calc end
                if(b != gen_do){
                    for(int i = 0; i <= 15; i++){
                        cout << "\n";
                    }
                Life_Draw(field);
                Wait_Secs(gen_wait);
                }
            }
            // animation end
            break;
        case 8:
            // Erase field start
            for(int var = 0; var <= 34; var++){
                for(int var2 = 0; var2 <= 34; var2++){
                    field[var][var2] = false;
                }
            }
            // Erase field end
            break;
            case 10:
                // exit start
                play = false;
                done = false;
                // exit end
                break;
            default:
                // invalid start
                cout << "\nInvalid input. Try again.\n\n";
                done = false;
                // invalid end
                break;
        }
        if(done){
        cout << "\nDone.\n\n";
        }
    }
}

Recommended Answers

All 5 Replies

what compiler did you use? And what operating system?

The function want_secs() is completely unnecessary. If you want your program to wait for awhile then use os-specific api to do that so that other processes can get CPU time instead of your program hogging it all up.

MS-Windows: win32 api function named Sleep() (except old Turbo C, which has a wait() function of its own).

*nix: sleep() or wsleep()

To avoid having to read all of your code (laziness on my part, most assuredly), I'll just point out that your Wait_Secs() function is needlessly complex. It can be as simple as this if you make an assumption that time_t represents seconds (not an unreasonable assumption):

void Wait_Secs(int seconds)
{
    time_t start = time(NULL);

    while (time(NULL) < (start + seconds))
        ;
}

A better solution depends on difftime() which actually does return a guaranteed number of seconds and is no less simple in my opinion:

void Wait_Secs(int seconds)
{
    time_t start = time(NULL);

    while (difftime(time(NULL), start) < seconds)
        ;
}

Both your solutions are not as good as using the os api. Both your functions are CPU hogs.

Both your solutions are not as good as using the os api.

I'm aware of that.

Both your functions are CPU hogs.

I'm aware of that too. However, the point was not to come up with the best possible solution for waiting a number of seconds. The point was to show that the time library needn't be so awkward. The library is awkward enough without actively choosing a backassward method of getting the information you need.

This understanding will help with problems that cannot or should not be solved with an OS API for the given problem.

So much I want to say but i think this will be good.
you can if you want use \" for char(34).
'\"' == char(34)

This reminds me of programming in C for some reason.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.