E:魔兽世界三(开战) 2022春季程设实习

该程序模拟了魔兽世界的战斗场景,包括不同类型的战士(如龙、忍者、冰人、狮子和狼)的出生、移动、战斗、武器使用和忠诚度变化。每个城市和时间点的事件,如战士出生、逃跑、前进、抢夺武器、战斗报告、生命源更新和武士状态报告等都被详细记录和输出。战斗规则遵循特定顺序,如在奇数编号城市红方先攻,武器使用前排序,以及忠诚度低于0的狮子逃跑等。此外,还包括了司令部生命元报告和武士武器情况报告。
摘要由CSDN通过智能技术生成

描述

魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市,城市从西向东依次编号为1,2,3 … N ( N <= 20)。红魔军的司令部算作编号为0的城市,蓝魔军的司令部算作编号为N+1的城市。司令部有生命元,用于制造武士。

两军的司令部都会制造武士。武士一共有dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值、攻击力这三种属性。

双方的武士编号都是从1开始计算。红方制造出来的第n 个武士,编号就是n。同样,蓝方制造出来的第n 个武士,编号也是n。

武士在刚降生的时候有一个初始的生命值,生命值在战斗中会发生变化,如果生命值减少到0(生命值变为负数时应当做变为0处理),则武士死亡(消失)。

武士可以拥有武器。武器有三种,sword, bomb,和arrow,编号分别为0,1,2。

sword的攻击力是使用者当前攻击力的20%(去尾取整)。

bomb的攻击力是使用者当前攻击力的40%(去尾取整),但是也会导致使用者受到攻击,对使用者的攻击力是对敌人取整后的攻击力的1/2(去尾取整)。Bomb一旦使用就没了。

arrow的攻击力是使用者当前攻击力的30%(去尾取整)。一个arrow用两次就没了。

武士降生后就朝对方司令部走,在经过的城市如果遇到敌人(同一时刻每个城市最多只可能有1个蓝武士和一个红武士),就会发生战斗。战斗的规则是:

  1. 在奇数编号城市,红武士先发起攻击
  2. 在偶数编号城市,蓝武士先发起攻击
  3. 战斗开始前,双方先对自己的武器排好使用顺序,然后再一件一件地按顺序使用。编号小的武器,排在前面。若有多支arrow,用过的排在前面。排好序后,攻击者按此排序依次对敌人一件一件地使用武器。如果一种武器有多件,那就都要用上。每使用一件武器,被攻击者生命值要减去武器攻击力。如果任何一方生命值减为0或小于0即为死去。有一方死去,则战斗结束。
  4. 双方轮流使用武器,甲用过一件,就轮到乙用。某一方把自己所有的武器都用过一轮后,就从头开始再用一轮。如果某一方没有武器了,那就挨打直到死去或敌人武器用完。武器排序只在战斗前进行,战斗中不会重新排序
  5. 如果双方武器都用完且都还活着,则战斗以平局结束。如果双方都死了,也算平局。
  6. 有可能由于武士自身攻击力太低,而导致武器攻击力为0。攻击力为0的武器也要使用。如果战斗中双方的生命值和武器的状态都不再发生变化,则战斗结束,算平局。
  7. 战斗的胜方获得对方手里的武器。武士手里武器总数不超过10件。缴获武器时,按照武器种类编号从小到大缴获。如果有多件arrow,优先缴获没用过的。
  8. 如果战斗开始前双方都没有武器,则战斗视为平局。如果先攻击方没有武器,则由后攻击方攻击。

不同的武士有不同的特点。

0

编号为n的dragon降生时即获得编号为n%3 的武器。dragon在战斗结束后,如果还没有战死,就会欢呼。

1

编号为n的ninjia降生时即获得编号为n%3 和(n+1)%3的武器。ninja 使用bomb不会让自己受伤。

2

编号为n的iceman降生时即获得编号为n%3 的武器。iceman每前进一步,生命值减少10%(减少的量要去尾取整)。

3

编号为n的lion降生时即获得编号为n%3 的武器。lion 有“忠诚度”这个属性,其初始值等于它降生之后其司令部剩余生命元的数目。每前进一步忠诚度就降低K。忠诚度降至0或0以下,则该lion逃离战场,永远消失。但是已经到达敌人司令部的lion不会逃跑。lion在己方司令部可能逃跑。

4

wolf降生时没有武器,但是在战斗开始前会抢到敌人编号最小的那种武器。如果敌人有多件这样的武器,则全部抢来。Wolf手里武器也不能超过10件。如果敌人arrow太多没法都抢来,那就先抢没用过的。如果敌人也是wolf,则不抢武器。

以下是不同时间会发生的不同事件:

在每个整点,即每个小时的第0分, 双方的司令部中各有一个武士降生。

