Weird and Unwanted Error!

Hello again!
I'm writing a "Rock, Paper, Scissors"-program, and it is going pretty well, except for one little problem. Whenever the user enters that it doesn't want to play anymore, the program still goes on as if the user had entered that it wanted to continue playing. Here is an example of what the program outputs:

Do you want to play again?

(1) Yes.
(2) No.

2

Goodbye!The computer chose scissors!
Do you want to play again?
(1) Yes.
(2) No.

And after that you can go on playing. I have no clue why the program is doing this, could you look into my code and find out? It is quite long, but I couldn't shorten it down because maybe then you wouldn't be able to find the problem. BTW, sorry for using system("BLABLABLA"), I know that I shouldn't. There maybe are a few things in my code that could be shortened down or completely removed for further effectiveness.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

void computerChoice(string comparison, int counter2, int losses4);
void continuing(int counter3, int losses3);
void statistics(int counter4, int losses2);

int main(){
    string type;
    int counter1 = 0, losses1 = 0;
    cout << "-= Rock, Paper, Scissors =-\n\n";
    while(type != "rock" && type != "paper" && type != "scissors" && type != "statistics"){
        cout << "Rock, paper, scissors or statistics? "; cin >> type;
        if(type == "statistics"){
            statistics(counter1, losses1);
        }
    }
    computerChoice(type, counter1, losses1);
    return(0);
}

void continuing(int counter3, int losses3){
    string type;
    cout << "-= Rock, Paper, Scissors =-\n\n";
    while(type != "rock" && type != "paper" && type != "scissors" && type != "statistics"){
        cout << "Rock, paper, scissors or statistics? "; cin >> type;
        if(type == "statistics"){
            statistics(counter3, losses3);
        }
    }
    computerChoice(type, counter3, losses3);
}

void computerChoice(string comparison, int counter2, int losses4){
    srand(time(0));
    int answer = 0;
    int x = 1+(rand()%3);
    switch(x){
        case 1:
            cout << "The computer chose rock!" << endl;
            if(comparison == "rock"){
                cout << "No one won!\n" << endl;
                break;
            }
            if(comparison == "paper"){
                counter2++;
                cout << "Paper covers rock; you win!\n" << endl;
                break;
            }
            if(comparison == "scissors"){
                losses4++;
                cout << "Rock breaks scissors; you lose!\n" << endl;
                break;
            }
            break;
        case 2:
            cout << "The computer chose paper!" << endl;
            if(comparison == "rock"){
                losses4++;
                cout << "Paper covers rock; you lose!\n" << endl;
                break;
            }
            if(comparison == "paper"){
                cout << "No one won!\n" << endl;
                break;
            }
            if(comparison == "scissors"){
                counter2++;
                cout << "Scissors cut paper; you win!\n" << endl;
                break;
            }
            break;
        case 3:
            cout << "The computer chose scissors!" << endl;
            if(comparison == "rock"){
                counter2++;
                cout << "Rock breaks scissors; you win!\n" << endl;
                break;
            }
            if(comparison == "paper"){
                losses4++;
                cout << "Scissors cut paper; you lose!\n" << endl;
                break;
            }
            if(comparison == "scissors"){
                cout << "No one won!\n" << endl;
                break;
            }
            break;
    }
    while(answer != 1 && answer != 2){
        cout << "Do you want to play again?\n\n(1) Yes.\n(2) No.\n\n"; cin >> answer;
        if(answer == 1){
            system("CLS");
            continuing(counter2, losses4);
        }
        if(answer == 2){
            cout << "\nGoodbye!";
        }
    }
}

