Problem with array of class objects leads to crash - c++

So I am making a textbased RPG and I wanted to have multiple enemy encounter at once. So I modified my function that determines whether an object of the class Monster, to fill in the Monster(s) into an array of the class monster and set the objects bool to true, as you can see here:
Monster * Map::checkRandomEncounter()
{
Monster* monster = new Monster[3];
for (int i = 0; i < 3; i++)
{
int roll = Random(0, 20);
if (roll <= 5)
{
//No encounter
return 0;
}
else if (roll > 6 && roll < 10)
{
monster[i] = Monster();
monster[i].giveID("Orc", 10, 8, 200, 100, 1, "Short Sword", 2, 7);
monster[i].isFilled();
std::cout << "You encounter an Orc!" << std::endl;
std::cout << "Prepare for battle!" << std::endl;
std::cout << std::endl;
}
else if (roll >= 11 && roll <= 15)
{
monster[i] = Monster();
monster[i].giveID("Goblin", 6, 6, 100, 75, 0, "Dagger", 1, 5);
monster[i].isFilled();
std::cout << "You encounter a Goblin!" << std::endl;
std::cout << "Prepare for battle!" << std::endl;
std::cout << std::endl;
}
else if (roll >= 16 && roll <= 19)
{
monster[i] = Monster();
monster[i].giveID("Ogre", 20, 12, 500, 200, 2, "Club", 3, 8);
monster[i].isFilled();
std::cout << "You encounter an Ogre!" << std::endl;
std::cout << "Prepare for battle!" << std::endl;
std::cout << std::endl;
}
else if (roll == 20)
{
monster[i] = Monster();
monster[i].giveID("Orc Lord",
25,
15,
2000,
1000,
5,
"Two Handed Sword",
5,
20);
monster[i].isFilled();
std::cout << "You encounter an Orc Lord!" << std::endl;
std::cout << "Prepare for battle!" << std::endl;
std::cout << std::endl;
}
}
return monster;
}
The function above will be called in my main function, which looks like this:
int main()
{
srand(time(0));
Map gameMap;
Player mainPlayer;
mainPlayer.createClass();
//Beginn adventure
bool done = false;
while (done == false)
{
// Each Loop Cycle outputs player pos and selection menu
gameMap.printPlayerPos();
int selection = 1;
std::cout << "1) Move 2) Rest 3) View Stats 4) Quit: ";
std::cin >> selection;
Monster* monster = 0;
switch (selection)
{
case 1: // Move the player
gameMap.movePlayer();
if (gameMap.getPlayerXPos() == 2
&& gameMap.getPlayerYPos() == 3)
{
std::cout << "You see a store nearby !" << std::endl;
}
if (gameMap.getPlayerXPos() == 2
&& gameMap.getPlayerYPos() == 4)
{
Store store;
store.enter();
store.showInventory(mainPlayer);
}
//Check for a random encounter
//returns a null pointer if no encounter happened
monster = gameMap.checkRandomEncounter();
//'monster' not null, start battle script
if (monster != 0)
{
//Loop until a break statement
for (int i = 0; i < 3; i++)
{
//Display Hitpoints
mainPlayer.displayHitPoints();
monster[i].displayHitPoints();
std::cout << std::endl;
//Players turn to attack first
**bool runAway = mainPlayer.attack(monster, mainPlayer);** // Crash happening in this area
if (runAway) // Player flees
{
break;
}
if (monster[i].isDead())
{
mainPlayer.victory(monster->getXPReward(),
monster->getGoldReward());
mainPlayer.levelUp(mainPlayer);
}
break;
//Monster attacks
monster[i].attack(mainPlayer);
if (mainPlayer.isDead())
{
mainPlayer.gameOver();
done = true;
break;
}
}
//Pointer to Monster must destroy created instance of Monster
//to make sure that there is no Memory leak
}
delete monster;
monster = 0;
break;
case 2: // resting
mainPlayer.rest();
monster = gameMap.checkRandomEncounter();
//'monster' not null, start battle script
monster = gameMap.checkRandomEncounter();
//'monster' not null, start battle script
if (monster != 0)
{
//Loop until a break statement
for (int i = 0; i < 3; i++)
{
//Display Hitpoints
mainPlayer.displayHitPoints();
monster[i].displayHitPoints();
std::cout << std::endl;
//Players turn to attack first
bool runAway = mainPlayer.attack(monster, mainPlayer);
if (runAway) // Player flees
{
break;
}
if (monster[i].isDead())
{
mainPlayer.victory(monster->getXPReward(),
monster->getGoldReward());
mainPlayer.levelUp(mainPlayer);
}
break;
//Monster attacks
monster[i].attack(mainPlayer);
if (mainPlayer.isDead())
{
mainPlayer.gameOver();
done = true;
break;
}
}
//Pointer to Monster must destroy created instance of Monster
//to make sure that there is no Memory leak
}
delete monster;
monster = 0;
break;
case 3: // viewing stats
mainPlayer.viewStats();
break;
case 4: // quitting
done = true;
break;
}
}
return 0;
}
and finally the last puzzle piece, the function where the player attacks the Monster(s):
bool Player::attack(Monster Monster[], Player& Player)
{
int ArmorBefore = 0;
int Roll = 0;
int selection = 1;
int i;
if (Monster[0].isFilled() == true)
{
i = 0;
}
else if (Monster[1].isFilled() == true)
{
i = 1;
}
else if (Monster[2].isFilled() == true)
{
i = 2;
}
if (Monster[i].isFilled() == true)
{
std::cout << "1) Attack 2) Run 3) Cast Spell 4) Use Item: ";
std::cin >> selection;
std::cout << std::endl;
switch (selection)
{
case 1: // Player fights
std::cout << " You attack an " << Monster[i].getName()
<< " with a " << mWeapon.mName << std::endl;
if (Random(0, 20) < mAccuracy) // Player hits Monster
{
int damage = Random(mWeapon.mDamageRange);
int totalDamage = damage - Monster[i].getArmor();
if (totalDamage <= 0) // Armor is equal or higher than player atk
{
std::cout << "Your attack failed to penetrate "
<< Monster[i].getName() << "'s armor !"
<< std::endl;
return false;
}
else // Attack is higher than Monsters armor
{
std::cout << "You hit " << Monster[i].getName()
<< " for " << totalDamage << " damage !"
<< std::endl;
// Subtract dmg from Monsters hp
Monster[i].takeDamage(totalDamage);
return false;
}
}
else // Player Misses
{
std::cout << "You miss !" << std::endl;
}
std::cout << std::endl;
return false;
break;
case 2: // Player runs with a 25% chance
Roll = Random(1, 4);
if (Roll == 1) // Success
{
std::cout << "You run away !" << std::endl;
return true; // <- Return out of the function
}
else
{
std::cout << "You failed to escape !" << std::endl;
return false;
}
case 3: // Casting Spell
{
int SpellSelect;
// Spells for the Fighter
if (Player.mClassName == "Fighter")
{
std::cout << std::endl;
std::cout << "1) Shield 2) Mighty Blow: ";
std::cin >> SpellSelect;
if (SpellSelect == 1)
{
if (Player.mMagicPoints >= 10) // checks for player mana
{
std::cout << "You cast a mighty shield!"
<< std::endl;
ArmorBefore = Player.mArmor;
Player.shield(Player);
Player.mMagicPoints -= 10;
}
else
{
std::cout << "Not enough Mana" << std::endl;
break;
}
}
else
{
if (Player.mMagicPoints >= 5) // casting Mighty Blow
{
int damage = Random(mMightyBlow.mDamageRange);
std::cout
<< "You strike with all your might ! and Deal "
<< damage << " damage !" << std::endl;
Monster[i].takeDamage(damage);
Player.mMagicPoints -= 5;
return false;
}
else
{
std::cout << "Not enough Mana" << std::endl;
return false;
}
}
}
//Spells for the Wizard
else if (Player.mClassName == "Wizard")
{
std::cout << "1) Fireball";
std::cin >> SpellSelect;
if (Player.mMagicPoints >= 45)
{
int damage = Random(mFireball.mDamageRange);
std::cout << "You cast a Fireball and deal " << damage
<< " damage !" << std::endl;
Monster[i].takeDamage(damage);
Player.mMagicPoints -= 45;
return false;
}
else
{
std::cout << "Not enough Mana" << std::endl;
return false;
}
}
// Spells for the Cleric
else if (Player.mClassName == "Cleric")
{
std::cout << "1) Magic Missile";
std::cin >> SpellSelect;
if (Player.mMagicPoints >= 35)
{
int damage = Random(mMagicMissile.mDamageRange);
std::cout << "You cast a Magic Missile and deal "
<< damage << " damage !" << std::endl;
Monster[i].takeDamage(damage);
Player.mMagicPoints -= 35;
}
else
{
std::cout << "Not enough Mana" << std::endl;
return false;
}
}
}
case 4: // using Item
int invSlot;
std::cout << "1) HP Potion: ";
std::cin >> invSlot;
if (invSlot == 1) // Potion slot
{
if (mHPot.mAmount.size() > 0)
{
std::cout << "You used a Potion and healed for 5 HP !"
<< std::endl;
int currentSize = mHPot.mAmount.size();
mHPot.mAmount.resize(currentSize - 1);
Player.mHitPoints += 5;
if (Player.mHitPoints > Player.mMaxHitPoints)
{
Player.mHitPoints = Player.mMaxHitPoints;
}
return false;
}
else
{
std::cout << "You have no Potions!" << std::endl;
return false;
}
}
else // wrong slot
{
std::cout << "No Item found!" << std::endl;
return false;
}
}
// Clearing stat boosts
if (Player.shield(Player) == true)
{
Player.mArmor = ArmorBefore;
}
}
return false;
}
When I run the game, I sometimes have the problem, that after filling in a Monster in a slot of the array, no battle will be triggered. And if a battle will be triggered, I get a crash with an error report every time, which says:
_CrtlValidHeadPointer(block)
I guess that something with my pointer is not functioning well.... but since I am a beginner I am pretty much stuck. I would be very grateful for some enlightenment :)