红方司令部按照iceman、lion、wolf、ninja、dragon 的顺序制造武士。

蓝方司令部按照lion、dragon、ninja、iceman、wolf 的顺序制造武士。

制造武士需要生命元。

制造一个初始生命值为m 的武士,司令部中的生命元就要减少m 个。

如果司令部中的生命元不足以制造某本该造的武士,那就从此停止制造武士。

在每个小时的第5分,该逃跑的lion就在这一时刻逃跑了。

在每个小时的第10分:所有的武士朝敌人司令部方向前进一步。即从己方司令部走到相邻城市,或从一个城市走到下一个城市。或从和敌军司令部相邻的城市到达敌军司令部。

在每个小时的第35分:在有wolf及其敌人的城市,wolf要抢夺对方的武器。

在每个小时的第40分:在有两个武士的城市,会发生战斗。

在每个小时的第50分,司令部报告它拥有的生命元数量。

在每个小时的第55分,每个武士报告其拥有的武器情况。

武士到达对方司令部后就算完成任务了,从此就呆在那里无所事事。

任何一方的司令部里若是出现了敌人,则认为该司令部已被敌人占领。

任何一方的司令部被敌人占领,则战争结束。战争结束之后就不会发生任何事情了。

给定一个时间,要求你将从0点0分开始到此时间为止的所有事件按顺序输出。事件及其对应的输出样例如下:

  1. 武士降生

输出样例:000:00 blue dragon 1 born

表示在0点0分,编号为1的蓝魔dragon武士降生

如果造出的是lion,那么还要多输出一行,例:

000:00 blue lion 1 born

Its loyalty is 24

表示该lion降生时的忠诚度是24

  1. lion逃跑

输出样例:000:05 blue lion 1 ran away

表示在0点5分,编号为1的蓝魔lion武士逃走

  1. 武士前进到某一城市

输出样例:

000:10 red iceman 1 marched to city 1 with 20 elements and force 30

表示在0点10分,红魔1号武士iceman前进到1号城市,此时他生命值为20,攻击力为30

对于iceman,输出的生命值应该是变化后的数值

  1. wolf抢敌人的武器

000:35 blue wolf 2 took 3 bomb from red dragon 2 in city 4

表示在0点35分,4号城市中,红魔1号武士wolf 抢走蓝魔2号武士dragon 3个bomb。为简单起见,武器不写复数形式

  1. 报告战斗情况

战斗只有3种可能的输出结果:

000:40 red iceman 1 killed blue lion 12 in city 2 remaining 20 elements

表示在0点40分,1号城市中,红魔1号武士iceman 杀死蓝魔12号武士lion后,剩下生命值20

000:40 both red iceman 1 and blue lion 12 died in city 2

注意,把红武士写前面

000:40 both red iceman 1 and blue lion 12 were alive in city 2

注意,把红武士写前面

  1. 武士欢呼

输出样例:003:40 blue dragon 2 yelled in city 4

  1. 武士抵达敌军司令部

输出样例:001:10 red iceman 1 reached blue headquarter with 20 elements and force 30

(此时他生命值为20,攻击力为30)对于iceman,输出的生命值和攻击力应该是变化后的数值

  1. 司令部被占领

输出样例:003:10 blue headquarter was taken

9)司令部报告生命元数量

000:50 100 elements in red headquarter

000:50 120 elements in blue headquarter

表示在0点50分,红方司令部有100个生命元,蓝方有120个

10)武士报告情况

000:55 blue wolf 2 has 2 sword 3 bomb 0 arrow and 7 elements

为简单起见,武器都不写复数形式。elements一律写复数,哪怕只有1个

交代武器情况时,次序依次是:sword,bomb, arrow。

输出事件时:

首先按时间顺序输出;

同一时间发生的事件,按发生地点从西向东依次输出. 武士前进的事件, 算是发生在目的地。

在一次战斗中有可能发生上面的 5 至 6 号事件。这些事件都算同时发生,其时间就是战斗开始时间。一次战斗中的这些事件,序号小的应该先输出。

两个武士同时抵达同一城市,则先输出红武士的前进事件,后输出蓝武士的。

对于同一城市,同一时间发生的事情,先输出红方的,后输出蓝方的。

显然,8号事件发生之前的一瞬间一定发生了7号事件。输出时,这两件事算同一时间发生,但是应先输出7号事件

虽然任何一方的司令部被占领之后,就不会有任何事情发生了。但和司令部被占领同时发生的事件,全都要输出。

输入

第一行是t,代表测试数据组数

每组样例共三行。

