战斗游戏 - C ++,鉴于一个Spawner类,我怎样才能在每一轮产生更强大的敌人

时间:2016-07-04 11:02:18

标签: c++ class

我的OOP作业有问题。我必须编写一场1对1战斗。

这是一个生存游戏,在玩家中,玩家不断与敌人战斗,直到玩家死亡。随着他的进步,球员变得更加强大。每一轮敌人都会变得更强壮。

我创建了两个类,The Unit和Spawner。 我们不能使用继承或多态。 我们必须只使用类的简单定义。

我的问题是,我想不出一种简单的方法让Spawner每一轮产生一个更强大的敌人。

我曾想过让Unit的Contructor超载,但是我无法操纵它。

有人请帮忙吗?

这是我的单元头文件(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
};

这是我的Unit.cpp文件(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;
}

这是我的Spawner Header文件(Spawner.h):

 #pragma once

 #include "Unit.h"

 class Spawner
 {
 public:
      Spawner();
      ~Spawner();
       void spawn(Unit*& unit);

  private:
      Unit* mUnit;
      int mRandomClass;
 };

这是我的Spawner.cpp文件(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;
}

最后这是我的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;
    }
}

2 个答案:

答案 0 :(得分:1)

Unit类添加“级别”,并使用级别来增加单位的统计数据(例如,级别2可能意味着统计数据乘以1.5或某些等级)。将level作为参数传递给类似于单元类的构造函数。

答案 1 :(得分:0)

你需要让你的生成器知道它产生了多少敌人:

// this belongs into your class definition, it should start at zero
int mCurrentSpawn;

因此在构造函数中将其设置为零:

Spawner::Spawner()
{
   mCurrentSpawn = 0;
}

然后在你产生敌人时引用它:

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--;
    }
}