This place can potentially call undefined behavior and crash:
int i;
if (Monster[0].isFilled() == true)
{
i = 0;
}
else if (Monster[1].isFilled() == true)
{
i = 1;
}
else if (Monster[2].isFilled() == true)
{
i = 2;
}
/*else // one of solutions
break;*/
//"i" can be unset! and can have any value from INT_MIN to INT_MAX!
if (Monster[i].isFilled() == true) //potentially index over array
{
Also there are memory leaks and undefined behavior with memory management:
Monster* monster = new Monster[3];
...
delete monster
must be delete [] monster
but it is recommended to use smart pointers, vector, array, etc, for memory management

Related

How to return a value from a class to main

I am trying to build a simple dungeon crawl and am stuck at the battle. The damage taking is working but I cannot return the new health value so that it decreases past the initialized value. Every time the l;oop repeats it returns to the initial value. The same with treasure. What gives? How can I return a value from a member function to main?
#include <iostream>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
class monster
{
public:
int fight()
{
}
};
class chest
{
int loot()
{
}
};
class movement
{
public:
char wasd()
{
char mv;
char up = 'w';
char left = 'a';
char right = 'd';
char down = 's';
cout << "\nMove using w for (up), a for (left), d for (right), and s for (down).\n\n";
mv = _getch();
if (mv == up)
{
cout << "You have moved up 1 space.\n";
}
else if (mv == left)
{
cout << "You have moved left 1 space.\n";
}
else if (mv == right)
{
cout << "You have moved right 1 space.\n";
}
else if (mv == down)
{
cout << "You have moved down 1 space.\n";
}
else
{
cout << "it didn't work.";
}
return 0;
}
};
class random_enc
{ public:
int treasure;
int health = 12;
public:
int encounter(int)
{
int randnumber = rand() % 5 + 1;
treasure = 0;
if (randnumber == 1)
{
cout << "You have been attacked!!! You lose 1 hitpoint." << endl;
health = --health;
cout << "Hitpoints remaining: " << health << endl;
return health;
}
else if (randnumber == 2)
{
cout << "You found treasure!" << endl;
treasure = ++treasure;
cout << "Treasure collected: " << treasure << endl;;
return random_enc::treasure;
}
else if (randnumber == 3)
{
return health;
}
else if (randnumber == 4)
{
cout << "You step on a trap and take damage!! You lose 1 hit point.\n" << "Good bye." << endl;
health = --health;
cout << "Hitpoints remaining: " << health << endl;
}
return health;
}
};
int main()
{
string name;
cout << "Welcome to the dungeon, enter your name:\n";
cin >> name;
cout << "\nGood luck in the dungeon " << name << "\n";
int health = 12;
while (health != 0)
{
movement mvmt;
random_enc random;
mvmt.wasd();
random.encounter(health);
}
cout << "You have been killed. Goodbye.\n";
return 0;
}
I replaced the argument health on the encounter function in random_enc. I replaced it with a pointer: void encounter (int& health)
This passes the reference rather than the value. Then health is defined in the member function.
#include <iostream>
using namespace std;
void encounter(int& health) // note the ampersand
{
--health; // this will change health in main
}
int main()
{
int health = 12;
encounter(health);
cout << health << '\n'; // prints 11
}

Negative value not being added to Array

Problem
I have 2 arrays, one for positive numbers, one for negative numbers. For some reason, if the first number to be added is a negative number, it creates the array space to add the number yet the number inserted will always be 0.
Code for adding
Here is my add method, it determines if the value is negative or positive and adds the value to the appropriate array:
bool MyClass::addInt(int valueToBeInserted){
if (valueToBeInserted >= 0){
if (posArrayIterator >= sizeOfMyArray){
return false;
} else {
cout << "added " << valueToBeInserted << "\n" << endl;
myPArray[posArrayIterator] = valueToBeInserted;
posArrayIterator ++;
return true;
}
} else {
if (negArrayIterator >= sizeOfMyArray){
return false;
} else {
cout << "added " << valueToBeInserted << "\n" << endl;
myNarray[negArrayIterator] = valueToBeInserted;
negArrayIterator ++;
return true;
}
}
}
Output
With the following test:
b.addInt(-1);
b.addInt(-3);
b.addInt(-9);
The expected output would be
[-1, -3, -9]
but output is
[-3, -9, 0].
Any help is much appreciated.
Since you are not posting the whole class I can only guess where the problem is.
1) Are posArrayIterator and negArrayIterator initialized to 0? They should be!
2) What is a value of sizeOfMyArray?
There is nothing wrong with your bool MyClass::addInt(int valueToBeInserted)
See example below:
class MyClass
{
private:
int sizeOfMyArray;
int posArrayIterator;
int negArrayIterator;
int myNarray[20];
int myPArray[20];
public:
MyClass(){
sizeOfMyArray = 20;
posArrayIterator = 0;
negArrayIterator = 0;
};
bool addInt(int value);
void printNArray()
{
cout << "[ ";
for (int i=0; i<negArrayIterator; i++)
{
cout << myNarray[i];
if ( (i+1) < negArrayIterator )
{
cout << ", ";
}
}
cout << "]";
}
};
bool MyClass::addInt(int valueToBeInserted){
if (valueToBeInserted >= 0){
if (posArrayIterator >= sizeOfMyArray){
return false;
} else {
cout << "added " << valueToBeInserted << "\n" << endl;
myPArray[posArrayIterator] = valueToBeInserted;
posArrayIterator ++;
return true;
}
} else {
if (negArrayIterator >= sizeOfMyArray){
return false;
}
else {
cout << "added " << valueToBeInserted << "\n" << endl;
myNarray[negArrayIterator] = valueToBeInserted;
negArrayIterator ++;
return true;
}
}
}
int main()
{
MyClass b;
b.addInt(-1);
b.addInt(-3);
b.addInt(-9);
b.printNArray();
return 0;
}
Output:
added -1
added -3
added -9
[ -1, -3, -9]

