题目:
http://cxsjsxmooc.openjudge.cn/2021t3springall2/021/
分析:
本题主要是在 “ 魔兽世界之一 ” 的基础上增加了装备系统,需要新增一个武器类(包括基类和派生类),然后由于需要对每个武士的装备和状态进行输出,所以需要用到多态(virtual)。
下面给我写的代码以及郭炜老师的代码以供参考(我觉得参考他人特别是高手的代码不仅可以学习到其思想,还能学习到他人优秀的编码风格)。
参考代码(我的):
#include<iostream>
using namespace std;
#define WarriorNum 5
#define WarriorsMax 10000 //武士数量上限
#define WeaponNum 3
int WarriorLife[WarriorNum] ={};
char colors[2][5] = {"red", "blue"};
char WarriorsName[WarriorNum][10] ={"dragon" ,"ninja","iceman","lion","wolf"};
char WeaponName[WeaponNum][10] = {"sword", "bomb","arrow"};
class Headquarters;
class Warrior;
class Dragon;
class Ninja;
class Iceman;
class Lion;
class Wolf;
class Weapon;
class sword;
class bomb;
class arrow;
class Weapon{
private:
int attack;
int defend;
int Type;
public:
void Init(int _Type){
Type = _Type;
}
int GetWeapon(){ return Type;}
};
class Warrior{
protected:
int Life;
int Type; //武士类别,分别是dragon 、ninja、iceman、lion、wolf
int ArrayNum; //武士队列编号
Headquarters * team; //指针指回Head,省下很多参数
public:
Warrior(Headquarters * p,int _ArrayNum):team(p),ArrayNum(_ArrayNum){}
virtual void PrintProduce(int time) = 0;
void PrintProduce(int time,int) ;
virtual ~Warrior(){};
};
class Headquarters{
private:
int Life;
int Color; //0是红,1是蓝。
Warrior * WarriorsArray[WarriorsMax]; //武士队列
int WarriorsArrayNum;
int Warrior_MakeSeq[WarriorNum];//该司令部生产序列
int MakeNum; //当前生产序列编号
bool ProduceState;
int WarriorsNums[WarriorNum]; //对应武士数量
public:
Headquarters(int _Color, int _Life, int * _Warrior_MakeSeq):Color(_Color),Life(_Life){
for(int i = 0; i < WarriorNum ;i++){
Warrior_MakeSeq[i] = _Warrior_MakeSeq[i];
WarriorsNums[i] = 0;
}
WarriorsArrayNum = 0;
MakeNum = 0;
ProduceState = true;
}
~Headquarters(){
for(int i = 0; i < WarriorsArrayNum; i++) delete WarriorsArray[i];
}
bool produce(int time);
int GetLife() { return Life; }
int GetColor(){ return Color; }
int GetWarriorsNums(int Type){ return WarriorsNums[Type]; }
};
void Warrior::PrintProduce(int time,int) {
int color = team->GetColor();
printf("%03d %s %s %d born with strength %d,%d %s in %s headquarter\n",
time,colors[color],WarriorsName[Type],ArrayNum,
Life,team->GetWarriorsNums(Type),WarriorsName[Type],colors[color]);
};
class Dragon:public Warrior{
private:
Weapon wp;
float Morale;
public:
Dragon(Headquarters * p,int _ArrayNum):Warrior(p,_ArrayNum){
Type = 0;
Life = WarriorLife[Type];
wp.Init(ArrayNum % WeaponNum);
Morale = team->GetLife() * 1.0 / Life;
}
virtual void PrintProduce(int time){
Warrior::PrintProduce(time,0);
printf("It has a %s,and it's morale is %.02f\n",WeaponName[wp.GetWeapon()],Morale);
}
// virtual ~Dragon();
};
class Ninja:public Warrior{
private:
Weapon wp[2];
public:
Ninja(Headquarters * p,int _ArrayNum):Warrior(p,_ArrayNum){
Type = 1;
Life = WarriorLife[Type];
wp[0].Init(ArrayNum % WeaponNum);
wp[1].Init((ArrayNum + 1) % WeaponNum);
}
virtual void PrintProduce(int time){
Warrior::PrintProduce(time,0);
printf("It has a %s and a %s\n",WeaponName[wp[0].GetWeapon()],WeaponName[wp[1].GetWeapon()]);
}
// virtual ~Ninja();
};
class Iceman:public Warrior{
private:
Weapon wp;
public:
Iceman(Headquarters * p,int _ArrayNum):Warrior(p,_ArrayNum){
Type = 2;
Life = WarriorLife[Type];
wp.Init(ArrayNum % WeaponNum);
}
virtual void PrintProduce(int time){
Warrior::PrintProduce(time,0);
printf("It has a %s\n",WeaponName[wp.GetWeapon()]);
}
//virtual ~Iceman();
};
class Lion:public Warrior{
private:
int loyalty;
public:
Lion(Headquarters * p,int _ArrayNum):Warrior(p,_ArrayNum){
Type = 3;
Life = WarriorLife[Type];
loyalty = team->GetLife();
}
virtual void PrintProduce(int time){
Warrior::PrintProduce(time,0);
printf("It's loyalty is %d\n",loyalty);
}
//virtual ~Lion();
};
class Wolf:public Warrior{
public:
Wolf(Headquarters * p,int _ArrayNum):Warrior(p,_ArrayNum){
Type = 4;
Life = WarriorLife[Type];
}
virtual void PrintProduce(int time){
Warrior::PrintProduce(time,0);
}
// virtual ~Wolf();
};
bool Headquarters::produce(int time){
if(ProduceState == false) return false;
for(int i = 0; i < WarriorNum ; i++){
if(Life >= WarriorLife[Warrior_MakeSeq[(MakeNum + i) % WarriorNum]]){
MakeNum = (MakeNum + i) % WarriorNum;
ProduceState = true;
Life -= WarriorLife[Warrior_MakeSeq[MakeNum]];
switch (Warrior_MakeSeq[MakeNum]) { //{"dragon" ,"ninja","iceman","lion","wolf"};
case 0:
WarriorsArray[WarriorsArrayNum] = new Dragon(this,WarriorsArrayNum + 1);
break;
case 1:
WarriorsArray[WarriorsArrayNum] = new Ninja(this,WarriorsArrayNum + 1);
break;
case 2:
WarriorsArray[WarriorsArrayNum] = new Iceman(this,WarriorsArrayNum + 1);
break;
case 3:
WarriorsArray[WarriorsArrayNum] = new Lion(this,WarriorsArrayNum + 1);
break;
case 4:
WarriorsArray[WarriorsArrayNum] = new Wolf(this,WarriorsArrayNum + 1);
break;
}
WarriorsNums[Warrior_MakeSeq[MakeNum]] ++;
WarriorsArray[WarriorsArrayNum++]->PrintProduce(time);
MakeNum = (MakeNum + 1) % WarriorNum;
return true;
}
}
//上面没有return true则说明已经无法制造士兵了
ProduceState = false;
printf("%03d %s headquarter stops making warriors\n",time,colors[Color]);
return false;
}
int main(){
int n,m;
cin >> n;
for(int i = 1 ;i <= n ;i++){
cout << "Case:" << i <<endl;
cin >> m;
for(int i = 0; i < WarriorNum ; i++){
cin >> WarriorLife[i];
}
int Head_Red_Warrior_MakeSeq[WarriorNum] = {2,3,4,1,0};
int Head_Blue_Warrior_MakeSeq[WarriorNum] = {3,0,1,2,4};
Headquarters Head_Red(0,m,Head_Red_Warrior_MakeSeq);
Headquarters Head_Blue(1,m,Head_Blue_Warrior_MakeSeq);
bool Red_flag = true , Blue_flag = true; //
int time = 0;
while(Red_flag == true || Blue_flag == true){
Red_flag = Head_Red.produce(time);
Blue_flag= Head_Blue.produce(time);
time ++;
}
}
return 0;
}
参考代码(郭炜老师):
// by Guo Wei
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
//下面这些东西都是常量,而且不止一个类都要用到,就声明为全局的较为简单
#define WARRIOR_NUM 5
#define WEAPON_NUM 3
enum { DRAGON,NINJA,ICEMAN,LION,WOLF };
/*
char * CWarrior::Names[WARRIOR_NUM] = { "dragon","ninja","iceman","lion","wolf" };
红方司令部按照 iceman、lion、wolf、ninja、dragon 的顺序制造武士。
蓝方司令部按照 lion、dragon、ninja、iceman、wolf 的顺序制造武士。 */
class CHeadquarter;
class CDragon;
class CNinja;
class CIceman;
class CLion;
class CWolf;
class CWeapon;
class CWarrior;
class CWeapon {
public:
int nKindNo;
int nForce;
static int InitialForce[WEAPON_NUM];
static const char * Names[WEAPON_NUM];
};
class CWarrior {
protected:
CHeadquarter * pHeadquarter;
int nNo;
public:
static const char * Names[WARRIOR_NUM];
static int InitialLifeValue [WARRIOR_NUM];
CWarrior( CHeadquarter * p,int nNo_):pHeadquarter(p),nNo(nNo_) { }
virtual void PrintResult(int nTime,int nKindNo);
virtual void PrintResult(int nTime) = 0;
virtual ~CWarrior() { }
};
class CHeadquarter {
private:
static const int MAX_WARRIORS = 1000;
int nTotalLifeValue;
bool bStopped;
int nColor;
int nCurMakingSeqIdx;
int anWarriorNum[WARRIOR_NUM];
int nTotalWarriorNum;
CWarrior * pWarriors[MAX_WARRIORS];
public:
friend class CWarrior;
static int MakingSeq[2][WARRIOR_NUM];
void Init(int nColor_, int lv);
~CHeadquarter () ;
int Produce(int nTime);
void GetColor( char * szColor);
int GetTotalLifeValue() { return nTotalLifeValue; }
};
void CWarrior::PrintResult(int nTime,int nKindNo) {
char szColor[20];
pHeadquarter->GetColor(szColor);
printf("%03d %s %s %d born with strength %d,%d %s in %s headquarter\n"
,nTime, szColor, Names[nKindNo], nNo, InitialLifeValue[nKindNo],
pHeadquarter->anWarriorNum[nKindNo],Names[nKindNo],szColor);
}
class CDragon:public CWarrior {
private:
CWeapon wp;
double fmorale;
public:
void Countmorale(){
fmorale = pHeadquarter -> GetTotalLifeValue() /(double)CWarrior::InitialLifeValue [0];
}
CDragon( CHeadquarter * p,int nNo_):CWarrior(p,nNo_) {
wp.nKindNo = nNo % WEAPON_NUM;
wp.nForce = CWeapon::InitialForce[wp.nKindNo ];
Countmorale();
}
void PrintResult(int nTime) {
CWarrior::PrintResult(nTime,DRAGON);
printf("It has a %s,and it's morale is %.2f\n", CWeapon::Names[wp.nKindNo], fmorale); }
};
class CNinja:public CWarrior {
private:
CWeapon wps[2];
public:
CNinja( CHeadquarter * p,int nNo_):CWarrior(p,nNo_) {
wps[0].nKindNo = nNo % WEAPON_NUM;
wps[0].nForce = CWeapon::InitialForce[wps[0].nKindNo];
wps[1].nKindNo = ( nNo + 1) % WEAPON_NUM;
wps[1].nForce = CWeapon::InitialForce[wps[1].nKindNo];
}
void PrintResult(int nTime) {
CWarrior::PrintResult(nTime,NINJA);
printf("It has a %s and a %s\n",CWeapon::Names[wps[0].nKindNo],CWeapon::Names[wps[1].nKindNo]);
}
};
class CIceman:public CWarrior {
private:
CWeapon wp;
public:
CIceman( CHeadquarter * p,int nNo_):CWarrior(p,nNo_) {
wp.nKindNo = nNo % WEAPON_NUM;
wp.nForce = CWeapon::InitialForce[ wp.nKindNo ];
}
void PrintResult(int nTime) {
CWarrior::PrintResult(nTime,ICEMAN);
printf("It has a %s\n",CWeapon::Names[wp.nKindNo]);
}
};
class CLion:public CWarrior {
private:
int nLoyalty;
public:
void CountLoyalty() {
nLoyalty = pHeadquarter ->GetTotalLifeValue();
}
CLion( CHeadquarter * p,int nNo_):CWarrior(p,nNo_) {CountLoyalty(); }
void PrintResult(int nTime) {
CWarrior::PrintResult(nTime,LION);
CountLoyalty();
printf("It's loyalty is %d\n",nLoyalty);
}
};
class CWolf:public CWarrior {
public:
CWolf( CHeadquarter * p,int nNo_):CWarrior(p,nNo_) { }
void PrintResult(int nTime) {
CWarrior::PrintResult(nTime,WOLF); }
};
void CHeadquarter::Init(int nColor_, int lv) {
nColor = nColor_;
nTotalLifeValue = lv;
bStopped = false;
nCurMakingSeqIdx = 0;
nTotalWarriorNum = 0;
for( int i = 0;i < WARRIOR_NUM;i ++ ) anWarriorNum[i] = 0;
}
CHeadquarter::~CHeadquarter () {
int i;
for( i = 0;i < nTotalWarriorNum; i ++ ) delete pWarriors[i];
}
int CHeadquarter::Produce(int nTime) {
int nSearchingTimes = 0;
if( bStopped )
return 0;
while( CWarrior::InitialLifeValue[MakingSeq[nColor][nCurMakingSeqIdx]]
> nTotalLifeValue &&nSearchingTimes < WARRIOR_NUM )
{
nCurMakingSeqIdx = ( nCurMakingSeqIdx + 1 ) % WARRIOR_NUM ;
nSearchingTimes ++;
}
int nKindNo = MakingSeq[nColor][nCurMakingSeqIdx];
if( CWarrior::InitialLifeValue[nKindNo] > nTotalLifeValue ) {
bStopped = true;
if( nColor == 0)
printf("%03d red headquarter stops making warriors\n",nTime);
else
printf("%03d blue headquarter stops making warriors\n",nTime);
return 0;
}
nTotalLifeValue -= CWarrior::InitialLifeValue[nKindNo];
nCurMakingSeqIdx = ( nCurMakingSeqIdx + 1 ) % WARRIOR_NUM ;
int nTmp = anWarriorNum[nKindNo];
anWarriorNum[nKindNo] ++;
switch( nKindNo ) {
case DRAGON:
pWarriors[nTotalWarriorNum] = new CDragon( this,nTotalWarriorNum+1);
break;
case NINJA:
pWarriors[nTotalWarriorNum] = new CNinja( this,nTotalWarriorNum+1);
break;
case ICEMAN:
pWarriors[nTotalWarriorNum] = new CIceman( this,nTotalWarriorNum+1);
break;
case LION:
pWarriors[nTotalWarriorNum] = new CLion( this,nTotalWarriorNum+1);
break;
case WOLF:
pWarriors[nTotalWarriorNum] = new CWolf( this,nTotalWarriorNum+1);
break;
}
pWarriors[nTotalWarriorNum]->PrintResult(nTime);
nTotalWarriorNum ++;
return 1;
}
void CHeadquarter::GetColor( char * szColor) {
if( nColor == 0)
strcpy(szColor,"red");
else
strcpy(szColor,"blue");
}
const char * CWeapon::Names[WEAPON_NUM] = {"sword","bomb","arrow" };
int CWeapon::InitialForce[WEAPON_NUM];
const char * CWarrior::Names[WARRIOR_NUM] = { "dragon","ninja","iceman","lion","wolf" };
int CWarrior::InitialLifeValue [WARRIOR_NUM];
int CHeadquarter::MakingSeq[2][WARRIOR_NUM] = { { 2,3,4,1,0 },{3,0,1,2,4} };
int main() {
int t;
int m;
//freopen("war2.in","r",stdin);
CHeadquarter RedHead,BlueHead;
scanf("%d",&t);
int nCaseNo = 1;
while ( t -- ) {
printf("Case:%d\n",nCaseNo++);
scanf("%d",&m);
int i;
for(i = 0;i < WARRIOR_NUM;i ++ )
scanf("%d", & CWarrior::InitialLifeValue[i]);
RedHead.Init(0,m);
BlueHead.Init(1,m);
int nTime = 0;
while(true) {
int tmp1 = RedHead.Produce(nTime);
int tmp2 = BlueHead.Produce(nTime);
if( tmp1 == 0 && tmp2 == 0) break;
nTime ++;
}
}
return 0;
}