Text-Based Adventure-Need Help

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
#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

string choice;
void roomB();
void roomA();

int main(int argc, char *argv[])
{
    
void roomA();
{
 cout << "You are in room A" << endl;
 cin >> choice;
  if ( choice == "roomB" )
  {
    roomB();
  }
}
void roomB();
{
 cout << "You are in room B" << endl;
 cin >> choice;
  if ( choice == "roomA" )
  {
    roomA();
  }
}

Okay, so I'm trying to break away from goto statements and also, goto statements take forever. I'm almost finished with this, I just need help fixing it.
What exactly do you need help with? What do you want the program to do?
I just want it to work. For some reason it keeps saying
undefined reference to 'roomA()'
undefined reference to 'roomB()'
I just cant figure it out
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
#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

// prototypes
void roomB();
void roomA();
string choice;

int main(int argc, char *argv[])
{
    // assuming you want to start in roomA:
    roomA();
}

void roomA()
{
 cout << "You are in room A" << endl;
 cin >> choice;
  if ( choice == "roomB" )
  {
    roomB();
  }
}

void roomB()
{
 cout << "You are in room B" << endl;
 cin >> choice;
  if ( choice == "roomA" )
  {
    roomA();
  }
}

- Prototypes look like type myFunction();
- Function declerations lose the ';' type myFunction() { //... }
- Don't declare your function inside of other functions (you delcared both inside of the main function)
- You should maybe have "Choose a room: 1) Dungeon, 2) Commonroom" then ask for an integer input (int choice) instead of asking for a string.
- Add some error code for invalid inputs (if room isn't 1 or 2.. do this)
Last edited on
Hello GrailStudios,

I just joined up here and came across your topic. Your problem is that you are trying to use your functions before declaring them properly. The correct code would be this:
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
#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

string choice;
void roomB();
void roomA();

int main(int argc, char *argv[])
{
    roomA();
}

void roomA();
{
 cout << "You are in room A" << endl;
 cin >> choice;
  if ( choice == "roomB" )
  {
    roomB();
  }
}

void roomB();
{
 cout << "You are in room B" << endl;
 cin >> choice;
  if ( choice == "roomA" )
  {
    roomA();
  }
}


I hope that helps you =D
Last edited on
Yes, it does. Thank you!
I slightly improved your code so that it won't close even if you don't type in roomA or roomB.

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
#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

string choice;
void roomB();
void roomA();

int main(int argc, char *argv[])
{
    roomA();
}

void roomA()
{
 cout << "You are in room A" << endl;
 cin >> choice;
  if ( choice == "roomB" )
  {
    roomB();
  }
  else
  {
    roomA();
  }
}

void roomB()
{
 cout << "You are in room B" << endl;
 cin >> choice;
  if ( choice == "roomA" )
  {
    roomA();
  }
  else
  {
    void roomB();
  }
}
You are using functions as if they were gotos, which is a bad idea.

If the player keeps moving from room A to room B and back again, the computer has to remember where each call came from so it can "return" out of the function. It builds what's called a "call stack".

For example:

1
2
3
4
5
6
7
8
9
10
11
void foo()
{
  cout << "foo";
}

int main()
{
  foo();  // foo called here
  // once foo "returns" / exits, the computer comes back here
  cout << "after foo";
}


So by calling roomA from roomB and vice versa, you will force the computer to remember all the function calls. Eventually, if the user moves between them enough, you will run out of stack space and your program will crash.


An alternative is to do something more state based:

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
enum Location
{
  RoomA,
  RoomB
};

Location DoRoomA()
{
  // do stuff in room A
  if( user_wants_to_go_to_room_b )
  {
    return RoomB;
  }
}

Location DoRoomB()
{
  // do stuff in room B

  if( user_wants_to_go_to_room_a )
  {
    return RoomA;
  }
}

int main()
{
  Location playerpos = RoomA;  // start in Room A
  while( user_is_playing )
  {
    switch(playerpos)
    {
    case RoomA:  playerpos = DoRoomA();  break;
    case RoomB:  playerpos = DoRoomB();  break;
    }
  }
}
Last edited on
gotcha,

I do love those switch(state) loops
I actually greatly dislike them as they require you to keep multiple areas of code in sync (if you add a new room, you have to update the room function as well as all the switch statements that check the current room). I just showed it because it's simpler than some of the other alternatives.

A better way might be to have some kind of inheritance-based mechanism:

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
class Location
{
public:
  virtual Location* Run() = 0;
};

class RoomA : public Location
{
public:
  virtual Location* Run()
  {
    // do roomA stuff
    //  if user goes to room B
      return new RoomB;
  }
};

// .. same idea for RoomB

int main()
{
  Location* current = new RoomA;
  Location* next = 0;

  while( current != 0 )
  {
    next = current->Run();
    delete current;
    current = next;
  }
}
yeah i dont know how to use classes (yet) so thats probably why I like switch(cases).

Topic archived. No new replies allowed.