第一行,4个整数 M,N,K, T。其含义为:
每个司令部一开始都有M个生命元( 1 <= M <= 100000)
两个司令部之间一共有N个城市( 1 <= N <= 20 )
lion每前进一步,忠诚度就降低K。(0<=K<=100)
要求输出从0时0分开始,到时间T为止(包括T) 的所有事件。T以分钟为单位,0 <= T <= 6000

第二行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的初始生命值。它们都大于0小于等于200

第三行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的攻击力。它们都大于0小于等于200

输出

对每组数据,先输出一行:

Case n:

如对第一组数据就输出 Case 1:

然后按恰当的顺序和格式输出到时间T为止发生的所有事件。每个事件都以事件发生的时间开头,时间格式是“时: 分”,“时”有三位,“分”有两位。

样例输入

1
20 1 10 400
20 20 30 10 20
5 5 5 5 5

样例输出

Case 1:
000:00 blue lion 1 born
Its loyalty is 10
000:10 blue lion 1 marched to city 1 with 10 elements and force 5
000:50 20 elements in red headquarter
000:50 10 elements in blue headquarter
000:55 blue lion 1 has 0 sword 1 bomb 0 arrow and 10 elements
001:05 blue lion 1 ran away
001:50 20 elements in red headquarter
001:50 10 elements in blue headquarter
002:50 20 elements in red headquarter
002:50 10 elements in blue headquarter
003:50 20 elements in red headquarter
003:50 10 elements in blue headquarter
004:50 20 elements in red headquarter
004:50 10 elements in blue headquarter
005:50 20 elements in red headquarter
005:50 10 elements in blue headquarter

提示

请注意浮点数精度误差问题。OJ上的编译器编译出来的可执行程序,在这方面和你电脑上执行的程序很可能会不一致。5 * 0.3 的结果,有的机器上可能是 15.00000001,去尾取整得到15,有的机器上可能是14.9999999,去尾取整后就变成14。因此,本题不要写 5 * 0.3,要写 5 * 3 / 10。

来源

Guo Wei

我的代码

分析和收获什么的……等有时间再写吧……

#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;
/*需要完成的功能:
* 城市编号、武器攻击力、战斗开始前给武器排序
* 如果司令部生命元不足以制造就停止制造
* 战斗规则
* 不同类武士的不同特点:欢呼、逃跑、抢夺武器等
* 时间:精确到分
* 事件:逃跑、前进、抢夺、战斗、生命元数量和武器情况报告、占领司令部战争结束
*/
/*计划
* weapon类:指向主人的指针、刷新攻击力函数、耐久度
* warrior类:武器向量(指向武器的指针)、武器排序(已有武器排序、抢夺武器排序)、location
* 武士移动:soldierPool
* 战斗:从西到东输出,战斗后胜方缴获对方武器
* 时间线:born lionescape march wolfTakeWeapon battle reportPower reportStatus
* 武器:使用前的排序、抢夺前排序,注意wolf的抢夺和战胜后抢夺的规则不同
*/
int makingSeq[2][5] = { {2,3,4,1,0},{3,0,1,2,4} };		// {redSeq,blueSeq}
int lifeAll, cityNum, loyaltyCost, stopTime, warrLife[5], minLife, warrATK[5]; 		//lifeD, lifeN, lifeI, lifeL, lifeW;
int curr_hour = 0;
int curr_minute = 0;
void printTime() {
	cout << setw(3) << setfill('0') << curr_hour;
	cout << ":" << setw(2) << setfill('0') << curr_minute;
}
class Headquarter;
class Warrior;
class Dragon;
class Ninja;
class Iceman;
class Lion;
class Wolf;
class CWeapon;
class CSword;
class CBomb;
class CArrow;
class BattleFront;

class CWeapon {
protected:
	int type;// 0 sword 1 bomb 2 arrow
	int ATK;//攻击力
	int durability;
	//Warrior* currOwner;//当前主人
public:
	void setATK(int ownerATK) {
		switch (type) {
		case 0:
			ATK = ownerATK * 2 / 10; break;
		case 1:
			ATK = ownerATK * 4 / 10; break;
		case 2:
			ATK = ownerATK * 3 / 10; break;
		default:
			cout << "set ATK error!" << endl; break;
		}
	}
	CWeapon(int type = 0, int ownerATK = 0, int dur = 0) :type(type), durability(dur) {
		setATK(ownerATK);
	}
	virtual ~CWeapon() {};	
	string getWeaponName() {
		switch (type) {
		case 0:
			return "sword";
		case 1:
			return "bomb";
		case 2:
			return "arrow";
		default:
			return "error!!!";
		}
	}
	friend int compareWeaponUse(const void* p1, const void* p2);
	friend int compareWeaponTake(const void* wpn1, const void* wpn2);
	friend class Warrior;
	friend class Wolf;
};