void statistics(int counter4, int losses2){
    int answer1 = 0;
    if(counter4 == 0 || losses2 == 0){
        cout << "Welcome to the statistics board!\n\nWins: " << counter4 << "\nLosses: " << losses2 << "\n" << endl;
    }
    if(counter4 != 0 && losses2 != 0){
        cout << "Welcome to the statistics board!\n\nWins: " << counter4 << "\nLosses: " << losses2 << "\nWin/Loss-ratio: " << counter4/losses2 << "\n" << endl;
    }
    while(answer1 != 1 && answer1 != 2){
        cout << "Do you want to play again?\n\n(1) Yes.\n(2) No.\n\n"; cin >> answer1;
        if(answer1 == 1){
            system("CLS");
            continuing(counter4, losses2);
            break;
        }
        if(answer1 == 2){
            cout << "\nGoodbye!";
        }
    }
}
as far as i know, and i could be wrong.
There is no safe/effective way to end a program outside of main. I would suggest just sending the program up to the end of main before the return 0; if the user selects "2"
@GoranGaming

Your program continues when the statistics function ends, which then takes control to line 20 in main - where everything starts over.

You have some repetition in your code lines 93 - 102 and 113 - 123. That code should be in a function which should clear up the logic a bit. Also the continuing function.

while(type != "rock" && type != "paper" && type != "scissors" && type != "statistics"){
I personally hate really dislike constructs like this. They are error prone and not scalable - what if you had 20 options for your menu?

Much better to use a switch for menu options:

http://www.cplusplus.com/forum/beginner/99203/#msg534078


If you want a choice between 2 options, just use an ordinary if statement.
@Blanchy

Not really - there are several ways of doing this, and your answer implies using goto :

- Have a quit option in the main menu;
- Have a value returned from a function that means the user wants to quit;
- Use the rather abrupt exit function
@Blanchy

I'll try that!

@TheIdeasMan

Do you mean that I should set a number for each option and then use a switch instead? I use the while loop because I want it to repeat if you enter something that's not allowed, although I'm sure you could do that with a switch in some way.

This works fine with 4 options, it is not choosing options that is the problem in my program, so why wouldn't it work with 20? Sure, it would look a little strange, but it would work :) I think...
Last edited on
@TheIdeasMan and Blanchy

I remade the program, so that it always goes back to the menu despite if you want it or not, and it works fine now. There is only one issue, the statistics board seems a little bit weird. It outputs this:

Wins: 4
Losses: 5
Win/Loss-ratio: 0.00

The win/loss-ratio shouldn't be 0.00, it should be 0.8. I don't know why it does this, it works with integers though. Could you explain what's going on for me?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void statistics(int counter4, int losses4){
    cout << "Welcome to the statistics board!\n" << endl;
    if(counter4 == 0 || losses4 == 0){
        cout << "Wins: " << counter4 << "\nLosses: " << losses4 << "\n\n";
    }else{
        double resultat = counter4/losses4;
        cout << "Wins: " << counter4 << "\nLosses: " << losses4 << "\nWin/Loss-ratio: " << fixed << setprecision(2) << resultat << "\n\n";
    }
    cout << "Press enter to go back to the menu!" << endl;
    cin.get();
    cin.get();
    system("CLS");
    continuing(counter4, losses4);
}
integer division returns an integer
4/5 is 0
4.0/0.5 approximates 0.8 ;)
GoranGaming wrote:
Do you mean that I should set a number for each option and then use a switch instead? I use the while loop because I want it to repeat if you enter something that's not allowed, although I'm sure you could do that with a switch in some way.


GoranGaming wrote:
I remade the program, so that it always goes back to the menu despite if you want it or not, and it works fine now


I am not sure how you changed your program, so I will explain what my code does briefly.

If you look at it you will see the switch inside the while loop. The switch has a default clause to catch bad input which causes the loop to go around again. In this way you can accomplish your goal. The switch makes it scalable - that is easy to add lots more options to a menu, in an easy to understand way.

How did you get along with the other things I mentioned - it would be nice to see your new code :-)
Sure, here you go:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
using namespace std;

void computerChoice(int type2, int counter2, int losses2);
void continuing(int counter3, int losses3);
void statistics(int counter4, int losses4);

