Trying to make a simple text adventure to practice C++

I’ve just completed the Triple X section of the course and decided to take on a project for myself. I’m trying to make a text adventure. How it works is it presents you with a scenario and a number of choices afterward. Each choice may lead to a another scenario. How I had it planned out looks something like this:

#include <iostream>

void PrintIntroduction()
{
    std::cout << "---------------------------------------------------------------------------";
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << "-- Welcome to my game!\n";
    std::cout << "-- Through the course of this game you will be\n";
    std::cout << "   presented with a scenario and some options.\n";
    std::cout << "-- When you have chosen your option, simply type\n";
    std::cout << "   the number of that option and press enter to continue.\n";
    std::cout << "-- Enjoy the game!";
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << "---------------------------------------------------------------------------";
}

void Sec1()
{
    int PlayerChoice;
    
    std::cout << std::endl;
    std::cout << "*************************************************************************";
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << "++ From outside of the void you hear a voice calling to you.\n";
    std::cout << "++ \"Awaken, slave. Hear my words and obey!\"\n";
    std::cout << "++ From everywhere you feel tendrils of will tugging at your essence.\n";
    std::cout << "++ It feels like being drawn from a deep sleep.";
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << "*************************************************************************";
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << "What do you do?\n";
    std::cout << std::endl;
    std::cout << "1 . Try to resist\n";
    std::cout << "2 . Surrender your will\n";
    std::cin >> PlayerChoice;

    if(PlayerChoice == 1)
    {
        Sec2();

        if(PlayerChoice == 2)
        {
            Sec4();
        }
    }
}

This is one section. Sec2 and Sec4 would look very similar.
The idea is that the player chooses an option, types the number of that option, presses enter and will be taken to the next section, etc.
Then, to start the whole thing off:

int main ()
{

    system("CLS");
    PrintIntroduction();
    std::cout << std::endl;
    std::cout << std::endl;
    system("pause");
    system("CLS");
    Sec1();

}

What this does is it clears the terminal, prints the introduction and then presents the player with a prompt to press any key to continue. When the player presses a key it it clears the terminal again and calls Sec1.

The problem must is probably obvious by now. I didn’t account for the fact that I can’t, for example, call Sec4 from inside of Sec1 because it hasn’t been defined yet (I think). I also don’t believe I can use a loop with something like section++ every time you complete a section because answer 2 in Sec1 will go to Sec4 and at one point, I believe, Sec99 loops back to Sec63, for example.

I’m sure the answer somehow involves parameters and variable scope somehow, but I just figured out how those work today, so I have no idea.

Thanks in advance.

EDIT

So I figured out that if I rearrange the sections so that Sec1 is defined last and then called in main it seems to work so far. However, I’d still like to hear from you guys because there are literally about 100 bits of dialogue, each one a section, and they get thrown out of order quick. So I’m worried that I’ll code them all neatly just to find out that, even if I order them from 100 down to 1, if a choice leads the player to loop back from Sec63 to Sec44 (which might be on a completely different dialogue branch), it might not work because Sec44 isn’t defined before Sec63.

I’m not really going to help here (besides this reply) as there’s more than one way to do this and that is up to you to decide - that is part of being a programmer.

For example you state “something like section++” but you can also do a “section = eg 32” or even add in a “last section” if you really need it. You can use getters and setters. You may need to do “other things” because if you have branching paths you will need to know (and in the end the code) which ones can go where.

As far as this “Sec44 isn’t defined before Sec63”, you haven’t yet learned enough to know how to work around this and I suggest you learn this part of c++ better. The c++ course here should get you onto the right track as its really hard to make anything if there’s not a way to use something anywhere you need it. I don’t need to duplicate anything in this reply.

Hopefully, that helps you in some way.

1 Like

Your problem is basically more of a design problem than an actual coding problem. You need to know which sections a section is hooked up to, before you get into coding. You could actually use a map to handle all your sections, that at least what I would do. Your key could be an integer and your value could be a pointer to your section object. Then you could create all the objects you need at the beginning of the program, have them sitting somewhere in memory and have a pointer to them in your map. Accessing code from somewhere else is usually not the problem and should be doable quite easily. If that is the thing you are struggling with I would recommend to rather follow some more C++ tutorials and come back to it in a week or two.

1 Like

The first problem you should tackle is factoring out what you have so far. Every time you see yourself repeating code, think about how you can solve that issue so you don’t have to, DRY.

For a basic starter example, you currently have

std::cout << "*************************************************************************";
std::cout << std::endl;
std::cout << std::endl;
///
//message
///
std::cout << std::endl;
std::cout << std::endl;
std::cout << "*************************************************************************";

Twice already, that’s a lot to repeat every time you want to enter some story text. How can you factor that out into a function so you just type

PrintStory(Message);

(Also I would change the std::endl's to ‘\n’ just because that’s a lot of screen space just for 4 newlines)

1 Like

Hello all,
Thanks for your suggestions. I made it work somehow.
It’s still not very efficient but I decided to go with this way since it works and the original idea was just to practice what I learned in the Tripple X section. It has since gotten quite out of hand and developed several possible endings and a few branches of dialogue that completely branches off from the main story, so I’m kind of overdoing it.

1 Like

As others have mentioned, there are many ways to go about this. Ultimately, you’d learn more about data structures in C++, and come up with a general data object (class or structure) definition for the current location in the game. Most of the game details would be encoded into the data structure, and the main game loop would then be more or less a single function that interacts with the game location data structure. The full game map would be a graph of connected locations referring to each other. That’s just to give you an understanding of what you’re shooting for if you’d like to do this “right”, it is too advanced for this point in the course.

Your approach of putting each location in the game into its own function can work fine for a simple game, though. You can solve the “who comes first” problem of function SecAA() not knowing about function SecXX() in C++ by declaring all the functions before defining them.

In C++ you can declare and define functions, these are different things. When you declare a function in C++ you’re just telling the compiler that “I have a function with this name, it has this return type, and takes these types of parameters [the names of the parameters don’t matter and you can even leave them out if you like], and I’ll fill in the code details later”. The “details” is the definition of the function, when you provide the code for the function in between the curly braces.

A function definition is what the course tells you about: a function name with its return type, parameters, and code:

 // definition of MyFunction, a function with no return type 
// and taking a single int parameter
void MyFunction(int argument)  
{
    /* do something */
}

A function declaration looks just like a function definition, just without the braces and code, and ending with a semi-colon:

 // declaration of MyFunction, a function with no return type 
// and taking a single int parameter

void MyFunction(int argument);
// no code here!   Declarations have no code, only definitions have code

In this way you can declare all your functions before defining them, and have no chicken-and-the-egg problems with cycles in the call graph (function A calls function B calls function C calls function A).

// declare all functions ahead of defining them
void funcA();
void funcB();
void funcC();

// define functions
void funcA()
{
    funcB();
}

void funcB()
{
    funcC();
}

void funcC()
{
    funcA();
}

There’s more to say about organizing this nicely (“header files”) but the course hasn’t talked about creating your own at this point. You can look it up for yourself (normally function declarations go in header files named “file.h” or “file.hpp” and you #include them into your source code file).

This is how you can solve your dilemma and produced your adventure game :).

Oh, and by the way, a function can have many declarations (as long as all the details agree), but only one definition. And be careful, in C++ you can declare functions with the same name but different parameters and return types (“overloading”), so make sure the “signature” (return type, name, and types and number of parameters in a specific order" agree between your declarations and your definitions).