Always Crashes - Why?

OK. So I'm making this program from my C++ course. I have to run a game of Hi Ho Cherry-O. I made one version of the code (which worked perfectly), until I realized I was supposed to make an array for the players' information. So I reworked the cord, using the already existing code. When I run in CodeBlocks, it crashes right after I get all four players' information, before entering the while loop within int main. When I run in Visual C++, it crashes right as I attempt to enter the last player's information. I need serious help. What did I do wrong to make the code no longer work?

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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <cctype>

using namespace std;

//declare functions
void Opening (void);
void GetPLayerInfo (struct AllPlayersT * Player);
void PlayGame (string & winner, int & winnerAge, string & winnerThing, struct AllPlayersT * Player);
void PrepareGameBoard (string & winner, int newCherries, int & winnerAge, string & winnerThing, struct AllPlayersT * Player);
......

//declare constants
const int MAX_CHERRIES = 10;
const int MAX_NUMBER_OF_PLAYERS = 4;
const string COMP_1 = "Alphie";
const string COMP_2 = "Bettie";
const string COMP_3 = "Deltie";
const string COMP_4 = "Gammie";

//declare player struct
struct AllPlayersT
{   string name, thing;
    int age, playerCherry;
};

int main (){
    //declare variables
    int rounds = 0, winnerAge =0;
    string winner, winnerThing, enter;
    AllPlayersT Player [MAX_NUMBER_OF_PLAYERS];

    Opening();
    winner = "NONE";

    //Player and computer info
    GetPLayerInfo(Player);

    cout << "Now let's play the game! You go first " << Player[1].name << ". Hit ENTER to spin!" << endl;
    getline(cin, enter);

    while (winner.find("NONE") != string::npos)
    {   rounds ++;
        PlayGame(winner, winnerAge, winnerThing, Player);
    }
    //make sure correct ending
    CorrectEnding(winner, winnerThing, winnerAge, rounds);

    return 0;
}
/*  This routine welcomes the player to the game.
    no input or output
*/
void Opening (void)
{   cout << "Hello, and welcome to a fun game of Hi Ho! Cherry-O!";
    cout << endl << endl;
    return;
}
/* This routine gets the players information in the PLayerT struct.
    no input
    Its output is the stuct human.Player.
*/
void GetPLayerInfo(struct AllPlayersT * Player)
{   int i=0, times = 1;
    char answer;

    while (i != MAX_NUMBER_OF_PLAYERS)
    {   i ++;
        cout << "Are you a player or commputer (p for player or c for computer)=>";
        cin >> answer;
        if (answer == 'p')
        {   cin.ignore(80,'\n');
            cout << "What is your name? => ";
            getline(cin, Player[i].name);
            cout << endl;
            cout << "How old are you? => ";
            cin >> Player[i].age;
            Player[i].thing = "human";
        }
        if (answer == 'c')
        {   if (times == 1)
            {Player[i].name = COMP_1;
            }
            if (times == 2)
            {Player[i].name = COMP_2;
            }
            if (times == 3)
            {Player[i].name = COMP_3;
            }
            if (times == 4)
            {Player[i].name = COMP_4;
            }
            Player[i].thing = "computer";
            cout << "How old is this computer player? => ";
            cin >> Player[i].age;
            times ++;
        }
        cout << endl << endl;
    }
    return;
}
/*  The routine contain how the game is played.
    the input is the humanplayer's info and all the number of cherries in each basket.
    the output is the string which will contain the winner's name
*/
void PlayGame(string & winner, int & winnerAge, string & winnerThing, struct AllPlayersT * Player)
{   int number = 0, newCherries = 0, i = 0;

    srand (time(NULL));
    cout << "here" << endl;
    while (i != MAX_NUMBER_OF_PLAYERS)
    {   i ++;
        cout << "in here" << endl;
        if (Player[i].thing == "human")
        {   newCherries = 0;
            cout << Player[i].name << ", it is your turn," << endl;
            cout << "Press Enter to spin." << endl;
            cin.ignore();
            cout << endl << endl;
            number = rand()%10 - 1;
            Spinner (number, newCherries);
        }
        if (Player[i].thing == "computer")
        {   newCherries = 0;
            cout << "It is now " << Player[i].name << "'s turn." << endl;
            cout << Player[i].name << " spun the spinner." << endl;
            cout << endl << endl;
            number = rand()%10 - 1;
            Spinner (number, newCherries);
        }
    }
    PrepareGameBoard(winner, newCherries, winnerAge, winnerThing, Player);

    if (winner.find("NONE") == string::npos)
    {
        return;
    }
    GameBoard(Player);

    cout << "Press ENTER to contine:" << endl;
    cin.ignore();
    cout << endl << endl;
    return;
}
......
Any time you have
1
2
3
while (i != MAX_NUMBER_OF_PLAYERS)
{   i ++;
    // ... 
move the i++; to the bottom of the loop, or replace that whole thing with a for loop:
1
2
3
for (int i = 0; i < MAX_NUMBER_OF_PLAYERS; ++i)
{
    // ... 

The reason it's crashing is because you increment i at the start of the loop, so instead of storing the information in Player[0], Player[1], ..., Player[MAX_NUMBER_OF_PLAYERS-1], it stores to Player[1], Player[2], ..., Player[MAX_NUMBER_OF_PLAYERS] (this last one is out of bounds).
Um, I'm not sure if you didn't get all the code pasted but there is a lot of undefined functions in this code. Visual Studio will not compile it for me. The following is showing up as undefined:

Error 1 error C3861: 'CorrectEnding': identifier not found cplusplus
Error 4 error C3861: 'Spinner': identifier not found cplusplus
Error 5 error C3861: 'GameBoard': identifier not found
6 IntelliSense: identifier "CorrectEnding" is undefined cplusplus
7 IntelliSense: identifier "Spinner" is undefined cplusplus
8 IntelliSense: identifier "Spinner" is undefined cplusplus
9 IntelliSense: identifier "GameBoard" is undefined cplusplus

I would suggest creating definitions for these functions or if you've already defined them to please post the rest of the code.
Last edited on
long double main: Ok I made the changes you suggested but it still crashes in the same place.

unsensible: Those fuctions are defined. I'm sorry. I didnt think to post the rest of the code.
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
130
131
132
133
134
135
136
137
138
139
140
141
142
// rest of declarations
void Spinner (int number, int & newCherries);
void SpilledBasketCheck (int newCherries, int & cherries);
void GameBoard (struct AllPlayersT Player[]);
void MakeBoard (int cherries);
void CorrectEnding (string winner, string winnerThing, int winnerAge, int rounds);
void PrintUserEnding (string winner, int winnerAge, int rounds);
void PrintComputerEnding (string winner, int winnerAge, int rounds);

// the functions
void Spinner (int number, int & newCherries)
{  switch (number){
        case 1:
            newCherries = 1;
            break;
        case 2:
            newCherries = 2;
            break;
        case 3:
            newCherries = -2;
            break;
        case 4:
            newCherries = 4;
            break;
        case 5:
            newCherries = 1;
            break;
        case 6:
            newCherries = 2;
            break;
        case 7:
            newCherries = 3;
            break;
        case 8:
            newCherries = 4;
            break;
        case 9:
            newCherries = -2;
            break;
        case 0:
            newCherries = 0;
            break;
        cout << "Got here too!" << endl;
    }
}

void PrepareGameBoard(string & winner, int newCherries, int & winnerAge, string & winnerThing,  struct AllPlayersT * Player)
{   int cherries = 0, number = 0;

    cout << "Got here!" << endl;
    //get cherries for all the theys
    for (int i = 0;i < MAX_NUMBER_OF_PLAYERS; i++)
    {   cherries = Player[i].playerCherry + newCherries;
        SpilledBasketCheck(newCherries, cherries);
        Player[i].playerCherry = cherries;
        cout << newCherries << endl;

        if (cherries >= MAX_CHERRIES)
        {   winner = Player[i].name;
            winnerAge = Player[i].age;
            winnerThing = Player[i].thing;
            return;
        }
    }
}

void SpilledBasketCheck(int newCherries, int & cherries)
{  if (newCherries == 0)
    {   cherries = 0;
        cout << "Oh no! You spilled your basket!. You have 0 cherries now.";
        cout << endl<< endl;
    }
    if (newCherries < 0)
    {   cherries = cherries - newCherries;
        cout << "Oh no! A bird/dog took two of your cherries!   You now have " << cherries << " left." << endl;
        cout << endl << endl;
        return;
    }
    if (cherries <= MAX_CHERRIES && cherries > 0)
    {   cout << "You picked " << newCherries << " cherries.     You now have " << cherries << "." << endl;
        cout << endl << endl;
    }
    if (cherries >= MAX_CHERRIES)
    {   cout << "You won! Hi Ho Cherry-o!";
        cout << endl << endl;
        return;
    }
    return;
}

void GameBoard (struct AllPlayersT Player[])
{   int cherries =0;

    for (int i = 0;i < MAX_NUMBER_OF_PLAYERS; i++)
    {   cout << "Player " << i << " " << Player[i].name  << ",   (" << Player[i].playerCherry
             << ")    is a " << Player[i].thing << "          ";
        cherries = Player[i].playerCherry;
        MakeBoard(cherries);
    }
    return;
}

void MakeBoard(int cherries)
{   int i;

    for (i=0; i< cherries; i++)
    {
        cout << " *";
    }
    for (i=0; i <= MAX_CHERRIES - cherries; i++)
    {
        cout << " o";
    }
    cout << endl;
    return;
}

void CorrectEnding(string winner, string winnerThing, int winnerAge, int rounds)
{   if (winnerThing == "human")
    {
        PrintUserEnding(winner, winnerAge, rounds);
    }
        else
            PrintComputerEnding(winner, winnerAge, rounds);
    return;
}

void PrintUserEnding (string winner, int winnerAge, int rounds)
{
    cout << winner <<" have won the game. You did so in " << rounds << " rounds." << endl;
    cout << "That is very good for a human of " << winnerAge<<  " years old." << endl;
    return;
}

void PrintComputerEnding (string winner, int rounds, int winnerAge)
{   cout << "I'm sorry but you have lost to " << winner << " the computer." << endl;
    cout << winner << " won in " << rounds << " rounds, which is pretty bad for a computer of "
         << winnerAge << " years old." << endl;
    return;
}

Thank you. I believe the issue is in your GetPlayerInfo function. The main issue is this piece of code:

1
2
 while (i != MAX_NUMBER_OF_PLAYERS)
    {   i ++;


The issue is that you're increment i BEFORE populating the struct array. So what ends up happening is that i will be 4 which means it's attempting to access an area in the array that doesn't exist. Even though Player can have 4 players, it only counts as 0-3 instead of 1-4.

So basically, just put i++ at the bottom of the loop instead of at the beginning.
Last edited on
Looking further into the program, I believe you have the same problem in your PlayGame function. I would suggest putting the i++ from the beginning of that loop to the end as well.
Topic archived. No new replies allowed.