Combat Game - C++, Given a Spawner Class, How can I spawn stronger enemy every round

I have a problem in my OOP homework. I have to code a 1 v 1 battle.
This is a Survival Game where in the player fights continuously with enemies until the player dies. The Player gets stronger as he advances through. The enemy also grows stronger every round.
I have created two Classes, The Unit and the Spawner.
We cannot use Inheritance nor Polymorphism.
We Have to use only the simple definition of the class.
My problem is that i cannot think of a SIMPLE way to make the class Spawner spawn a stronger enemy every round.
I have thought of overloading the Unit's Contructor but i have trouble manipulating that.
Would anyone please help?
Here's my Unit Header file (Unit.h):
#pragma once
#include <string>
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
// Class Types
const string CLASS_WARRIOR = "Warrior" ;
const string CLASS_ASSASSIN = "Assassin";
const string CLASS_MAGE = "Mage" ;
// Class Choices
const int CHOICE_WARRIOR = 1;
const int CHOICE_ASSASSIN = 2;
const int CHOICE_MAGE = 3;
// Multipliers
const double MULTIPLIER_DAMAGE = 0.50f;
const double MULTIPLER_HEAL = 0.30f;
// Advantage
const bool ADVANTAGE = true;
// Win Bonus
const int BONUS_THREE = 3;
const int BONUS_FIVE = 5;
// Minimum and maximum values
const int HIT_RATE_MAX = 80;
const int HIT_RATE_MIN = 20;
const int DAMAGE_MIN = 1;
// Hit or miss
const bool ATTACK_HIT = true;
const bool ATTACK_MISS = false;
class Unit
{
public:
// Constructors
Unit(string name, int classChoice);
// Getters and setters
string getName();
string getClass();
int getHp();
int getMaxHp();
int getPower();
int getVitality();
int getAgility();
int getDexterity();
int getDamage();
int getHeal();
int getBonusDamage();
bool getFirstToAttack();
bool getHit();
void setClassStats(const int classChoice);
// Primary Actions
void attack(Unit* target);
// Secondary Actions
void check(const Unit* target); // Inspects the enemy
void lvlUp(); // Grants this Unit Bonus Stats on Victory
private:
// Info
string mName;
string mClass;
// Basic Stats
int mHp;
int mMaxHp;
int mPower;
int mVitality;
int mAgility;
int mDexterity;
// Derived Stats
int mDamage;
int mHitrate;
int mHeal;
int mBonusDamage;
// Miscellaneous
bool mAdvantage; // If the player has the advantage
string mTargetClass;// This Unit keeps in mind the class of this Unit's Opponent for reference
int mChanceOfHit; // The random chance if the attack will Hit/Miss
bool mFirstToAttack;//if this unit will attack first
bool mHit; // if the attack is a hit or miss
};
Here's my Unit.cpp file (Unit.cpp):
#include "Unit.h"
Unit::Unit(string name, int classChoice)
{
mName = name;
setClassStats(classChoice);
}
string Unit::getName()
{
return mName;
}
string Unit::getClass()
{
return mClass;
}
int Unit::getHp()
{
return mHp;
}
int Unit::getMaxHp()
{
return mMaxHp;
}
int Unit::getPower()
{
return mPower;
}
int Unit::getVitality()
{
return mVitality;
}
int Unit::getAgility()
{
return mAgility;
}
int Unit::getDexterity()
{
return mDexterity;
}
int Unit::getDamage()
{
return mDamage;
}
int Unit::getHeal()
{
return mHeal;
}
int Unit::getBonusDamage()
{
return mBonusDamage;
}
bool Unit::getFirstToAttack()
{
return mFirstToAttack;
}
bool Unit::getHit()
{
return mHit;
}
void Unit::setClassStats(const int classChoice)
{
if (classChoice == CHOICE_WARRIOR) {
mClass = CLASS_WARRIOR;
mMaxHp = 20;
mHp = mMaxHp;
mPower = 15;
mVitality = 10;
mAgility = 7;
mDexterity = 7;
return;
}
else if (classChoice == CHOICE_ASSASSIN) {
mClass = CLASS_ASSASSIN;
mMaxHp = 15;
mHp = mMaxHp;
mPower = 17;
mVitality = 8;
mAgility = 12;
mDexterity = 10;
return;
}
else if (classChoice == CHOICE_MAGE) {
mClass = CLASS_MAGE;
mMaxHp = 30;
mHp = mMaxHp;
mPower = 12;
mVitality = 12;
mAgility = 9;
mDexterity = 8;
return;
}
throw exception("Error! Class not part of this game. ");
}
void Unit::attack(Unit * target)
{
// Determine Whether the attack will Hit/Miss Based on the hit rate
mChanceOfHit = rrand() % 100 + 1;
if (mChanceOfHit > mHitrate) {
mHit = ATTACK_MISS;
return;
}
// Deducts the targets Hp by the Damage given by this Unit (if the attack didn't miss)
target->mHp -= mDamage;
mHit = ATTACK_HIT;
// if target HP is negative, set it to zero
if (target->mHp < 0) target->mHp = 0;
}
void Unit::check(const Unit * target)
{
// The Unit Keeps in Mind his target's Class
if (target->mClass == CLASS_WARRIOR) mTargetClass = CLASS_WARRIOR;
else if (target->mClass == CLASS_ASSASSIN) mTargetClass = CLASS_ASSASSIN;
else if (target->mClass == CLASS_MAGE) mTargetClass = CLASS_MAGE;
// Checks if the Unit is Advantageous Against his Target
if (mClass == CLASS_WARRIOR) {
if (target->mClass == CLASS_ASSASSIN) mAdvantage = ADVANTAGE;
else mAdvantage = false;
}
else if (mClass == CLASS_ASSASSIN) {
if (target->mClass == CLASS_MAGE) mAdvantage = ADVANTAGE;
else mAdvantage = false;
}
else if (mClass == CLASS_MAGE) {
if (target->mClass == CLASS_WARRIOR) mAdvantage = ADVANTAGE;
else mAdvantage = false;
}
// Determine if this Unit Will Attack first
if (mAgility >= target->mAgility) mFirstToAttack = true;
else mFirstToAttack = false;
// Determines Damage, Bonus Damage ( If Applicable ), and Hit Rate Based on targets stats
mDamage = mPower - target->mVitality;
if (mDamage < DAMAGE_MIN) mDamage = DAMAGE_MIN;
mBonusDamage = mDamage * MULTIPLIER_DAMAGE;
// Evaluates Damage Based on advantage
if (mAdvantage) mDamage += mBonusDamage;
mHitrate = ((float)mDexterity / (float)target->mAgility) * 100;
// Clamps the Hit Rate within the Hit Rate Range
if (mHitrate > HIT_RATE_MAX) mHitrate = HIT_RATE_MAX;
else if (mHitrate < HIT_RATE_MIN) mHitrate = HIT_RATE_MIN;
}
void Unit::lvlUp()
{
// Determine Win Bonus Based on the target that he kept in mind
if (mTargetClass == CLASS_WARRIOR) {
mMaxHp += BONUS_THREE;
mVitality += BONUS_THREE;
}
else if (mTargetClass == CLASS_ASSASSIN) {
mAgility += BONUS_THREE;
mDexterity += BONUS_THREE;
}
else if (mTargetClass == CLASS_MAGE) {
mPower += BONUS_FIVE;
}
// Heals the player 30% of his Maximum HP
mHeal = mMaxHp * MULTIPLER_HEAL;
mHp += mHeal;
}
Here's my Spawner Header file (Spawner.h):
#pragma once
#include "Unit.h"
class Spawner
{
public:
Spawner();
~Spawner();
void spawn(Unit*& unit);
private:
Unit* mUnit;
int mRandomClass;
};
Here's my Spawner.cpp file (Spawner.cpp):
#include "Spawner.h"
Spawner::Spawner()
{
}
Spawner::~Spawner()
{
delete mUnit;
mUnit = NULL;
}
void Spawner::spawn(Unit *& unit)
{
mRandomClass = rand() % 3 + 1;
unit = new Unit("Enemy", mRandomClass);
mUnit = unit;
}
And finally here is my main.cpp:
#include "Unit.h"
#include "Spawner.h"
// Create player
Unit* createPlayer();
// Display Stats
void displayStats(Unit* unit);
// Play 1 round
void playRound(Unit*player, Unit* enemy);
// Simulate 1 attack (implement Higher agility gets to atttack first)
void combat(Unit* player, Unit* enemy);
void main()
{
srand(time(NULL));
Unit* player = createPlayer();
Unit* enemy = NULL;
Spawner *spawner = new Spawner();
int round = 1;
while (true) {
cout << "Round " << round << endl;
spawner->spawn(enemy);
player->check(enemy);
enemy->check(player);
playRound(player, enemy);
// if player is dead, end the game
if (player->getHp() == 0) break;
// else, add stats
player->lvlUp();
delete enemy;
enemy = NULL;
cout << "You defeted an enemy" << endl;
system("pause>nul");
system("cls");
round++;
}
cout << "You were defeted! " << endl;
cout << "You survived until Round " << round << endl;
displayStats(player);
delete player;
player = NULL;
delete spawner;
spawner = NULL;
system("pause>nul");
system("cls");
}
Unit* createPlayer()
{
Unit* unit = NULL;
string name;
int classChoice;
cout << "Enter your Name: ";
getline(cin, name);
system("cls");
cout << "Pick a class: " << endl
<< "\t [ 1 ] Warrior" << endl
<< "\t [ 2 ] Assassin" << endl
<< "\t [ 3 ] Mage" << endl
<< endl;
cin >> classChoice;
while (classChoice > 3 || classChoice <= 0) {
cout << "INVALID INPUT! Please try again" << endl;
cout << "Pick a class: " << endl
<< "\t [ 1 ] Warrior" << endl
<< "\t [ 2 ] Assassin" << endl
<< "\t [ 3 ] Mage" << endl
<< endl;
cin >> classChoice;
}
unit = new Unit(name, classChoice);
return unit;
}
void displayStats(Unit* unit)
{
cout << "=========================================================================================" << endl
<< "Name: " << unit->getName() << " \t \t \t HP: " << unit->getHp() << " / " << unit->getMaxHp() << endl
<< "Class: " << unit->getClass() << endl
<< "==========================================================================================" << endl
<< "POW: " << unit->getPower() << endl
<< "VIT: " << unit->getVitality() << endl
<< "AGI: " << unit->getAgility() << endl
<< "DEX: " << unit->getDexterity() << endl
<< endl;
}
void playRound(Unit*player, Unit* enemy)
{
while (player->getHp() > 0 && enemy->getHp() > 0) {
displayStats(player);
displayStats(enemy);
system("pause>nul");
combat(player, enemy);
system("cls");
}
}
void combat(Unit* player, Unit* enemy)
{
if (player->getFirstToAttack()) {
player->attack(enemy);
if (player->getHit() == ATTACK_MISS) cout << player->getName() << "'s Attack Missed! " << endl;
else if (player->getHit() == ATTACK_HIT) cout << player->getName() << " dealt " << player->getDamage() << " Damage" << endl;
system("pause>nul");
if (enemy->getHp() == 0) return;
enemy->attack(player);
if (enemy->getHit() == ATTACK_MISS) cout << enemy->getName() << "'s Attack Missed! " << endl;
else if (enemy->getHit() == ATTACK_HIT) cout << enemy->getName() << " dealt " << enemy->getDamage() << " Damage" << endl;
system("pause>nul");
return;
}
else if (enemy->getFirstToAttack()) {
enemy->attack(player);
if (enemy->getHit() == ATTACK_MISS) cout << enemy->getName() << "'s Attack Missed! " << endl;
else if (enemy->getHit() == ATTACK_HIT) cout << enemy->getName() << " dealt " << enemy->getDamage() << " Damage" << endl;
system("pause>nul");
if (player->getHp() == 0) return;
player->attack(enemy);
if (player->getHit() == ATTACK_MISS) cout << player->getName() << "'s Attack Missed! " << endl;
else if (player->getHit() == ATTACK_HIT) cout << player->getName() << " dealt " << player->getDamage() << " Damage" << endl;
system("pause>nul");
return;
}
}
Add a "level" to the Unit class, and use the level to increase the stats of the unit (for example level 2 could mean the stats are multiplied by 1.5 or some such). Pass the level as an argument to the constructor similar to the units class.
You need to make your spawner aware of how many enemies it has spawned:
// this belongs into your class definition, it should start at zero
int mCurrentSpawn;
So set it to zero in your constructor:
Spawner::Spawner()
{
mCurrentSpawn = 0;
}
Then reference it when you spawn an enemy:
void Spawner::spawn(Unit *& unit)
{
mRandomClass = rand() % 3 + 1;
unit = new Unit("Enemy", mRandomClass);
mUnit = unit;
mCurrentSpawn++;
int levelUps = mCurrentSpawn - 1;
while(levelUps > 0)
{
mUnit->lvlUp();
levelUps--;
}
}