int main(){
    int type1 = 0, counter1 = 0, losses1 = 0;
    cout << "-= Rock, Paper, Scissors =-\n\n(1) Rock.\n(2) Paper.\n(3) Scissors.\n(4) Statistics.\n(5) Quit.\n\n"; cin >> type1;
    switch(type1){
        case 1:
            computerChoice(type1, counter1, losses1);
            break;
        case 2:
            computerChoice(type1, counter1, losses1);
            break;
        case 3:
            computerChoice(type1, counter1, losses1);
            break;
        case 4:
            statistics(counter1, losses1);
            break;
        case 5:
            cout << "Goodbye!";
            break;
        default:
            system("CLS");
            main();
    }
    return(0);
}

void continuing(int counter3, int losses3){
    int type3;
    cout << "-= Rock, Paper, Scissors =-\n\n(1) Rock.\n(2) Paper.\n(3) Scissors.\n(4) Statistics.\n(5) Quit.\n\n"; cin >> type3;
    switch(type3){
        case 1:
            computerChoice(type3, counter3, losses3);
            break;
        case 2:
            computerChoice(type3, counter3, losses3);
            break;
        case 3:
            computerChoice(type3, counter3, losses3);
            break;
        case 4:
            statistics(counter3, losses3);
            break;
        case 5:
            cout << "Goodbye!";
            break;
        default:
            system("CLS");
            main();
    }
}

void computerChoice(int type2, int counter2, int losses2){
    srand(time(0));
    int x = 1+(rand()%3);
    switch(x){
        case 1:
            cout << "The computer chose rock!" << endl;
            if(type2 == 1){
                cout << "No one wins!" << endl;
            }
            if(type2 == 2){
                cout << "Paper covers rock; you win!" << endl;
                counter2++;
            }
            if(type2 == 3){
                cout << "Rock breaks scissors; you lose!" << endl;
                losses2++;
            }
            break;
        case 2:
            cout << "The computer chose paper!" << endl;
            if(type2 == 1){
                cout << "Paper covers rock; you lose!" << endl;
                losses2++;
            }
            if(type2 == 2){
                cout << "No one wins!" << endl;
            }
            if(type2 == 3){
                cout << "Scissors cut paper; you win!" << endl;
                counter2++;
            }
            break;
        case 3:
            cout << "The computer chose scissors!" << endl;
            if(type2 == 1){
                cout << "Rock breaks scissors; you win!" << endl;
                counter2++;
            }
            if(type2 == 2){
                cout << "Scissors cut paper; you lose!" << endl;
                losses2++;
            }
            if(type2 == 3){
                cout << "No one wins!" << endl;
            }
            break;
    }
    cout << "Press enter to go back to the menu!" << endl;
    cin.get();
    cin.get();
    system("CLS");
    continuing(counter2, losses2);
}

void statistics(int counter4, int losses4){
    cout << "Welcome to the statistics board!\n" << endl;
    if(counter4 == 0 || losses4 == 0){
        cout << "Wins: " << counter4 << "\nLosses: " << losses4 << "\n\n";
    }else{
        double resultat = counter4/losses4;
        cout << "Wins: " << counter4 << "\nLosses: " << losses4 << "\nWin/Loss-ratio: " << fixed << setprecision(2) << resultat << "\n\n";
    }
    cout << "Press enter to go back to the menu!" << endl;
    cin.get();
    cin.get();
    system("CLS");
    continuing(counter4, losses4);
}
1
2
3
4
5
...
default:
    system("CLS");
    main();
...


Never, ever, ever call main() directly.
Why? How do you think that I should do it instead?
@GoranGaming

You didn't put the switch inside a while loop like I had in my code:

http://www.cplusplus.com/forum/beginner/99203/#msg534078


if you did, then it would cause the while loop to go around again.

Do you see how it works now?
Yeah. I get it know. Is there anything else I could improve in my code? Why I have a "continuing" function is because I set the value of wins and losses to 0 in the main function, so if I would always go back there instead, the wins- and losses-counter would always go back to zero.
Last edited on
I'm not sure, but is return 0; important to terminate program successfully?
No. I think I read somewhere that it is not necessary, but I still always write it in the end of main(); and I don't know why really.
Last edited on
Topic archived. No new replies allowed.