I am currently on the path of learning C++ and this is an example program I wrote for the course I'm taking. I know that there are things in here that probably makes your skin crawl if you're experienced in C/C++, heck the program isn't even finished, but I mainly need to know why I keep receiving this error after I enter my name: Exception thrown at 0x79FE395E (vcruntime140d.dll) in Learn.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC. I know there is something wrong with the constructors and initializations of the member variables of the classes but I cannot pinpoint the problem, even with the debugger. I am running this in Visual Studio and it does initially run, but I realized it does not compile with GCC. Feel free to leave some code suggestions, but my main goal is to figure out the program-breaking issue.
#include <iostream>
#include <string>
#include <cstdio>
#include <array>
#include <cstdlib>
#include <ctime>
int getRandomNumber(int min, int max)
{
    static constexpr double fraction{ 1.0 / (RAND_MAX + 1.0) };
    return min + static_cast<int>((max - min + 1) * (std::rand() * fraction));
}
class Creature
{
protected:
    std::string m_name;
    char m_symbol;
    int m_health;
    int m_damage;
    int m_gold_count;
public:
    Creature(const std::string name, char symbol, int health, int damage, int gold_count) :
        m_name{ name }, m_symbol{ symbol }, m_health{ health }, m_damage{ damage }, m_gold_count{ gold_count }
    {}
    const std::string getName() const { return m_name; }
    const char getSymbol() const { return m_symbol; }
    const int getHealth() const { return m_health; }
    const int getDamage() const { return m_damage; }
    const int getGold() const { return m_gold_count; }
    void reduceHealth(int hp_taken) { m_health -= hp_taken; }
    bool isDead() const { return m_health <= 0; }
    void addGold(int gold) { m_gold_count += gold; }
};
class Player : public Creature
{
private:
    int m_level = 1;
public:
    Player(const std::string name) : Creature{ name, '@', 10, 1, 0}
    {}
    int getLevel() { return m_level; }
    void levelUp() { ++m_level; ++m_damage; }
};
class Monster : public Creature
{
public:
    enum class Type
    {
        dragon,
        orc,
        slime,
        max_types
    };
private:
    static const Creature& getDefaultCreature(const Type& type)
    {
        static const std::array<Creature, static_cast<std::size_t>(Type::max_types)> monsterData{
        { {"dragon", 'D', 20, 4, 100}, {"orc", 'o', 4, 2, 25}, {"slime", 's', 1, 1,10}}
        };
        return monsterData.at(static_cast<std::size_t>(type));
    }
public:
    Monster(const Type& type) : Creature{getDefaultCreature(type)}
    {
    }
    static const Monster& getRandomMonster() {
        return Monster(static_cast<Type>(getRandomNumber(0, static_cast<int>(Type::max_types)-1)));
    }
};
void attackPlayer(const Monster& monster, Player& player) {
    std::cout << "The " << monster.getName() << " hit you for " << monster.getDamage() << ".\n";
    player.reduceHealth(monster.getDamage());
}
void attackMonster(Monster& monster, Player& player) {
    std::cout << "You hit the " << monster.getName() << " for " << player.getDamage() << ".\n";
    monster.reduceHealth(player.getDamage());
    if (monster.isDead()) {
        printf("The %s is dead!\n", monster.getName());
        player.levelUp();
        player.addGold(monster.getGold());
        if (player.getLevel() == 20)
            printf("You won!");
        return;
    }
    attackPlayer(monster, player);
}
void fightMonster(Player& player) {
    Monster m{ Monster::getRandomMonster() };
    printf("You have encountered a %s (%c).\n", m.getName(), m.getSymbol());
    while (!m.isDead() && !player.isDead()) {
        std::cout << "(R)un or (F)ight: ";
        char choice;
        std::cin >> choice;
        if (choice == 'r' || choice == 'R') {
            if (getRandomNumber(1, 2) == 1) {
                std::cout << "You have successfully fled.\n";
                return;
            }
            else {
                std::cout << "You failed to flee.\n";
                attackPlayer(m, player);
            }
        }
        else if (choice == 'f' || choice == 'F')
        {
            attackMonster(m, player);
        }
    }
}
int main()
{
    std::srand(time(NULL));
    std::rand();
    std::string name;
    std::cout << "Enter Your Name: ";
    std::cin >> name;
    Player p{ name };
    while (!p.isDead() && p.getLevel() < 20)
    {
        fightMonster(p);
    }
    if (p.isDead())
        printf("You have died with %d gold and are level %d.", p.getGold(), p.getLevel());
}
 
    