设计和实现回合制战斗系统Combat
1. Soldier战士类
Soldier的属性(protected作用域)
最大生命 maxHP 当前生命 HP 最大体力maxSP 当前体力SP
攻击力 damage 经验 exp 等级 level 姓名 name
药瓶数量 drugNum
Soldier的动作(public作用域)
决策 makeDecision 攻击 attack 休息 rest 吃药 takingDrug
Soldier被创建后,maxHP和HP为100,maxSP和SP为100,damage为20,exp为0, level为1,drugNum为5;
每回合Soldier通过决策(makeDecision)来决定需要发出哪一个动作(攻击attack、休息rest或吃药takingDrug,注意每回合只能做其中一个动作)。请自行设计和调整每种动作发出的必要条件,例如:生命值若低于最大值的30%该回合就吃药,体力低于最大值的50%该回合就休息,生命力和体力都充足该回合就发起攻击,等等;
攻击(attack)敌人一次,体力(SP)减少10,经验(exp)增加5。敌人的生命值(HP)减去攻击方攻击力值(damage)的大小。敌人生命值(HP)减少到0时死去,如果敌人被自己打死,获得敌人身上的所有药瓶;
经验(exp)每增加20,等级(level)就提高1级,maxHP、maxSP、damage分别增加20;Soldier, Wizard, Master升级后,当前HP,SP,MP和NP的值皆按比例(xx:MaxXX)增长,注意:不是升级后上述当前属性值就自动全满。例如:Wizard的 HP/MaxHP 50/100,升级后,HP/MaxHP调整为60/120。升级前HP:MaxHP比例为0.5,升级后MaxHP变成120,若要保持0.5的比例,HP自动调整为60。这种设定类似于魔兽争霸III。
休息(rest)一次,生命值(HP)、体力(SP)增加最大值的50%,但不要超过最大值。(例如,当前生命值是30,最大生命值是100,则吃药后的当前生命值为30+100*50%=80。)
吃药(takingDrug),如果药瓶数量为0,不能吃药。吃药一次,药瓶数量减少1,生命值(HP)增加最大值的80%,但不能超过maxHP。
2. Wizard巫师类,从Soldier类公有继承
Wizard的属性(protected作用域)
新增的属性: 最大魔法值 maxMP 当前魔法值 MP
Wizard的动作(public作用域)
决策 makeDecision 攻击 attack 休息 rest 吃药 takingDrug
魔法攻击wizard_attack
Wizard被创建后,maxMP和MP为100 ,maxHP和HP为100,maxSP和SP为100,maxMP和MP为100,damage为20,exp为0,level为1;
每回合Wizard通过决策(makeDecision)来决定需要发出哪一个动作(攻击attack、魔法攻击wizard_attack、休息rest或吃药takingDrug,注意每回合只能做一个动作);
魔法攻击(wizard_attack):如果魔法值小于25、或体力小于10无法使用该技能。一次魔法攻击能同时攻击几个敌人,但每对付一个敌人,自己的体力(SP)减少10、魔法值减少25、经验(exp)增加5、敌人的生命值(HP)减去自己攻击力值(damage)。敌人生命值(HP)减少到0时死去,同时自己获得敌人身上的所有药瓶;
经验(exp)每增加20,等级(level)提高1级,maxHP、maxSP、maxMP、damage分别增加20;(如果觉得升级太快了,或者升级增加的HP和damage不太协调,可以调整这些参数)
休息(rest)一次,生命值(HP)、体力(SP)恢复效果同Soldier的休息(rest)动作。魔法值增加最大魔法值的30%,但不要超过最大魔法值,例如:_mp=_mp+_maxMp*30%。
吃药(takingDrug)一次,效果等同于Soldier吃药。
攻击(attack),攻击效果同Soldier。
3. Master巫师类,从Wizard类公有继承
Master的属性(protected作用域)
新增的属性: 最大内力 maxNp 当前内力 NP
Master的动作(public作用域)
决策 makeDecision 攻击 attack 休息 rest 吃药 takingDrug
魔法攻击wizard_attack 绝杀攻击master_attack
Master被创建后,maxMP和MP为100 ,maxHP和HP为100,maxSP和SP为100,maxNP和NP为100,damage为30,exp为0,level为1;
每回合Wizard通过决策(makeDecision)来决定需要发出哪一个动作(攻击attack、魔法攻击wizard_attack、绝杀攻击master_attack、休息rest或吃药takingDrug,注意每回合只能做一个动作);
大师攻击(master_attack),如果内力(NP)大于50时,可以使用大师(master_attack)攻击。一次大师攻击能让被攻击的敌人的生命值(HP)减少其最大生命值的(maxHP)50%(可能有点太强了,破坏平衡性!容易导致游戏在短短几个回合就结束,可以考虑适当减小。),例如敌人HP为100,maxHP为160,被大师攻击后,生命值变为HP-maxHP50%=100-16050%=20。一次大师攻击会内力(NP)损耗50、体力(SP)损耗30,经验增加5。
魔法攻击(wizard_attack),攻击效果等同于Wizard的攻击(attack)动作
攻击(attack),攻击效果等同于Soldier的攻击(attack)动作。
使用大师攻击后,经验(exp)每增加20,等级(level)就提高1级,maxHP、maxSP、maxMP、maxNP分别增加20,damage增加20;
休息(rest)一次,内力增加最大内力的30%,但不要超过最大内力值。其余如HP、SP、MP的恢复等同于Wizard的休息(rest)动作。
吃药(takingDrug)一次,效果等同于Soldier的吃药(takingDrug)动作。
4. WarSystem战斗系统类
WarSystem类的属性
军团A Soldier ** _pGroupA; 军团B Soldier ** _pGroupB;
WarSystem类的动作
战斗开始startWar 回合开始startRound
每次战斗,双方派出一个军团,军团由数名战士、巫师和大师组成。战斗按回合制进行,即每回合中,一方军团的每个成员做完各自的一次动作(由makeDecision决定)后,另一方军团每个成员接着完成自己的一次动作。战斗开始,由哪个军团先发起攻击,系统随机决定。回合的生成和结束由WarSystem类控制;
WarSystem类拥有两个数据成员(指向指针变量的指针,即二级指针):
Soldier ** _pGroupA;
Soldier ** _pGroupB;
分别对应战斗的双方军团。(提示,军团可以由Soldier *数组的形式生成,在WarSystem的pGroupA和pGroupB分别指向两个军团,注意OOP的多态实现。)
WarSystem类可以发出战斗开始即startWar()动作。在startWar()中,随机决定由哪一方率先发起攻击(恐怕是每个回合都随机决定谁先出手会比较公平,如果每回合先出手都是固定一方,那么战斗结果完全是确定性的。而且由于两支队伍的成员一样,交换先出手权后的结果也是对称的。),然后调用WarSystem的另一动作:回合开始,即startRound()。
startRound()动作的描述:在startRound()中,按军团顺序调用每个战士的makeDecision()动作(也可以考虑两个军团轮流一次一人行动,比较公平)。
本博客是博主花几个小时弄的,尚未完全满足题目要求,例如未进行随机开启军团战斗(用随机函数判断即可,较简单),本博客意在为广大初学者提供类的设计思路,故不提供主函数代码,请自行设计,由于时间仓促代码多有不足,请读者朋友仔细甄别其中优劣之处,再次提醒,代码仅提供给大家作为思路参考!!!!
#ifndef A1
#define A1
#include
#include
using namespace std;
class Soldier//战士类
{
protected:
double maxHP=100,HP=100,maxSP=100,SP=100,damage=20,drugNum=5,level=1;
int exp=0;
string name;
public:
Soldier()
{
}
int enemynum = 3;//设置一个默认敌人数量
void setHP()//重置生命值为0
{
HP = 0;
}
void underattack(double x);
virtual void setname();//设置名字
virtual ~Soldier(){}
virtual void makeDecision(Soldier **t);
void attack(Soldier **t);
virtual void rest();
void takingDrug();
string getname()//获取名字
{
return name;
}
double getmaxHP()//获取最大生命值
{
return maxHP;
}
double getHP()//获取生命值
{
return HP;
}
double getdrugnum()//获取药瓶数量
{
return drugNum;
}
};
void Soldier::makeDecision(Soldier **t)//决策
{
if (HP < (maxHP * 0.3))//生命值若低于最大值的30%该回合就吃药
takingDrug();
else if (SP < (maxSP * 0.5))//体力低于最大值的50%该回合就休息
rest();
else//生命力和体力都充足该回合就发起攻击t
attack(t);
}
void Soldier::underattack(double hurt)
{
HP -= hurt;
}
void Soldier::attack(Soldier **enemy)//攻击函数(平A)
{
for (int i = 0; i < enemynum; i++)
{
if (HP > 0 && enemy[i]->getHP()> 0 && SP > 0)
{
cout << name << "攻击了" << enemy[i]->getname()<< endl;
enemy[i]->underattack(damage);
SP -= 10;
exp += 5;
cout << name << "的体力值下降至" << SP << '\t' << "经验+5(" << exp << ")" << endl;
if (exp % 20 == 0)
{
double BHP = HP / maxHP;
double BSP = SP / maxSP;
level++;
damage *= 1.2;
maxHP *= 1.2;
maxSP *= 1.2;
HP = maxHP * BHP;
SP = maxSP * BSP;
cout << name << "升级至等级" << level << endl;
}
if (enemy[i]->getHP()<= 0)
{
enemy[i]->setHP();
drugNum += enemy[i]->getdrugnum();
cout << enemy[i]->getname()<< "死亡,生命值为" <<HP<< "\t" << name << "获得药瓶数量" << enemy[i]->getdrugnum()<< endl;
}
cout << enemy[i]->getname() << "受到" << damage << "伤害 当前生命值为" << enemy[i]->getHP() << endl << endl;
return;
}
}
}
void Soldier::takingDrug()//吃药
{
cout << name << "***开始吃药***" << endl;
if (drugNum == 0)
{
cout << "很遗憾," << name << "没有药瓶了" << endl;
return;
}
else {
drugNum--;
HP += maxHP * 0.8;
if (HP > maxHP)
HP = maxHP;
}
cout << "***结束吃药***" << endl << "当前生命值:" << HP << '\t' << "体力" << SP << endl;
}
//coding by wangxiao/wansixinxin/wangboxin/liuyang
void Soldier::rest()//休息
{
cout << name << "***开始休息***" << endl;
HP += maxHP * 0.5;
if (HP > maxHP)
HP = maxHP;
SP += maxSP * 0.5;
if (SP > maxSP)
SP = maxSP;
cout << "***休息结束***" << endl << "当前生命值:" << HP << '\t' << "体力" << SP << endl;
}
void Soldier::setname()//命名
{
cout << "请为战士命名:";
cin >> name;
}
#endif // !A1
#ifndef A2
#define A2
#include"Soldier.h"
#include
using namespace std;
class Wizard :public Soldier//巫师类
{
protected:
double MP=100;
double maxMP = 100;
public:
Wizard() {}
~Wizard() {}
virtual void setname();
virtual void rest();
virtual void makeDecision(Soldier **enemy);
void wizard_attack(Soldier **enemy);//法术攻击
};
void Wizard::rest()//巫师休息
{
cout << name << "***开始休息***" << endl;
HP += maxHP * 0.5;
if (HP > maxHP)
HP = maxHP;
SP += maxSP * 0.5;
if (SP > maxSP)
SP = maxSP;
MP+= maxMP * 0.5;
if (MP > maxMP)
MP = maxMP;
cout << "***休息结束***" << endl << "当前生命值:" << HP << '\t' << "体力" << SP <<"魔法值"<<MP<<endl;
}
void Wizard::makeDecision(Soldier** enemy)
{
if (MP <= 25 && SP <= 10)
rest();
else if (MP <= 25 && SP>=10)
attack(enemy);
else if (HP <= 20)
takingDrug();
else
wizard_attack(enemy);
}
void Wizard::wizard_attack(Soldier** enemy)
{
if (HP>0)
{
for (int i = 0; i < enemynum; i++)
{
if (enemy[i]->getHP()>0)
{
if (MP > 25 && SP > 10)
{
MP -= 25;
SP -= 10;
cout << endl<< name << "对" << enemy[i]->getname() << "发动魔法攻击"<< endl;
enemy[i]->underattack(damage * 0.2);
cout << enemy[i]->getname() << "的生命值下降至" << enemy[i]->getHP() << endl;
exp += 5;
cout << name << "的体力值/魔法值下降为:" << SP << "/" << MP << "经验+5(" << exp << ")" << endl;
if (enemy[i]->getHP() <= 0)
{
enemy[i]->setHP();
drugNum += enemy[i]->getdrugnum();
cout << enemy[i]->getname()<< "死亡" << "\t" << name << "获得药瓶数量" << enemy[i]->getdrugnum()<< endl;
}
if (exp % 20 == 0)
{
double BHP = HP / maxHP;
double BSP = SP / maxSP;
double BMP = MP / maxMP;
level++;
damage *= 1.2;
maxHP *= 1.2;
maxSP *= 1.2;
maxMP *= 1.2;
HP = maxHP * BHP;
SP = maxSP * BSP;
MP = maxMP * BMP;
cout << name << "升级至等级" << level << endl;
}
}
else
{
cout << "魔法值或者体力值不足无法继续魔法攻击" << endl;
return;
}
}
}
}
}
void Wizard::setname()
{
cout << "请为法师命名:";
cin >> name;
}
#endif // !A2
#ifndef A3
#define A3
#include"Wizard.h"
class Master :public Wizard
{protected:
double NP = 100;
double maxNP = 100;
public:
Master() {};
~Master() {};
void setname();
void master_attack(Soldier **enemy);
void makeDecision(Soldier** enemy);
void rest();
};
void Master::master_attack(Soldier** enemy)//大师攻击(终结技)
{
if (HP > 0)
{
for (int i = 0; i < enemynum; i++)
{
if (enemy[i]->getHP() > 0 && NP >= 50 && SP >= 30)
{
NP -= 50;
SP -= 30;
enemy[i]->setHP();
cout << enemy[i]->getname() << "被" << name << "终结" << endl;
cout << enemy[i]->getname() << "的生命值当前为" << enemy[i]->getHP()<<endl;
exp += 5;
if (exp % 20 == 0)
{
double BHP = HP / maxHP;
double BSP = SP / maxSP;
double BMP = MP / maxMP;
double BNP = NP / maxNP;
level++;
damage *= 1.2;
maxHP *= 1.2;
maxSP *= 1.2;
maxMP *= 1.2;
HP = maxHP * BHP;
if (HP > maxHP)
HP = maxHP;
SP = maxSP * BSP;
if (SP > maxSP)
SP = maxSP;
MP = maxMP * BMP;
if (MP > maxMP)
MP = maxMP;
NP = maxNP * BNP;
if (NP > maxNP)
NP = maxNP;
cout << name << "升级至等级" << level << endl;
cout << name<<"各项属性提升至:生命" << HP << "体力" << SP << "魔法值" << MP << "内力" << NP << endl << endl;
}
}
else if (NP < 50 && SP < 30)
{
cout <<name<< "内力或体力不足无法继续发动终结技" << endl;
return;
}
}
}
}
void Master::rest()
{
cout << name << "***开始休息***" << endl;
HP += maxHP * 0.5;
if (HP > maxHP)
HP = maxHP;
SP += maxSP * 0.5;
if (SP > maxSP)
SP = maxSP;
MP += maxMP * 0.5;
if (MP > maxMP)
MP = maxMP;
NP += maxNP * 0.5;
if (NP > maxNP)
NP = maxNP;
cout << "***休息结束***" << endl << "当前生命值:" << HP << '\t' << "体力" << SP << "魔法值" << MP << "内力" << NP << endl;
}
void Master::makeDecision(Soldier** enemy)
{
for (int i = 0; i < enemynum; i++)
{
if (enemy[i]->getHP() <= enemy[i]->getmaxHP() * 0.4)
{
master_attack(enemy);
return;
}
}
if (MP <= 25 && SP <= 10)
rest();
else if (MP <= 25 && SP >= 10)
attack(enemy);
else if (HP <= 20)
takingDrug();
else
wizard_attack(enemy);
}
void Master::setname()
{
cout << "请为此大师命名:";
cin >> name;
}
#endif // !A3
#ifndef A5
#define A5
#include"Master.h"
#include
#include
class Warsystem
{
private:
Soldier** _pgroupA;
Soldier** _pgroupB;
void startround(Soldier **A,Soldier **B);
public:
bool isgrouplose(Soldier** A);
Warsystem(Soldier** A, Soldier** B)
{
_pgroupA = A;
_pgroupB = B;
}
void startwar();
};
void Warsystem::startwar()
{
int round = 1;
do
{
cout << endl<<endl<<endl<<"第" << round << "回合:" << endl << endl;
if (round++ & 1)
startround(_pgroupA, _pgroupB);
else
startround(_pgroupB, _pgroupA);
Sleep(3000);
} while (!isgrouplose(_pgroupA) && !isgrouplose(_pgroupB));
if (isgrouplose(_pgroupA))
cout << "B军团胜利";
else
cout << "A军团胜利";
}
void Warsystem::startround(Soldier** A, Soldier** B)
{
for (int i = 0; i < A[0]->enemynum; i++)
{
if(A[i]->getHP()>0)
A[i]->makeDecision(B);
}
}
bool Warsystem::isgrouplose(Soldier** A)
{
for (int i = 0; i < A[0]->enemynum; i++)
{
if (A[i]->getHP()>0)
return false;
}
return true;
}
#endif // ! A4