class CSword :public CWeapon {
public:
	CSword(int ownerATK = 0) :CWeapon(0, ownerATK, -1) {}
	~CSword() {};
};
class CBomb :public CWeapon {
public:
	CBomb(int ownerATK = 0) :CWeapon(1, ownerATK, 1) {}
	~CBomb() {};
};
class CArrow :public CWeapon {
public:
	CArrow(int ownerATK = 0) :CWeapon(2, ownerATK, 2) {}//耐久度=2
	~CArrow() {};
};

int compareWeaponUse(const void* p1, const void* p2) {//如果写成成员函数,就会多一个this参数
	CWeapon* wpn1 = (CWeapon*)p1;
	CWeapon* wpn2 = (CWeapon*)p2;
	if (wpn1->type != wpn2->type)
		return wpn1->type < wpn2->type;
	if (wpn1->type == 2)
		return wpn1->durability < wpn2->durability; // 使用时,弓箭耐久度高的排后面
	//compare函数需要满足严格弱序
	//运行到此处说明两种武器同样是sword或同样是bomb,或者是自己与自己相比:应当返回false
	return false;
}

int compareWeaponTake(const void* p1, const void* p2) {
	CWeapon* wpn1 = (CWeapon*)p1;
	CWeapon* wpn2 = (CWeapon*)p2;
	if (wpn1->type != wpn2->type)
		return wpn1->type < wpn2->type;
	if (wpn1->type == 2)
		return wpn1->durability > wpn2->durability; // 抢夺时,弓箭耐久度高的排后面
	return false;
}

class Headquarter {
private:
	int lifeSource = 0;		// 司令部剩余生命元
	int side;	// 0 red, 1 blue
	string sideName;
	bool isStopped = false;		// 是否停止制造
	int currWarrior = 0;		//当前武士类别,从0开始
	int numTotal = 0;		//武士总编号,初始为1
public:
	friend class Warrior;
	friend class Dragon;
	friend class Lion;
	Headquarter(int i) :side(i) { if (side)sideName = "blue"; else sideName = "red"; };		// constructor
	~Headquarter() {};
	void reset() {
		lifeSource = lifeAll;
		isStopped = false;		//是否停止制造
		currWarrior = 0;		//当前武士类别,从0开始
		numTotal = 0;		//武士总编号,初始为1
	}
	void makeWarrior();
	void reportLifeSource() {
		printTime();
		cout << " " << lifeSource << " elements in " << sideName << " headquarter" << endl;
	}
};
Headquarter redHQ(0), blueHQ(1);

