This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
So basically, I have to write a program that is kind of like an RPG game where there are different types of creatures. Each creature is an object of the class Creature, and has member variables for hitpoints, strength, etc.
What I am having trouble with is writing the function that handles dealing and taking damage between the classes.
#include <iostream>
#include <string>
#include <stdlib.h>
using std::cout;
using std::cin;
using std::endl;
using std::string;
//Creature Base Class (Type 0)
class Creature
{
public:
Creature(int, int, int);
int gettype() {return type;}
int getstrength(){return strength;}
int gethitpoints() {return hitpoints;}
void sethitpoints(int);
string getspecies();
void printstats();
void dealdamage(Creature, Creature);
void takedamage(int);
private:
int type;
int strength;
int hitpoints;
};
Creature::Creature(int t, int s, int hp)
{
type = t;
strength = s;
hitpoints = hp;
}
void Creature::printstats()
{
cout << "This creature has: " << endl;
cout << strength << " strength" << endl;
cout << hitpoints << " hitpoints" << endl;
cout << "and is of type " << type << "(" << getspecies() << ")" << endl;
}
void Creature::sethitpoints(int a)
{
hitpoints = a;
}
string Creature::getspecies()
{
switch(type)
{
case 0: return "Creature";
case 1: return "Human";
case 2: return "Elf";
case 3: return "Demon";
case 4: return "Balrog";
case 5: return "Cyberdemon";
}
}
void Creature::dealdamage(Creature dealer, Creature target)
{
srand(5);
int damage;
damage = rand() % strength+1;
cout << dealer.getspecies() << " inflicts " << damage;
cout << " damage to " << target.getspecies() << "!" << endl;
target.takedamage(damage);
}
void Creature::takedamage(int damage)
{
sethitpoints((gethitpoints()-damage));
}
int main()
{
Creature monster1(0, 10, 100);
Creature monster2(1, 7, 90);
monster1.printstats();
monster2.printstats();
monster1.dealdamage(monster1, monster2);
monster2.printstats();
return 0;
}
Right now, the output the program gives me is:
This creature has:
10 strength
100 hitpoints
and is of type 0(Creature)
This creature has:
7 strength
90 hitpoints
and is of type 1(Human)
Creature inflicts 5 damage to human!
This creature has:
7 strength
90 hitpoints
and is of type 1(Human)
So the dealdamage() function seems to be working, but the takedamage() function is not properly changing the hitpoints of the creature that is taking the damage.
Any help would be appreciated.
The problem is
void Creature::dealdamage(Creature dealer, Creature target)
Firstly, this is called "pass by value". New "Creature" objects are constructed and the values of the "Creature" objects you call the function with are copied into them. The procedure executes, and these temporary Creature objects EOL - the original Creature objects are never touched.
You need to take a pointer or a reference to the original object. But unless you are intending to support some kind of 3-way fight, you shouldn't be requiring both items anyway -- this is a non-static member function, so it's already operating in the context of one of the creatures, hence the syntax with which you invoked it:
monster1.dealdamage(monster1, monster2);
Change your dealdamage like this:
void Creature::dealdamage(Creature& target) // takes a reference
{
//srand(5); <- this will cause rand() to always return the same value. dont do it.
//int damage; <- don't separate declaration and assignment when you can avoid it.
int damage = rand() % strength+1;
cout << getspecies() << " inflicts " << damage
<< " damage to " << target.getspecies() << "!" << endl;
target.takedamage(damage);
}
You can use this->getspecies() if you find just using getspecies() unclear.
Instead of srand(constant value) try something like 'srand(time(NULL))', or better still, do it once at the start of the program.
Related
I am trying to write what I expected to be a very simple program for a text-based game where a player unit and an enemy unit deal damage to each other until one unit hits 0 health. However, somehow both the player and the enemy are resetting to full health between each call of my attack function. This makes no sense to me because the unit health correctly updates in order to print within the attack function. Here is my code. I called the attack function multiple times in my code to demonstrate.
#include <iostream>
using namespace std;
class player; // this is to avoid a syntax error in the enemy attack function
class enemy
{
public:
int health;
int strength;
int defense;
enemy(int h, int s, int d);
void attack(player u);
};
class player
{
public:
int health;
int strength;
int defense;
player(int h, int s, int d);
void attack(enemy u);
};
player::player(int h, int s, int d)
{
health = h;
strength = s;
defense = d;
srand(time(NULL));
cout << "You arrive to the battlefield..." << endl;
}
void player:: attack(enemy u)
{
int damage = 0;
damage = strength - u.defense + (rand() % 3);
u.health -= damage;
cout << "You strike the enemy and deal " << damage << " damage. The enemy now has " << u.health << " health.\n" << endl;
}
enemy::enemy(int h, int s, int d)
{
health = h;
strength = s;
defense = d;
cout << "An enemy has appeared!" << endl;
}
void enemy::attack(player u)
{
int damage = 0;
damage = strength - u.defense + (rand() % 6);
u.health -= damage;
cout << "The enemy strikes you and deals " << damage << " damage. You now have " << u.health << " health.\n" << endl;
}
void battle()
{
player p(50,35,20);// Both healths are set at 50
enemy e(50,34,19);
p.attack(e); // Target health resets after each attack function runs. Unsure why.
//cout << e.health << endl;
e.attack(p);
p.attack(e);
e.attack(p);
p.attack(e);
e.attack(p);
}
int main()
{
battle();
return 0;
}
It's simple enough. Your code is copying your objects and you are altering the hit points of the copied objects, not the original objects in battle. That's why it seems to reset when you go back to battle. You're making the common but incorrect assumption that C++ objects are references, but they are not, they are values and they do get copied.
Change this
void enemy::attack(player u)
to this
void enemy::attack(player& u)
The extra & makes u a reference, and not a copy, so the changes you make will affect the original object, not a copied object. Similar changes needed elsewhere.
Depending on if you only have one copy of the player object vs multiple you can just simply make void enemy::attack() without an argument.
If there's only one player ever, then you can just simply do e.attack() and not pass in the value and reference the player object.
Player could easily be a singleton class (since there's only one copy of it, ever). If there are multiple copies of Player or multiple players then this wouldn't work clearly.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
#include <iostream>
using namespace std;
class Fruit {
protected:
int nr_fruits = 0;
public:
void printTotal() {
cout << "Total fruits in the basket: " << nr_fruits << endl;
}
};
class Mango : public Fruit {
int nr_mangoes;
public:
void getMango(int x) {
nr_mangoes = x;
cout << "There are " << nr_mangoes << " mangoes in the basket" << endl;
nr_fruits = nr_fruits + nr_mangoes;
}
};
class Apple : public Fruit {
int nr_apples;
public:
void getApple(int x) {
nr_apples = x;
cout << "There are " << nr_apples << " apples in the basket" << endl;
nr_fruits = nr_fruits + nr_apples;
}
};
int main(int argc, const char * argv[]) {
Apple a1;
Mango m1;
a1.getApple(10);
a1.printTotal();
m1.getMango(20);
m1.printTotal();
return 0;
}
I need to make a function in the parent class Fruit, to be able to print the number of total fruits, in my case, nr_mangoes + nr_apples.
Obviously, the way i do it, the nr_fruits variable will output only the amount of mangoes or the amount of apples as the total amount of fruit.
How can i get to access the data members of the child classes, or make the variable nr_fruits so that it keeps the value throughout the program.
In this case you need the use of inheritance.
You will use virtual functions.
You will have to store in a vector of pointers to fruit, all the fruits you have.
vector<Fruit*> MyFruits;
Inside class Fruit you will implement a virtual function:
virtual int get_num_of_fruits(){}
And inside the child classes:
int get_num_of_fruits(){
return nr_child; //nr_apples,nr_mangos etc.
}
Then you will have an int nr_fruits = 0 and add to the number of all the fruits(apples,mangos etc.)
So, nr_fruits += MyFruits[i]->get_num_of_fruits(); for i = 0 to i<MyFruits.size()
In the case of your example and for simplicity, you can change your nr_fruits variable to be static, then initialize it after the class declaration:
class Fruit {
public:
static int nr_fruits;
void printTotal() {
cout << "Total fruits in the basket: " << nr_fruits << endl;
}
};
int Fruit::nr_fruits = 0;
However, without knowing the full scope of the requirements for your program, I think you may want to consider to design a better approach to your problem...
I am just started learning OOP concepts and to help myself learning, I have created a Characters class. From this class I have made instance called main and an instance called monster. Here is the code for the class:
#include <iostream>
#include <string>
using namespace std;
class Character {
public:
string name;
float health;
int attackLevel;
int defenseLevel;
void setAttr(string sName,float sHealth, int sAttackLevel, int sDefenseLevel) {
name = sName;
health = sHealth;
attackLevel = sAttackLevel;
defenseLevel = sDefenseLevel;
}
void attack(int whatInstanceToAttack) {
whatInstanceToAttack.hitpoints -= 20; //obviously not valid but how do i do this?
return whatInstanceToAttack;
}
int defend(string defend) {
int damageRelieved = defenseLevel * 2;
return damageRelieved;
}
};
int main() {
Character main;
Character monster;
main.setAttr("Rafael",200,100,30);
monster.setAttr("Monster1",30,40,30);
cout << "Default Values for Raf are;" << endl;
cout << main.name << endl;
cout << main.health<< endl;
cout << main.attackLevel << endl;
cout << main.defenseLevel << endl;
cout << "Default values for monster are" << endl;
cout <<monster.name << endl;
cout <<monster.health << endl;
cout << monster.attackLevel<< endl;
cout << monster.defenseLevel << endl;
return 0;
}
Basically what I want to do is somehow access the monster instance via the main instance. I want to do this by running the attack method. So if I run
main.attack(monster);
then I want the monster to lose 20 hitpoints.
How do I go about doing this?
All you need is to pass reference of Character in attack method.
I think you must be aware of pass by value and pass by reference concept. If not you can read it here
void attack(Character &whatInstanceToAttack) {
whatInstanceToAttack.hitpoints -= 20; //obviously not valid but how do i do this?
}
Yes you can access the variables of an instance from another instance of the same class. You need to use a reference to the object to ensure the changes are reflected in the other instance. So here is what your attack function should look like.
void attack(Character &c)
{
c.hitpoints - = 20;
}
Now when you call main.attack(monster) from the main() function, the hitpoints of monster will get decremented by 20.
As a side note, it is considered a good practice to make the data members of a class private, to avoid illegal access/modification of the data. Always use the member functions as an interface to your class instances.
overload the method attack and you can pass by value or reference as per your requirement.
void attack(Character chr)
or
void attack(Character &chr)
I've been at this for a few hours now. I am making a small game in C++ and I am trying to figure out how I can edit variables from inside of a function. I can place the variables in the main() and edit them them there no problem, but I can't figure out what I need to do to edit from a function. Below is the function.
void HeroSelect(string& hero)
{
int gold = 20, health = 5, attack = 5, stats[2] = { health, attack };
string weapon;
cout << "Please choose your hero.\n";
cin >> hero;
if (hero == "Warrior" || hero == "warrior")
{
weapon = "Broad Sword";
cout << "You are a Warrior wielding a " << weapon << endl;
cout << "Good choice.\n"
<< "You start out with " << gold << " gold." << endl
<< "You have " << stats[0]<< " health and " << stats[1] << " attack.\n";
}
Above is the function definition and I want to be able to edit the health when the player gets attacked or say gets a stronger weapon. Below is the main() of the script.
void main()
{
double enter, room1, room2, room3, room4, BossRoom;
int, gold = 20; //This is used as part of check inventory and will be subtracted when necessary
string hero, weapon;
//Set decimal two places
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
Intro(enter);
cout << "The first step in this adventure is to choose your hero. You can choose a warrior, a wizard, or an archer.\n";
HeroSelect(hero);
So let's say he gets a new weapon and it gives +1 attack how do I reflect that in the function? Would I create a separate function for this?
As the player goes through the game, they can type in "stats" whenever, and when they do I want it to display their current health and attack and then essentially just loop back to the beginning of the room or fight they are in.
I know I can make the changes to the variables if I made all of my loops and all of my if-else statements in main(), but I wanted to try this and keep my main script clean. I did stats as an array, because I think it is good to print the array as a list. Any help would be great. Thanks!
You may need to do a refresher on C++ and OOP. Your concept is not bad, but you can possibly make it better. (Granted if you really want to do something in a particular fashion, and you are able to do it in such fashion, then by all means just do it :P).
As mentioned in your comments, a re-engineering of the game design may be in order. You will want to establish a Hero class, with multiple variables or sub-classes as the attributes (for example: strength, health points, weapons class, armor class, etc. (We could go into a lower-level description, but i don't think it's necessary yet). If you plan to have multiple weapons, a weapons class might be a good idea as well, for example you could define the weapon stats: attack damage, attack rate, weapon durability etc...
In these classes you can create "Helper Functions" which you can then use to change the stats of the associated objects. Helper function could be public functions which would allow you to increment/decrement hero health or perhaps a helper function that will increase attack damage?
It seems like you're doing a good job learning, so hopefully you can visualize the idea here. Either way, keep on grinding and feel free to ask for a more in depth answer whenever necessary! I'd love to see your game when your ready for some testing!
There are several ways to handle this.
The first being to create a class which is covered in the comments and the answer by ejsd1989.
The second option is to make these variables global variables by creating them in the main and just pass them through each function by reference. This keeps your main clean like you desired.
For example:
void HeroSelect(string& hero, int &gold, int &health)
The third option is very similar to the second, and it is to store these variables in an array and just modify the array with each function.
Essentially, it boils down to creating a class or passing the variables to the functions you wish to use.
Main is not a script and there are some conceptual problems with design in question. Word by word answer would be: pass function parameters by reference. But it would not be a good solution for the task.
Please consider this example:
uint menu;
Hero * hero;
Room entrance, next[5];
entrance.Enter();
std::cout << "1st step in this adventure is to choose your hero." <<std::endl;
std::cout << "You can choose " <<std::endl;
std::cout << "(1) a warrior " << std::endl;
std::cout << "(2) , a wizard" << std::endl;
std::cout << "(3) , or an archer." << std::endl;
std::cout << "Please choose your hero." << std::endl;
std::cin >> menu;
switch( menu )
{
case 3 : { hero = new Archer; break; }
case 2 : { hero = new Wizard; break; }
default : { hero = new Warrior; break; }
}
hero->Weapon();
hero->Gold();
hero->Health();
hero->Attack();
std::cout << "Which room to enter? 1..5" << std::endl;
std::cin >> menu;
next[menu - 1].Enter();
if( 5 == menu )
{
std::cout << "You are attacked by a troll!" << std::endl;
hero->SetHealth( hero->GetHealth() >> 1 );
}
hero->Health();
You can handle hero types, room instances this way. Find properties of them that could be generalized and make differences via members or inheritance. Design it more carefully and you could minimize e. g. tons of couts and duplicated code branches.
class Room
{
static uint cntr;
std::string name;
public:
Room() : name ( "Room#" ) { if( cntr < 5 ) { name[ name.size() - 1 ] = cntr + '0'; } else { name = "BossRoom"; } ++cntr; }
void Enter() { std::cout << "You have entered " << name << "!" << std::endl; }
};
uint Room::cntr;
struct Limint
{
uint max;
uint curr;
Limint( uint init ) : max ( init ), curr( init ) {}
};
class Hero
{
protected:
std::string type;
uint gold;
Limint hp;
Limint attack;
std::string weapon;
public:
Hero() : type( "Hero" ), gold( 20 ), hp( 50 ), attack(5), weapon( "Kitchen knife" ) {}
uint GetHealth() { return hp.curr; }
void SetHealth( uint health ) { health = std::min( health, hp.max ); hp.curr = health; }
void Weapon() { std::cout << "You are a " << type << " wielding a " << weapon << ". Good choice!" << std::endl; }
void Gold() { std::cout << "You start out with " << gold << " gold." << std::endl; }
void Health() { std::cout << "You have " << hp.curr << " / " << hp.max << " health." << std::endl; }
void Attack() { std::cout << "You have " << attack.curr << " / " << attack.max << " attack." << std::endl; }
};
class Warrior : public Hero
{
public:
Warrior() { type = "Warrior"; weapon = "Broad sword"; }
};
class Wizard : public Hero
{
public:
Wizard() { type = "Wizard"; weapon = "Magic stick"; }
};
class Archer : public Hero
{
public:
Archer() { type = "Archer"; weapon = "Crossbow"; }
};
Have fun!
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I keep having errors, I'm not sure how to call this Car class into the main function. The instructions I was given are below.
#include <iostream>
#include <string>
class Car{
public:
Car(){
int year = 1990;
std::string make = "Bentley";
int speed = 0;
};
Car(int new_year, std::string new_make, int new_speed) {
year = new_year;
make = new_make;
speed = new_speed;
}
int get_year() { return year; }
std::string get_make() { return make; }
int get_speed() { return speed; }
void accelerate() {
speed+=5;
}
void brake() {
speed-=5;
}
private:
int year;
std::string make;
int speed;
};
int main()
{
int year = 1990;
std::string make = "Bentley";
int speed = 0;
Car YourCar(year, make, speed);
std::cout << "Year: " << YourCar.get_year << std::endl;
std::cout << "Make: " << YourCar.get_make << std::endl;
std::cout << "Speed: " << YourCar.get_speed << std::endl;
}
Instructions:
Please implement a class named Car in C++ that has the following member
variables:
year. An int that holds the car’s model year.
make. A string object that holds the make of car.
speed. An int that holds the car’s current speed.
In addition, the class should have the following member functions:
Constructor. The constructor should accept the car’s year and make
as arguments and assign these values to the object’s year and make
member variables. The constructor should initialize the speed member
variable to 0.
Accessors or Getters. Appropriate accessors or getters should allow
values to be retrieved from an object’s year, make and speed member
variables.
accelerate. The accelerate function should add 5 to the speed member
variable each time it’s called.
brake. The brake function should subtract 5 from the speed member
variable each time it is called.
Demonstrate the class in a program that creates a Car object and then
calls the accelerate function 5 times. After each call to the accelerate function,
get the current speed of the car and display it. Then, call the brake
function 5 times. After each call to the break function, get the current speed
of car and display it.
Change
Car(){
int year = 1990;
std::string make = "Bentley";
int speed = 0;
};
to
Car(){
year = 1990;
make = "Bentley";
speed = 0;
}
You don't need to specify the data type here.
next,
std::cout << "Year: " << YourCar.get_year << std::endl;
std::cout << "Make: " << YourCar.get_make << std::endl;
std::cout << "Speed: " << YourCar.get_speed << std::endl;
Should be
std::cout << "Year: " << YourCar.get_year() << std::endl;
std::cout << "Make: " << YourCar.get_make() << std::endl;
std::cout << "Speed: " << YourCar.get_speed() << std::endl;
You forgot the () after the functions.