Infinite Loop while inputting the different data type values in STACK

Below is the code for STACK with no overflow since I am using vector concept. Program seems to be working fine as long as I push integers, but as soon as I push float value (for testing) the output screen goes to infinite loop and debugger doesn't even stop at cin statement and it simply crosses it without giving the control to the console window.
#include"iostream"
class Mystack
{
private:
int *input;
int top;
int capacity;
public:
Mystack();
~Mystack();
void push(int x);
int pop();
int topElement() const;
bool isEmpty() const;
void print();
};
Mystack::Mystack()
{
top = -1;
capacity = 5;
input = new int[capacity];
}
Mystack::~Mystack()
{
delete[]input;
}
void Mystack::push(int x)
{
if (top + 1 == capacity)
{
int *vec = new int[capacity+capacity];
for (int i = 0; i <=top; i++)
{
vec[i] = input[i];
}
input = vec;
capacity = capacity * 2;
top++;
input[top] = x;
}
else
{
top++;
input[top] = x;
}
}
int Mystack::pop()
{
if (isEmpty())
{
throw std::out_of_range("Stack Underflow");
}
else
{
std::cout << "The popped element is" << input[top];
return input[top--];
}
}
bool Mystack::isEmpty() const
{
if (top == -1)
{
std::cout << "Is Empty" << std::endl;
return true;
}
else
{
std::cout << "Not Empty" << std::endl;
return false;
}
}
int Mystack::topElement() const
{
if (top == -1)
{
throw std::out_of_range("No Element to Display");
}
else
{
std::cout << "The top element is : " << input[top];
return input[top];
}
}
void Mystack::print()
{
for (int i = 0; i <= top; i++)
{
std::cout << input[i] << " ";
}
}
int main()
{
Mystack s1;
int num, ch = 1;
while (ch >0)
{
std::cout << "\n1. PUSH" << std::endl;
std::cout << "2. TOP" << std::endl;
std::cout << "3. IsEmpty" << std::endl;
std::cout << "4. POP" << std::endl;
std::cout << "5. EXIT" << std::endl;
std::cout << "6. Print" << std::endl;
std::cout << "Enter the choice" << std::endl;
std::cin >> ch; // DEBUGGER DOES NOT GIVE CONTROL TO CONSOLE WINDOW AND ASK FOR INPUT ONCE I PUT FLOAT VALUES, IT SIMPLE CROSSES IT
switch (ch)
{
case 1:
std::cout << "Enter the number to be pushed" << std::endl;
std::cin >> num;
s1.push(num);
break;
case 2:
std::cout << "Get the TOP Element" << std::endl;
try
{
s1.topElement();
}
catch (std::out_of_range &oor)
{
std::cerr << "Out of Range error:" << oor.what() << std::endl;
}
break;
case 3:
std::cout << "Check Empty" << std::endl;
s1.isEmpty();
break;
case 4:
std::cout << "POP the element" << std::endl;
try
{
s1.pop();
}
catch (const std::out_of_range &oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
break;
case 5: exit(0);
case 6:
s1.print();
break;
default:
std::cout << "Enter a valid input";
break;
}
}
std::cin.get();
}
Once you input the int value for example as 1.1 (invalid int value). Input conversion error occurs and the input stream because of invalid data ignores the rest of the operation even the cin. Make your code more generic in order for it to handle float or double or char.

C++ Why is my loop breaking?

I'm following a tutorial for making a MUD (text-based RPG), and I am having issues with my main function. If you'll look at the code, you'll see that when the player moves it will check for a random encounter, and if monster != 0, it will go into the combat loop. When I execute this in the command prompt, it will allow me to attack the monster, but it never makes it to the monster->attack(mainPlayer) function. It just goes back to the screen that states whether I want to move, rest, view stats, or quit. Any help with this would be greatly appreciated!
#include "stdafx.h"
#include "Map.h"
#include "Player.h"
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
srand( time(0) );
Map gameMap;
Player mainPlayer;
mainPlayer.createClass();
// Begin adventure
bool done = false;
while( !done )
{
// Each loop cycle we output the player position and
// a selection menu.
gameMap.printPlayerPos();
int selection = 1;
cout << "1) Move 2) Rest 3) View Stats 4) Quit: ";
cin >> selection;
Monster* monster = 0;
switch( selection )
{
case 1:
// Move the player
gameMap.movePlayer();
// Check for a random encounter. This function
// returns a null pointer if no monsters are
// encountered.
monster = gameMap.checkRandomEncounter();
// 'monster' not null, run combat simulation.
if( monster != 0)
{
// Loop until 'break' statement.
while( true )
{
// Display hitpoints
mainPlayer.displayHitPoints();
monster->displayHitPoints();
cout << endl;
// Player's turn to attack first.
bool runAway = mainPlayer.attack(*monster);
if( runAway )
{
break;
}
if( monster->isDead() )
{
mainPlayer.victory(monster->getXPReward());
mainPlayer.levelUp();
break;
}
monster->attack(mainPlayer);
if( mainPlayer.isDead() )
{
mainPlayer.gameover();
done = true;
break;
}
}
// The pointer to a monster returned from
// checkRandomEncounter was allocated with
// 'new', so we must delete it to avoid
// memeory leaks.
delete monster;
monster = 0;
}
break;
case 2:
mainPlayer.rest();
break;
case 3:
mainPlayer.viewStats();
break;
case 4:
done = true;
break;
} // End switch statement
} // End While statement
} // End main function
Here is the Player::attack function:
bool Player::attack(Monster& monster)
{
int selection = 1;
std::cout << "1) Attack 2) Run: ";
std::cin >> selection;
std::cout << std::endl;
switch( selection )
{
case 1:
std::cout << "You attack the " << monster.getName()
<< " with a " << mWeapon.mName << std::endl;
if( Random(0, 20) < mAccuracy )
{
int damage = Random(mWeapon.mDamageRange);
int totalDamage = damage - monster.getArmor();
if( totalDamage <= 0)
{
std::cout << "Your attack failed to penetrate the "
<< monster.getName() << "'s armor." << std::endl;
}
else
{
std::cout << "You attack for " << totalDamage
<< " damage!" << std::endl;
// Subtract from monster's hitpoints.
monster.takeDamage(totalDamage);
}
}
else
{
std::cout << "You miss!" << std::endl;
}
std::cout << std::endl;
break;
case 2:
// 25% chance of being able to run.
int roll = Random(1, 4);
if( roll == 1 )
{
std::cout << "You run away!" << std::endl;
return true; //<-- Return out of the function.
}
else
{
std::cout << "You could not escape!" << std::endl;
break;
}
}
}
And here is the Monster::attack function:
void Monster::attack(Player& player)
{
cout << "A " <<mName << " attacks you "
<< "with a " << mWeapon.mName << std::endl;
if( Random(0,20) < mAccuracy )
{
int damage = Random(mWeapon.mDamageRange);
int totalDamage = damage - player.getArmor();
if( totalDamage <= 0 )
{
cout << "The " << mName << "'s attack failed to "
<< "penetrate your armor." << endl;
}
else
{
cout << "You are hit for " << totalDamage
<< " damage!" << endl;
player.takeDamage(totalDamage);
}
}
else
{
cout << "The " << mName << " missed!" << endl;
}
cout << endl;
}
Your Player::attack() method has only one return-statement: return true;. You forgot to add the final line return false; to your method.
This could have easily been prevented if you enable warnings (and pay attention to them!)
Your Player::attack doesn't return in all cases (specifically when it needs to return false). When the calling function tries to access the return value of Player::Attack it will get junk and so you enter the if(ranAway) block and break out of your while loop