class Warrior {
protected:
	int armNum; //武器数量
	vector<CWeapon*> arms;
	int armSeq = 0;
	int armCount[3] = {};//0-sword 1-bomb 2-arrow
	int warriorNum; //武士编号
	int warriorType = 0; //武士类别,从0开始
	int side; // 0-red 1-blue 
	string sideName;
	string warriorName = "\0";
	int life;
	bool _isDead = false;
	int location;
	int ATK;
	Headquarter* currHQ;
public:
	friend class Headquarter;
	friend class BattleFront;
	friend class Wolf;
	friend int compareWarrior(const void* p1, const void* p2);
	Warrior(int armNum = 0, int num = 0, int side = 0, int life = 1, int atk = 0, Headquarter* currhq = NULL) :
		armNum(armNum), warriorNum(num), side(side), life(life),ATK(atk), currHQ(currhq) {
		for (int i = 0; i < armNum; ++i) {
			int j = (warriorNum + i) % 3;
			armCount[j]++;
			switch (j) {
			case 0:
				arms.push_back(new CSword(ATK)); break;
			case 1:
				arms.push_back(new CBomb(ATK)); break;
			case 2:
				arms.push_back(new CArrow(ATK)); break;
			}
		}
		if (side)sideName = "blue";
		else sideName = "red";
		if (side)location = cityNum + 1;
		else location = 0;
	}
	virtual void warriorBorn() {
		printTime();
		cout << " " << sideName << " " << warriorName << " " << currHQ->numTotal << " born" << endl;
	}
	void Die() { _isDead = true; }
	bool isDead() {
		if (life <= 0)
			this->Die();
		return _isDead;
	}
	void removeWastedArms() {
		if (arms.empty())return;
		for (auto iter = arms.begin(); iter != arms.end(); ++iter) {
			//需要考虑到相邻两个武器耐久都为0的情况
			while ((*iter)->durability == 0) {
				armCount[(*iter)->type]--;//先减少数量,再erase
				iter = arms.erase(iter);
				if (iter == arms.end())break;
			}
			if (iter == arms.end())break;
		}
	}
	void refreshArmsUse() {
		armSeq = 0;
		this->removeWastedArms();
		if (!arms.empty()) {
			//qsort(arms[0], arms.size(), sizeof(CWeapon*), &compareWeaponUse);
			sort(arms.begin(), arms.end(), compareWeaponUse);
		}
	}
	void refreshArmsTake() {
		this->removeWastedArms();
		if (!arms.empty()) {
			//qsort(arms[0], arms.size(), sizeof(CWeapon*), &compareWeaponTake);
			sort(arms.begin(), arms.end(), compareWeaponTake);
		}
	}
	CWeapon* getWeapon() {
		if (armSeq >= arms.size())armSeq = 0;		
		return arms[armSeq++];
	}
	void fight(Warrior* wrr) {
		this->removeWastedArms();
		if (this->arms.empty())return;
		CWeapon* currWpn = getWeapon();
		wrr->life -= currWpn->ATK;
		//cout << this->sideName << " " << this->warriorName << " " << this->warriorNum << " attack " <<
		//	wrr->sideName << " " << wrr->warriorName << " " << wrr->warriorNum << " using " <<
		//	currWpn->getWeaponName() << " force " << currWpn->ATK << endl;
		if (currWpn->type == 1 && this->warriorType != 1)
			this->life -= int(currWpn->ATK / 2);
		if (currWpn->type != 0)
			currWpn->durability--;
		this->removeWastedArms();
		wrr->removeWastedArms();
		this->isDead(); wrr->isDead();
	};
	void takeArms(Warrior* wrr) {
		if (wrr->arms.empty())return;
		wrr->refreshArmsTake();
		for (auto iter = wrr->arms.begin(); iter != wrr->arms.end(); ++iter) {
			if (this->arms.size() >= 10)break;
			this->arms.push_back(*iter);
			this->armCount[(*iter)->type]++;
			this->arms.back()->setATK(this->ATK);
		}
		wrr->arms.clear();
	}
	bool isHarmless() {//如果武士所有的武器都用完,或是剩余武器攻击力全为0,则为harmless
		if (arms.empty())return true;//所有武器都用完了
		if (armCount[1] != 0 || armCount[2] != 0)return false;//有炸弹或箭矢,可以使用
		for (auto iter = arms.begin(); iter != arms.end(); ++iter) {
			if ((*iter)->type == 0 && (*iter)->ATK != 0)return false;//存在有攻击力不为0的sword,可以使用
		}
		return true;//没有可造成伤害的武器了
	}
};



