I'm working on a textual game, I wish to assign a weapon to a player or monster.
I have created a 2d array with min & max damage so I can randomize every hits between min/max.
But I'm stuck for now.
Should I integrate the 2d array in the weapon class ?
How to affect the weapon to each player ?
thanks for any help :)
#include <iostream>
class player{
public:
std::string playerName;
int health;
int maxmana;
int minDegatWeapon;
int maxDegatWeapon;
};
class weapon{
public:
std::string weaponName;
int maxDegatWeapon;
int minDegatWeapon;
};
void createPlayer(player *p, weapon *w){
int weaponSelection = 0;
std::cout << "Player Name ?\n";
std::getline (std::cin,p->playerName);
p->health = 20;
p->maxmana = 80;
std::cout << "Choose your Weapon : 1-Dagger / 2-Sword / 3-Axe ? \n";
std::cin >> weaponSelection;
};
int main(){
player human = {" ", 0, 0, 0, 0};
weapon humanWeapon = {" ", 0, 0};
int weapons[3][2] = {
{3,4}, //dagger
{1,6}, //sword
{0,7} //axe
};
createPlayer(&human, &humanWeapon);
return 0;
}
You can always have class Weapon be an abstract class. There is no "generic weapon" so it would not be appropriate to instantiate an object of type weapon. Instead, have multiple classes inherit from the weapon class, and adjust their min/max value as needed. Further more, you can assign this weapon to the player by adding a weapon to the Player class.
#include <random>
#include <time.h>
class Weapon
{
public:
virtual std::string getWeaponType() = 0;
virtual int generateDamage() = 0;
int minDmg, maxDmg;
};
class Sword : public Weapon
{
public:
Sword()
{
minDmg = 1;
maxDmg = 6;
}
std::string getWeaponType()
{
return "SWORD";
}
int generateDamage()
{
return ( rand() % maxDmg + minDmg );
}
};
class Player
{
public:
Player(int weapon)
{
if(weapon == 1)
{
w = new Sword();
}
//else if(weapon == 2).....
//..................
}
Weapon* getWeapon()
{
return w;
}
private:
Weapon* w;
};
int main()
{
srand(time(NULL)); //random seed
Player p1 = Player(1);
std::cout << p1.getWeapon().generateDamage() << '\n'; //see if it works
}
Related
The title is perhaps confusing but I really did not knew how to put it in a better way.
I have a class Monsters which inherits the base values from class Creature, but I want to be able to generate different of monsters based on the values that I have in the enum Monsters. The code that I provided does not work, but this is my attempt and I think I am pretty close but cannot finish it.
Suppose that Spider can have energy from 1-3 and Dragon can have energy from 10-20. How can I make so that for differnt type of monster it will generate different amount of energy?
#include <iostream>
#include <random>
#include <chrono>
using namespace std;
enum Monsters
{
Spider,
Griffon,
Dragon
};
class Creature
{
public:
Creature() {}
Creature(int lifes, int damage)
{
this->lifes = lifes;
this->damage = damage;
}
virtual ~Creature() {}
protected:
int lifes;
int damage;
};
template <class T>
class Monster() : public Creature()
{
public:
Monster() : Creature() {}
Monster(int lifes, int damage, int energy) : Creature(lifes, damage)
{
maxPower = rand() % 10;
minPower = rand() % maxPower;
energy = rand() % maxPower + minPower;
}
virtual void stats()
{
cout << "Lifes left: " << this->lifes << endl;
cout << "Damage: " << this->damage << endl;
cout << "Energy: " << this->energy << endl;
}
protected:
int energy;
private:
int minPower;
int maxPower;
};
int main()
{
Monster<Dragon> *dragonOne = new Dragon(5, 10, 10);
dragonOne->stats();
return 0;
}
Pleas ask for more info, or edit this post accordingly if needed.
When trying to 'equip' the weapon and Armour objects they result in a read access violation and the output damage and input is all blanks. (Anything in parenthesis is an alternative output) The output should be
Attacker : Gary using Wooden Sword does 1 (or 2) damage.
Defender : Mary(4 HP) is equipped with Iron Armour and receives 0 (or 1) damage
but output is
Attacker : Gary using Weapon does damage.
Defender : Mary( HP) is equipped with Armour and recieves
This is the code:
class Weapon {
public:
std::string weapon_Name = "Weapon";
int MIN_DAMAGE = 0;
int MAX_DAMAGE = 1;
};
class Wooden : public Weapon {
public:
std::string weapon_Name = "Wooden Sword" ;
int MIN_DAMAGE = 1;
int MAX_DAMAGE = 2;
};
class Iron : public Weapon {
public:
std::string weapon_Name = "Iron Sword";
int MIN_DAMAGE = 2;
int MAX_DAMAGE = 4;
};
class Armour {
public:
std::string armour_Name = "Armour";
int DAM_REDUCTION = 0;
int DAM_ABSORBTION = 0;
};
class Leather : public Armour {
public:
std::string armour_Name = "Leather Armour";
int DAM_REDUCTION = 0;
int DAM_ABSORBTION = 1;
};
class Chainmail : public Armour {
public:
std::string armour_Name = "Iron Armour";
int DAM_REDUCTION = 1;
int DAM_ABSORBTION = 2;
};
class Player {
private:
int hp;
std::string name;
Weapon *WEAPON_EQUIPPED;
Armour *ARMOUR_EQUIPPED;
public:
Player(std::string pName, int startHP) {
this->hp = startHP;
this->name = pName;
}
void equipWeapon( Weapon &Weapon){ this->WEAPON_EQUIPPED = &Weapon; }
void equipArmour( Armour &Armour){ this->ARMOUR_EQUIPPED = &Armour; }
void getWeaponName() { std::cout << WEAPON_EQUIPPED->weapon_Name; }
void getArmourName() { std::cout << ARMOUR_EQUIPPED->armour_Name; }
void getPlayerName() { std::cout << name; }
int getPlayerHP() { return hp; }
int getOutDamage() {
srand((int)time(0));
int outDamage = ((rand() % this->WEAPON_EQUIPPED->MAX_DAMAGE) + this->WEAPON_EQUIPPED->MIN_DAMAGE);
return outDamage;
}
int getInDamage() {
int inDamage = getOutDamage();
srand((int)time(0));
int totalDamage = inDamage - (((rand() % this->ARMOUR_EQUIPPED->DAM_ABSORBTION) + this->ARMOUR_EQUIPPED->DAM_REDUCTION) % this->ARMOUR_EQUIPPED->DAM_ABSORBTION);
return totalDamage;
}
int recieveDamage(int inDam) {
//this->hp - inDam;
int dam = this->hp - inDam;
return dam;
}
};
void Attack(Player& attacker, Player& defender) {
std::cout << "Attacker : ";
attacker.getPlayerName();
std::cout << " using ";
attacker.getWeaponName();
std::cout << " does ";
attacker.getOutDamage();
std::cout << " damage." << std::endl;
std::cout << "Defender : ";
defender.getPlayerName();
std::cout << "(";
defender.getPlayerHP();
std::cout << " HP) is equipped with ";
defender.getArmourName();
std::cout << " and recieves ";
defender.recieveDamage(defender.getInDamage());
std::cout << " damage(";
defender.getPlayerHP();
std::cout << ")" << std::endl;
}
int main() {
Player Gary("Gary", 4);
Player Mary("Mary", 4);
Wooden wood;
Chainmail chain;
Wooden* ptrWeap = &wood;
Chainmail* ptrChain = &chain;
Gary.equipWeapon(wood);
Mary.equipArmour(chain);
Attack(Gary, Mary);
return 0;
}
Sorry for long code I do need help in understanding how to fix this, any help would be much appreciated
If you look at call stack while the exception if being thrown you will see, that in main you call Attack(Gary, Mary);, where Gary is an attacker and Mary is a defender. It then calls defender.recieveDamage(defender.getInDamage());. Then getInDamage(), calls getOutDamage() again on object Player and the instance of that object is Mary, for whom you never actually set WEAPON_EQUIPPED. And since it is uninitialized, it is by default a nullptr (at least on Debug) and here is where your access violation reading comes from.
I am looking to make this more efficient, how would I Re-write the Enemy class to use inheritance and virtual functions? Including any new child classes.
class Enemy
{
public:
int type; // 0 = Dragon, 1 = Robot
int health; // 0 = dead, 100 = full
string name;
Enemy();
Enemy(int t, int h, string n);
int getDamage(); // How much damage this enemy does
};
Enemy::Enemy() : type(0), health(100), name("")
{ }
Enemy::Enemy(int t, int h, string n) :
type(t), health(h), name(n)
{ }
int Enemy::getDamage() {
int damage = 0;
if (type == 0) {
damage = 10; // Dragon does 10
// 10% change of extra damage
if (rand() % 10 == 0)
damage += 10;
}
else if (type == 1) {
// Sometimes robot glitches and does no damage
if (rand() % 5 == 0)
damage = 0;
else
damage = 3; // Robot does 3
}
return damage;
}
This calculates how much total damage the band will dish out.
int calculateDamage(vector<Enemy*> bandOfEnemies)
{
int damage = 0;
for (int i = 0; i < bandOfEnemies.size(); i++)
{
damage += bandOfEnemies[i]->getDamage();
}
return damage;
}
That's a good start, but with inheritance, you don't need to be so specific. For example, in the enemy class you have an attribute type. If you want to use inheritance, you don't need to specify the type, because the derived class would be the type.
As for your function getDamage(), you can leave it blank and turn it into a virtual function. Putting all of this together, your code should look something like this:
class Enemy
{
public:
int health; // 0 = dead, 100 = full
string name;
Enemy();
Enemy(int t, int h, std::string n);
virtual int getDamage() = 0; // pure virtual function
};
Enemy::Enemy()
: type(0), health(100), name("") {}
Enemy::Enemy(int t, int h, std::string n)
: type(t), health(h), name(n) {}
// class 'Dragon' inherits from class 'Enemy'
class Dragon : public Enemy
{
public:
Dragon() {}
int getDamage()
{
// dragon's damage
}
};
Notice how if you want to create another enemy, you just inherit from the Enemy class. And this way, you can store your characters in an array like this:
vector<Enemy> enemies = {
Dragon(),
Dragon(),
Robot()
};
Errors
Hero: undeclared identifier
std::shared_ptr: Hero is not a valid template type argument for parameter _Ty
unary ->: std::shared_ptr does not define this operator or a conversion to a type acceptable to the predefined operator
attackInput, getSkill os not a member of std::shared_ptr
void my::Weapon::hit(std::shared_ptr,std::shared_ptr): cannot convert argument 1 from std::shard_ptr<my::Hero> to std::shared_ptr
Source.cpp
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <windows.h>
#include "Hero.h"
void checkLife(my::Hero* hero)
{
if (hero->is_dead())
{
delete hero;
hero = nullptr;
}
if (hero == nullptr)
{
srand(time(0));
int rand = 1 + std::rand() % 40;
if (rand > 0 && rand <= 10) hero = new my::King();
else if (rand > 10 && rand <= 20) hero = new my::Queen();
else if (rand > 20 && rand <= 30) hero = new my::Troll();
else if (rand > 30 && rand <= 40) hero = new my::Knight();
}
}
int main()
{
my::Hero* hero = nullptr;
my::Hero* enemy = nullptr;
while (true)
{
checkLife(hero);
checkLife(enemy);
hero->attackOutput(std::shared_ptr<my::Hero>(enemy));
enemy->attackOutput(std::shared_ptr<my::Hero>(hero));
system("cls");
std::cout << hero->getName() << "`s health - " << hero->getHealth() << std::endl;
std::cout << hero->getName() << "`s health - " << hero->getHealth() << std::endl;
Sleep(1000);
}
if (hero != nullptr) delete hero;
if (enemy != nullptr) delete enemy;
system("pause");
return 0;
}
Hero.h
#pragma once
#include <memory>
#include <cstdlib>
#include <time.h>
#include <string>
#include "Weapon.h"
namespace my
{
class Hero abstract
{
protected:
std::shared_ptr<Weapon> weapon;
std::string name;
int health;
int skill;
int pressure;
int nobleness;
int beauty;
virtual void attack(int damage)
{
srand(time(0));
this->health -= damage + rand() % 20 - this->getPressurel();
}
public:
Hero(std::string name, int health, int skill, int pressure, int nobleness, int beauty)
{
this->name = name;
this->health = health;
this->skill = skill;
this->pressure = pressure;
this->nobleness = nobleness;
this->beauty = beauty;
}
std::string getName() const
{
return this->name;
}
int getHealth() const
{
return this->health;
}
int getSkill() const
{
return this->skill;
}
int getPressurel() const
{
return this->pressure;
}
int getNobleness() const
{
return this->nobleness;
}
int getBeauty() const
{
return this->beauty;
}
void attackInput(const int damage)
{
this->attack(damage);
}
void attackOutput(std::shared_ptr<Hero> enemy)
{
std::shared_ptr<Hero> thisHero(this);
this->weapon->hit(std::shared_ptr<Hero>(thisHero), enemy);
}
virtual void takeWeapon(std::shared_ptr<Weapon> weapon)
{
this->weapon = weapon;
}
bool is_dead()
{
if (this->health <= 0) return true;
else return false;
}
};
class King : public Hero
{
public:
King() : Hero("King", 300, 2, 4, 10, 15) {}
};
class Queen : public Hero
{
public:
Queen() : Hero("Queen", 300, 2, 4, 10, 15) {}
};
class Troll : public Hero
{
public:
Troll() : Hero("Troll", 300, 2, 4, 10, 15) {}
};
class Knight : public Hero
{
public:
Knight() : Hero("Knight", 300, 2, 4, 10, 15) {}
};
}
Weapon.h
#pragma once
#include "Hero.h"
namespace my
{
class Weapon abstract
{
protected:
const int damage;
int wear;
public:
Weapon(int damage, int weight, int size, int wear) : damage(damage)
{
this->wear = wear;
}
Weapon() : Weapon(1, 1, 1, 1) {}
virtual void setWeaponWear(int wear)
{
this->wear = wear;
}
virtual int getWeaponDamage() const
{
return this->damage;
}
virtual int getWeaponWear() const
{
return this->wear;
}
virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy) = 0;
};
class Knife : public Weapon // NOZH
{
protected:
public:
virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy)
{
int damage = this->damage * me->getBeauty();
this->wear--;
enemy->attackInput(damage);
}
};
class Bow : public Weapon // LUCK
{
protected:
public:
virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy)
{
int damage = this->damage * me->getNobleness();
this->wear--;
enemy->attackInput(damage);
}
};
class Ax : public Weapon // TOPOR
{
protected:
public:
virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy)
{
int damage = this->damage * me->getPressurel();
this->wear--;
enemy->attackInput(damage);
}
};
class Sword : public Weapon // MECH
{
protected:
public:
virtual void hit(std::shared_ptr<Hero> me, std::shared_ptr<Hero> enemy)
{
int damage = this->damage * me->getSkill();
this->wear--;
enemy->attackInput(damage);
}
};
}
As pointed out in the comments by #WhozCraig you have a circular dependency. You need Weapon.h in Hero.h and Hero.h in Weapon.h.
The only reason you need Hero.h in Weapon.h. Is for the hit(...) function. The best solution would be to declare the hit function somewhere else. Right now the best place would be to add it to the Hero. A hero has a weapon and attacks with that weapon another hero, a weapon itself can't attack, so just from the semantics it makes more sense to have the hit function inside the hero class.
You can probably get it to compile by splitting the code up into a header (.h) and source file (.cpp) and having a forward declaration of Hero in Weaopon.h. But this will not fix the underlying problem and the design is still flawed and will probably cause even more problems if functionality is extended.
I need to creat an object Pokemon in the main()
that assign it into the class PokemonWorld, and let the PokemonWolrd to decide which PokemonStation is this Pokemon need to go
I tired get the data separatly (get name and hp) and get together(get a Pokemon class)
but both fail
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
class Pokemon {
public:
Pokemon() {};
Pokemon(char x[], int n) {
strncpy_s(name, x, 10);
hp = n;
};
private:
char name[10];
int hp;
};
class PokemonStation {
private:
Pokemon **list= new Pokemon*[1000];
public:
PokemonStation() {};
PokemonStation(int x) {
id = x;
};
int id;
void assigntoList(int i,Pokemon x)
{
if (i > 0)
i--;
list[i] = new Pokemon(x);
cout << "creat" << list[i];
};
};
class PokemonWorld {
private:
char name[10];
public:
PokemonStation s1;
PokemonStation s2;
PokemonWorld() {};
PokemonWorld(char x[], int y=1, int z=2) {
strncpy_s(name, x, 10);
PokemonStation s1(y);
PokemonStation s2(z);
};
const char* const getName() const{
return name;
};
void assigntoStation(int i,Pokemon x) {
if (i == 0 || i % 2 == 0)
s1.assigntoList(i, x);
else
s2.assigntoList(i, x);
};
};
void main() {
int number,hp,i;
char name[10];
cout << "What is the World Name ?" <<endl;
cin >> name;
PokemonWorld world(name);
cout << "Please input the number of Pokemon in the " << world.getName() <<" world:" << endl;
cin >> number;
Pokemon **mon = new Pokemon*[number];
cout << "Please input the characteristics of all Pokemon: Name HP" << endl;
for (i = 0;i < number;i++)
{
cin >> name >> hp;
mon[i] = new Pokemon(name, hp);
world.assigntoStation(i,*(mon[i]));
}
for (i = 0;i < number;i++)
cout << "world is " << world.getName() << endl;
system("pause");
};
In C++, you should use std::vectors for dynamic lists of things and std::strings for text. If you know Java, these are like ArrayList and String. (To use these, make sure you #include <vector> and <string>.)
For instance, your Pokemon class, rewritten with name as a string:
class Pokemon {
public:
Pokemon() {}
Pokemon(string name, int hp):name(name), hp(hp) { // construct the fields directly
}
private:
string name;
int hp;
};
And your PokemonStation class, rewritten using a vector for the list of Pokemon:
class PokemonStation {
private:
vector<Pokemon> list;
public:
PokemonStation() {}
PokemonStation(int x):id(x) {}
int id;
void assignToList(Pokemon x)
{
list.push_back(x); // add x to the list
}
};
If you want to print a Pokemon with cout <<, then you'll have to overload the << operator to define what gets printed. Add this into your class:
class Pokemon {
public:
...
friend ostream& operator<<(ostream& out, const Pokemon& p) {
out << p.name; // just print the name
return out;
}
...
};
Just make sure that you're couting a Pokemon, not a pointer-to-Pokemon (Pokemon*), and you won't get an address.