class Dragon :public Warrior {
public:
	Dragon(int num, int side, int life, int atk, Headquarter* currhq) :Warrior(1, num, side, life, atk, currhq) {
		warriorName = "dragon";
		warriorType = 0;
	}
	~Dragon() {};
};
class Ninja :public Warrior {
public:
	Ninja(int num, int side, int life,int atk, Headquarter* currhq) : Warrior(2, num, side, life, atk, currhq) {
		warriorName = "ninja";
		warriorType = 1;
	}
	~Ninja() {};
};
class Iceman :public Warrior {
public:
	Iceman(int num, int side, int life,int atk, Headquarter* currhq) :Warrior(1, num, side, life,atk, currhq) {
		warriorName = "iceman";
		warriorType = 2;
	}
	~Iceman() {};
};
class Lion :public Warrior {
private:
	int loyalty;
public:
	Lion(int num, int side, int life,int atk, Headquarter* currhq) :Warrior(1, num, side, life,atk, currhq) {
		warriorName = "lion";
		loyalty = currHQ->lifeSource;
		warriorType = 3;
	}
	~Lion() {};
	void warriorBorn() {
		Warrior::warriorBorn();
		cout << "Its loyalty is " << loyalty << endl;
	}
	friend class BattleFront;
};
class Wolf : public Warrior {
public:
	Wolf(int num, int side, int life,int atk, Headquarter* currhq) :Warrior(0, num, side, life,atk, currhq) {
		warriorName = "wolf";
		warriorType = 4;
	}
	~Wolf() {};
	void takeArm_Wolf(Warrior* wrr) {
		if (wrr->arms.empty())return;
		wrr->refreshArmsTake();
		//不用for循环,因为erase后相当于++iter,然后会和for里的++iter搞混;或者删除for里的++iter
		//for (auto iter = wrr->arms.begin(); iter < wrr->arms.end(); ++iter) {
		//	if (this->arms.size() >= 10)break;
		//	this->arms.push_back(*iter);
		//	this->arms.back()->setATK(this->ATK);
		//	this->armCount[(*iter)->type]++;
		//	wrr->armCount[(*iter)->type]--;
		//	takeCount++;
		//	takeWeaponName = (*iter)->getWeaponName();
		//	int originalType = (*iter)->type;
		//	iter = wrr->arms.erase(iter);
		//	if (iter == wrr->arms.end())break;
		//	if ((*iter)->type != originalType)break;
		//}
		auto iter = wrr->arms.begin();
		int takeWeaponType = (*iter)->type;
		int takeCount = 0;
		string takeWeaponName;
		while ((*iter)->type == takeWeaponType && this->arms.size() <= 10) {
			takeWeaponName = (*iter)->getWeaponName();
			this->arms.push_back(*iter);
			this->arms.back()->setATK(this->ATK);
			this->armCount[(*iter)->type]++;
			wrr->armCount[(*iter)->type]--;
			takeCount++;
			iter = wrr->arms.erase(iter);
			if (iter == wrr->arms.end())break;
		}
		if (takeCount != 0) {
			printTime();
			cout << " " << this->sideName << " wolf " << this->warriorNum << " took " << takeCount << " " << takeWeaponName <<
				" from " << wrr->sideName << " " << wrr->warriorName << " " << wrr->warriorNum << " in city " << this->location << endl;
		}
	}
};
int compareWarrior(const void* p1, const void* p2) {
	//注意 sort中使用的compare函数需要满足严格弱序条件
	Warrior* wrr1 = (Warrior*)p1;
	Warrior* wrr2 = (Warrior*)p2;
	if (wrr1->location != wrr2->location)
		return wrr1->location < wrr2->location;
	//location相同,一红一蓝
	return wrr1->side < wrr2->side; //0-red first
}
class BattleFront {
private:
	vector<Warrior*>warriorLine; //兵线,储存所有武士,以从西到东排序,同一城市的红蓝武士,红方在西边
public:
	BattleFront() {};
	~BattleFront() {
		int len = (int)warriorLine.size();
		for (int i = 0; i < len; ++i)
			if (warriorLine[i])delete warriorLine[i];
	}
	void addWarrior(Warrior* wrr) {
		warriorLine.push_back(wrr);
		wrr->warriorBorn();
	}
	void clearWarriors() {
		warriorLine.clear();
	}
	void refreshWarriorLine() {//march时调用
		// erase the dead warriors, then sort
		for (auto iter = warriorLine.begin(); iter != warriorLine.end(); ++iter) { 
			//需要考虑到相邻两个武士都死亡的情况
			while ((*iter)->isDead()) {
				iter = warriorLine.erase(iter);
				if (iter == warriorLine.end())break;
			}
			if (iter == warriorLine.end())break;
		}
		//stable_sort(warriorLine.begin(), warriorLine.end(), &BattleFront::compareWarrior);
		if (!warriorLine.empty()) {
			//qsort(warriorLine[0], warriorLine.size(), sizeof(Warrior*), &compareWarrior);
			sort(warriorLine.begin(), warriorLine.end(), compareWarrior);//注意 sort中使用的compare函数需要满足严格弱序条件
		}
	}
	void lionEscape() {//000:05
		for (auto iter = warriorLine.begin(); iter != warriorLine.end(); ++iter) {
			if ((*iter)->warriorType == 3 && (!(*iter)->isDead())) {
				Lion* lion = dynamic_cast<Lion*>(*iter);//下行转换为派生类对象指针
				if (lion->loyalty <= 0) {
					printTime();
					cout << " " << lion->sideName << " lion " << lion->warriorNum << " ran away" << endl;
					lion->Die(); //此处手动让lion死亡,其生命值并没有降为0或0以下
				}
			}
		}
		this->refreshWarriorLine();
	}
	bool march() {//000:10
		bool win = false;	
		if (warriorLine.empty())return false;
		//武士前进,lion减少忠诚度,iceman减少生命值
		for (auto iter = warriorLine.begin(); iter != warriorLine.end(); ++iter) {
			Warrior* wrr = *iter;
			if (wrr->side)wrr->location--;//blue
			else wrr->location++;//red
			if (wrr->warriorType == 3) {//lion
				Lion* lion = dynamic_cast<Lion*>(wrr);
				lion->loyalty -= loyaltyCost;
			}
			if (wrr->warriorType == 2) {//iceman
				wrr->life -= wrr->life / 10;
			}
		}
		this->refreshWarriorLine();
		//按照从西到东,先红后蓝的顺序输出到达城市(或司令部)、生命值与攻击力,司令部被占领
		//000:10 red iceman 1 marched to city 1 with 20 elements and force 30
		//001:10 red iceman 1 reached blue headquarter with 20 elements and force 30
		for (auto iter = warriorLine.begin(); iter != warriorLine.end(); ++iter) {
			Warrior* wrr = *iter;
			printTime();
			cout << " " << wrr->sideName << " " << wrr->warriorName << " " << wrr->warriorNum;			
			if (wrr->side == 0 && wrr->location == cityNum + 1) {// red warrior reached blue hq
				cout << " reached blue headquarter" << " with " << wrr->life << " elements and force " << wrr->ATK << endl;
				printTime();
				cout << " blue headquarter was taken" << endl;
				win = true;
			}
			else if (wrr->side == 1 && wrr->location == 0) {//blue warrior reached red hq
				cout << " reached red headquarter" << " with " << wrr->life << " elements and force " << wrr->ATK << endl;
				printTime();
				cout << " red headquarter was taken" << endl;
				win = true;
			}
			else {
				cout << " marched to city " << wrr->location << " with " << wrr->life << " elements and force " << wrr->ATK << endl;
			}
		}
		return win;
	}
	void wolfTakeWeapon() {//000:35
		if (warriorLine.empty())return;
		for (auto iter = warriorLine.begin(); iter < warriorLine.end() - 1; ++iter) {
			Warrior* wrr1 = *iter;
			Warrior* wrr2 = *(iter + 1);
			if (wrr1->location == wrr2->location) {
				if (wrr1->warriorType != 4 && wrr2->warriorType != 4) { ++iter; continue; }//都不是wolf,不抢
				if (wrr1->warriorType == 4 && wrr2->warriorType == 4) { ++iter; continue; }//都是wolf,也不抢,++iter相当于加两次,跳过了wrr2
				if (wrr1->warriorType == 4) {
					Wolf* wolf = dynamic_cast<Wolf*>(wrr1);
					wolf->takeArm_Wolf(wrr2);
					++iter;
				}
				if (wrr2->warriorType == 4) {
					Wolf* wolf = dynamic_cast<Wolf*>(wrr2);
					wolf->takeArm_Wolf(wrr1);
					++iter;
				}
			}
		}
	}
	bool fightEnd(Warrior* red_wrr, Warrior* blue_wrr) {//be sure that wrr1 is red!
		if (!red_wrr->isDead() && blue_wrr->isDead()) {//red wrr wins
			printTime();
			cout << " " << red_wrr->sideName << " " << red_wrr->warriorName << " " << red_wrr->warriorNum << " killed " <<
				blue_wrr->sideName << " " << blue_wrr->warriorName << " " << blue_wrr->warriorNum << " in city " << red_wrr->location <<
				" remaining " << red_wrr->life << " elements" << endl;
			red_wrr->takeArms(blue_wrr);
			return true;
		}
		else if (red_wrr->isDead() && !blue_wrr->isDead()) {//blue wrr wins
			printTime();
			cout << " " << blue_wrr->sideName << " " << blue_wrr->warriorName << " " << blue_wrr->warriorNum << " killed " <<
				red_wrr->sideName << " " << red_wrr->warriorName << " " << red_wrr->warriorNum << " in city " << red_wrr->location <<
				" remaining " << blue_wrr->life << " elements" << endl;
			blue_wrr->takeArms(red_wrr);
			return true;
		}
		else if (red_wrr->isDead() && blue_wrr->isDead()) {//both died
			printTime();
			cout << " both red " << red_wrr->warriorName << " " << red_wrr->warriorNum << " and blue " <<
				blue_wrr->warriorName << " " << blue_wrr->warriorNum << " died in city " << blue_wrr->location << endl;
			return true;
		}
		else {//both alive
			if (red_wrr->isHarmless() && blue_wrr->isHarmless()) {//both are harmless
				printTime();
				cout << " both red " << red_wrr->warriorName << " " << red_wrr->warriorNum << " and blue " <<
					blue_wrr->warriorName << " " << blue_wrr->warriorNum << " were alive in city " << blue_wrr->location << endl;
				return true;
			}
			else return false;
		}
	}
	void Battle() {//000:40
		if (warriorLine.empty())return;
		for (auto iter = warriorLine.begin(); iter < warriorLine.end() - 1; ++iter){
			Warrior* wrr1 = *iter;
			Warrior* wrr2 = *(iter + 1);
			if (wrr1->location == wrr2->location) {//battle starts, wrr1-red wrr2-blue
				wrr1->refreshArmsUse();
				wrr2->refreshArmsUse();
				if (wrr1->location % 2 == 0) {//even number, blue first
					while (true) {
						wrr2->fight(wrr1);
						if (fightEnd(wrr1, wrr2))break;
						wrr1->fight(wrr2);
						if (fightEnd(wrr1, wrr2))break;
					}
				}
				else {//odd number, red first
					while (true) {
						wrr1->fight(wrr2);
						if (fightEnd(wrr1, wrr2))break;
						wrr2->fight(wrr1);
						if (fightEnd(wrr1, wrr2))break;
					}
				}
				//不确定是先输出完所有战斗结果,再yell;还是按照城市进行
				if (wrr1->warriorType == 0 && !wrr1->isDead()) {
					printTime();
					cout << " red dragon " << wrr1->warriorNum << " yelled in city " << wrr1->location << endl;
				}
				if (wrr2->warriorType == 0 && !wrr2->isDead()) {
					printTime();
					cout << " blue dragon " << wrr2->warriorNum << " yelled in city " << wrr2->location << endl;
				}
				++iter;
			}
		}
	}
	void reportWarriorStatus() {//000:55
		if (warriorLine.empty())return;
		this->refreshWarriorLine();
		for (auto iter = warriorLine.begin(); iter != warriorLine.end(); ++iter) {
			Warrior* wrr = *iter;
			printTime();
			cout << " " << wrr->sideName << " " << wrr->warriorName << " " << wrr->warriorNum <<
				" has " << wrr->armCount[0] << " sword " << wrr->armCount[1] << " bomb " << wrr->armCount[2] << " arrow and " <<
				wrr->life << " elements" << endl;
		}
	}
};
BattleFront battlefront;
void Headquarter::makeWarrior() {
	if (isStopped)return;
	currWarrior = makingSeq[side][numTotal % 5];		//No. of current warrior 0-dragon 1-ninja 2-iceman 3-lion 4-wolf
	if (lifeSource >= warrLife[currWarrior]) {		//若当前生命元大于等于武士生命值,可以制造当前武士	
		lifeSource -= warrLife[currWarrior];		//减少生命元,先于武士降生,因为要根据降生后的生命元来生成士气值和忠诚度
		numTotal++;		//武士编号,初始为1
		switch (currWarrior)
		{
		case 0: //dragon
			battlefront.addWarrior(new Dragon(numTotal, side, warrLife[0], warrATK[0], this)); break;//Dragon对象是一个局部对象,赋值给newWarrior的时候只保留了其中属于warrior对象的部分
		case 1: //ninja
			battlefront.addWarrior(new Ninja(numTotal, side, warrLife[1], warrATK[1], this)); break;
		case 2: //iceman
			battlefront.addWarrior(new Iceman(numTotal, side, warrLife[2], warrATK[2], this)); break;
		case 3: //lion
			battlefront.addWarrior(new Lion(numTotal, side, warrLife[3], warrATK[3], this)); break;
		case 4: //wolf
			battlefront.addWarrior(new Wolf(numTotal, side, warrLife[4], warrATK[4], this)); break;
		}
		//pWarriors.back()->warriorBorn();
		return;
	}
	else {		//若当前生命元不足以制造当前武士,则停止制造武士
		isStopped = true;
		return;
	}
}
int main() {
	int n;		//case number
	cin >> n;
	for (int caseNum = 1; caseNum <= n; ++caseNum) {
		/*输入与初始化*/
		cin >> lifeAll >> cityNum >> loyaltyCost >> stopTime >>
			warrLife[0] >> warrLife[1] >> warrLife[2] >> warrLife[3] >> warrLife[4] >>
			warrATK[0] >> warrATK[1] >> warrATK[2] >> warrATK[3] >> warrATK[4];
		redHQ.reset(); blueHQ.reset(); //reset headquarter status
		curr_hour = 0; 		//set time at 0
		cout << "Case " << caseNum <<":" << endl;
		while (true) {
			curr_minute = 0;
			if (curr_minute + curr_hour * 60 > stopTime)break;
			redHQ.makeWarrior(); blueHQ.makeWarrior();

			//lionrunaway
			curr_minute = 5;
			if (curr_minute + curr_hour * 60 > stopTime)break;
			battlefront.lionEscape();

			//march
			curr_minute = 10;
			if (curr_minute + curr_hour * 60 > stopTime)break;
			bool winstatus = battlefront.march();
			if (winstatus)break;

			//wolftakewaepon
			curr_minute = 35;
			if (curr_minute + curr_hour * 60 > stopTime)break;
			battlefront.wolfTakeWeapon();

			//battle
			curr_minute = 40;
			if (curr_minute + curr_hour * 60 > stopTime)break;
			battlefront.Battle();

			//reportpower
			curr_minute = 50;
			if (curr_minute + curr_hour * 60 > stopTime)break;
			redHQ.reportLifeSource(); blueHQ.reportLifeSource();

			//reportstatus
			curr_minute = 55;
			if (curr_minute + curr_hour * 60 > stopTime)break;
			battlefront.reportWarriorStatus();

			++curr_hour;
		}
		battlefront.clearWarriors();
	}
	return 0;
}

致谢

感谢这些文章,真的帮了我很大的忙!好人一生平安.jpg
c++ invalid comparator
北京大学MOOC 程序设计与算法(三)魔兽世界三(开战)
dynamic_cast用法总结
OpenJudge - 045:魔兽世界三(开战) ←提供了错误测试点输入输出
pic
真是赏心悦目的颜色呢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值