魔兽世界之四:终极版(北京大学MOOC 程序设计与算法(三) C++面向对象程序设计)

本文主要是介绍魔兽世界之四:终极版(北京大学MOOC 程序设计与算法(三) C++面向对象程序设计),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

跳转解析:

题目解析~

参考代码~


题目来源:

北京大学MOOC 郭炜 程序设计与算法(三)C++面向对象程序设计

描述:

魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市,城市从西向东依次编号为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。

武士降生后就朝对方司令部走,在经过的城市如果遇到敌人(同一时刻每个城市最多只可能有1个蓝武士和一个红武士),就会发生战斗。每次战斗只有一方发起主动进攻一次。被攻击者生命值会减去进攻者的攻击力值和进攻者手中sword的攻击力值。被进攻者若没死,就会发起反击,被反击者的生命值要减去反击者攻击力值的一半(去尾取整)和反击者手中sword的攻击力值。反击可能致敌人于死地。

如果武士在战斗中杀死敌人(不论是主动进攻杀死还是反击杀死),则其司令部会立即向其发送8个生命元作为奖励,使其生命值增加8。当然前提是司令部得有8个生命元。如果司令部的生命元不足以奖励所有的武士,则优先奖励距离敌方司令部近的武士。

如果某武士在某城市的战斗中杀死了敌人,则该武士的司令部立即取得该城市中所有的生命元。注意,司令部总是先完成全部奖励工作,然后才开始从各个打了胜仗的城市回收生命元。对于因司令部生命元不足而领不到奖励的武士,司令部也不会在取得战利品生命元后为其补发奖励。

如果一次战斗的结果是双方都幸存(平局),则双方都不能拿走发生战斗的城市的生命元。

城市可以插旗子,一开始所有城市都没有旗子。在插红旗的城市,以及编号为奇数的无旗城市,由红武士主动发起进攻。在插蓝旗的城市,以及编号为偶数的无旗城市,由蓝武士主动发起进攻。

当某个城市有连续两场战斗都是同一方的武士杀死敌人(两场战斗之间如果有若干个战斗时刻并没有发生战斗,则这两场战斗仍然算是连续的;但如果中间有平局的战斗,就不算连续了) ,那么该城市就会插上胜方的旗帜,若原来插着败方的旗帜,则败方旗帜落下。旗帜一旦插上,就一直插着,直到被敌人更换。一个城市最多只能插一面旗帜,旗帜没被敌人更换前,也不会再次插同颜色的旗。

各种武器有其特点:

sword武器的初始攻击力为拥有它的武士的攻击力的20%(去尾取整)。但是sword每经过一次战斗(不论是主动攻击还是反击),就会变钝,攻击力变为本次战斗前的80% (去尾取整)。sword攻击力变为0时,视为武士失去了sword。如果武士降生时得到了一个初始攻击力为0的sword,则视为武士没有sword.

arrow有一个攻击力值R。如果下一步要走到的城市有敌人,那么拥有arrow的武士就会放箭攻击下一个城市的敌人(不能攻击对方司令部里的敌人)而不被还击。arrow使敌人的生命值减少R,若减至小于等于0,则敌人被杀死。arrow使用3次后即被耗尽,武士失去arrow。两个相邻的武士可能同时放箭把对方射死。

拥有bomb的武士,在战斗开始前如果判断自己将被杀死(不论主动攻击敌人,或者被敌人主动攻击都可能导致自己被杀死,而且假设武士可以知道敌人的攻击力和生命值),那么就会使用bomb和敌人同归于尽。武士不预测对方是否会使用bomb。

武士使用bomb和敌人同归于尽的情况下,不算是一场战斗,双方都不能拿走城市的生命元,也不影响城市的旗帜。

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

dragon可以拥有一件武器。编号为n的dragon降生时即获得编号为 n%3 的武器。dragon还有“士气”这个属性,是个浮点数,其值为它降生后其司令部剩余生命元的数量除以造dragon所需的生命元数量。dragon 在一次在它主动进攻的战斗结束后,如果还没有战死,而且士气值大于0.8,就会欢呼。dragon每取得一次战斗的胜利(敌人被杀死),士气就会增加0.2,每经历一次未能获胜的战斗,士气值就会减少0.2。士气增减发生在欢呼之前。

ninja可以拥有两件武器。编号为n的ninja降生时即获得编号为 n%3 和 (n+1)%3的武器。ninja 挨打了也从不反击敌人。

iceman有一件武器。编号为n的iceman降生时即获得编号为 n%3 的武器。iceman 每前进两步,在第2步完成的时候,生命值会减少9,攻击力会增加20。但是若生命值减9后会小于等于0,则生命值不减9,而是变为1。即iceman不会因走多了而死。

lion 有“忠诚度”这个属性,其初始值等于它降生之后其司令部剩余生命元的数目。每经过一场未能杀死敌人的战斗,忠诚度就降低K。忠诚度降至0或0以下,则该lion逃离战场,永远消失。但是已经到达敌人司令部的lion不会逃跑。Lion在己方司令部可能逃跑。lion 若是战死,则其战斗前的生命值就会转移到对手身上。所谓“战斗前”,就是每个小时的40分前的一瞬间。

wolf降生时没有武器,但是在战斗中如果获胜(杀死敌人),就会缴获敌人的武器,但自己已有的武器就不缴获了。被缴获的武器当然不能算新的,已经被用到什么样了,就是什么样的。

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

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

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

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

制造武士需要生命元。

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

如果司令部中的生命元不足以制造某武士,那么司令部就等待,直到获得足够生命元后的第一个整点,才制造该武士。例如,在2:00,红方司令部本该制造一个 wolf ,如果此时生命元不足,那么就会等待,直到生命元足够后的下一个整点,才制造一个 wolf。

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

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

在每个小时的第20分:每个城市产出10个生命元。生命元留在城市,直到被武士取走。

在每个小时的第30分:如果某个城市中只有一个武士,那么该武士取走该城市中的所有生命元,并立即将这些生命元传送到其所属的司令部。

在每个小时的第35分,拥有arrow的武士放箭,对敌人造成伤害。放箭事件应算发生在箭发出的城市。注意,放箭不算是战斗,因此放箭的武士不会得到任何好处。武士在没有敌人的城市被箭射死也不影响其所在城市的旗帜更换情况。

在每个小时的第38分,拥有bomb的武士评估是否应该使用bomb。如果是,就用bomb和敌人同归于尽。

在每个小时的第40分:在有两个武士的城市,会发生战斗。 如果敌人在5分钟前已经被飞来的arrow射死,那么仍然视为发生了一场战斗,而且存活者视为获得了战斗的胜利。此情况下不会有“武士主动攻击”,“武士反击”,“武士战死”的事件发生,但战斗胜利后应该发生的事情都会发生。如Wolf一样能缴获武器,旗帜也可能更换,等等。在此情况下,Dragon同样会通过判断是否应该轮到自己主动攻击来决定是否欢呼。

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

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

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

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

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

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

1) 武士降生

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

表示在 0点0分,编号为1的蓝魔lion武士降生
如果造出的是dragon,那么还要多输出一行,例:

000:00 blue dragon 1 born
Its morale is 23.34

表示该该dragon降生时士气是23. 34(四舍五入到小数点后两位)

如果造出的是lion,那么还要多输出一行,例:
000:00 blue lion 1 born
Its loyalty is 24

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

2) lion逃跑

输出样例: 000:05 blue lion 1 ran away
表示在 0点5分,编号为1的蓝魔lion武士逃走

3) 武士前进到某一城市

输出样例: 000:10 red iceman 1 marched to city 1 with 20 elements and force 30
表示在 0点10分,红魔1号武士iceman前进到1号城市,此时他生命值为20,攻击力为30
对于iceman,输出的生命值和攻击力应该是变化后的数值

4)武士放箭

输出样例: 000:35 blue dragon 1 shot
表示在 0点35分,编号为1的蓝魔dragon武士射出一支箭。如果射出的箭杀死了敌人,则应如下输出:
000:35 blue dragon 1 shot and killed red lion 4
表示在 0点35分,编号为1的蓝魔dragon武士射出一支箭,杀死了编号为4的红魔lion。

5)武士使用bomb

输出样例: 000:38 blue dragon 1 used a bomb and killed red lion 7
表示在 0点38分,编号为1的蓝魔dragon武士用炸弹和编号为7的红魔lion同归于尽。

6) 武士主动进攻

输出样例:000:40 red iceman 1 attacked blue lion 1 in city 1 with 20 elements and force 30
表示在0点40分,1号城市中,红魔1号武士iceman 进攻蓝魔1号武士lion,在发起进攻前,红魔1号武士iceman生命值为20,攻击力为 30

7) 武士反击

输出样例:001:40 blue dragon 2 fought back against red lion 2 in city 1
表示在1点40分,1号城市中,蓝魔2号武士dragon反击红魔2号武士lion

8) 武士战死

输出样例:001:40 red lion 2 was killed in city 1
被箭射死的武士就不会有这一条输出。

9) 武士欢呼

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

10) 武士获取生命元( elements )

输出样例:001:40 blue dragon 2 earned 10 elements for his headquarter

输出不包括在30分不是通过战斗获取的elements

11) 旗帜升起

输出样例:004:40 blue flag raised in city 4

12) 武士抵达敌军司令部

输出样例:001:10 red iceman 1 reached blue headquarter with 20 elements and force 30
(此时他生命值为20,攻击力为30)对于iceman,输出的生命值和攻击力应该是变化后的数值

13) 司令部被占领

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

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

000:50 100 elements in red headquarter
000:50 120 elements in blue headquarter
表示在0点50分,红方司令部有100个生命元,蓝方有120个

15)武士报告武器情况

000:55 blue wolf 2 has arrow(2),bomb,sword(23)
000:55 blue wolf 4 has no weapon
000:55 blue wolf 5 has sword(20)
表示在0点55分,蓝魔2号武士wolf有一支arrow(这支arrow还可以用2次),一个bomb,还有一支攻击力为23的sword。
蓝魔4号武士wolf没武器。
蓝魔5号武士wolf有一支攻击力为20的sword。
交代武器情况时,次序依次是:arrow,bomb,sword。如果没有某种武器,某种武器就不用提。报告时,先按从西向东的顺序所有的红武士报告,然后再从西向东所有的蓝武士报告。

输出事件时:

首先按时间顺序输出;

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

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

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

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

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

输入:

第一行是t,代表测试数据组数
每组样例共三行。
第一行,五个整数 M,N,R,K, T。其含义为:

每个司令部一开始都有M个生命元( 1 <= M <= 10000)
两个司令部之间一共有N个城市( 1 <= N <= 20 )
arrow的攻击力是R
lion每经过一场未能杀死敌人的战斗,忠诚度就降低K。
要求输出从0时0分开始,到时间T为止(包括T) 的所有事件。T以分钟为单位,0 <= T <= 5000

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

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

输出:

对每组数据,先输出一行:
Case n:
如对第一组数据就输出 Case1:
然后按恰当的顺序和格式输出到时间T为止发生的所有事件。每个事件都以事件发生的时间开头,时间格式是“时: 分”,“时”有三位,“分”有两位。

样例输入:

1
20 1 10 10 1000
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:30 blue lion 1 earned 10 elements for his headquarter
000:50 20 elements in red headquarter
000:50 20 elements in blue headquarter
000:55 blue lion 1 has no weapon
001:00 blue dragon 2 born
Its morale is 0.00
001:10 blue lion 1 reached red headquarter with 10 elements and force 5
001:10 blue dragon 2 marched to city 1 with 20 elements and force 5
001:30 blue dragon 2 earned 10 elements for his headquarter
001:50 20 elements in red headquarter
001:50 10 elements in blue headquarter
001:55 blue lion 1 has no weapon
001:55 blue dragon 2 has arrow(3)
002:10 blue dragon 2 reached red headquarter with 20 elements and force 5
002:10 red headquarter was taken

 题目解析:

该题在“魔兽世界三:开战”基础上改变和新增了许多功能,特别是在武士战斗、武器使用、新增城市旗帜这三个方面。其中如何处理武士之间的战斗关系、如何对城市旗帜的状态进行判断、如何处理相互关联事件的时间线以及如何在正确的时机输出信息是该题的几个重点。此外,对于题意的理解也有如下值得注意的地方

/*
1. 如果武士在战斗中没有sword,那么在主动攻击中被攻击者只需减去进攻者的攻击力,反击也是如此。 2. “sword武器的初始攻击力为拥有它的武士的攻击力的20%(去尾取整) ”: 
虽然iceman每走两步攻击力要提升,但是若其有一把从来没有用过的sword,那么这个sword的攻击力并不会重新更新。 
同样如果wolf抢夺到了一把从未使用过的sword,那么这个sword的攻击力也不会更新为这个wolf攻击力的20%; 3. 在35分的射箭环节上,每名战士最多只能射出一支箭 4. “武士到达对方司令部后就算完成任务了,从此就呆在那里无所事事”:但在55分时,依然会报告其拥有的武器情况 ; 5. “在每个小时的第20分:每个城市产出10个生命元。生命元留在城市,直到被武士取走”:城市中的生命元可累加,直到被武士取走 ; 6. dragon的士气是否可以为负值,在通过测试的代码中我并没有去限制这一点,因此无影响。
此外关于士气保留两位小数四舍五入输出的精度问题,参考我在“魔兽世界之二:装备(北京大学MOOC 程序设计与算法(三) C++面向对象程序设计)”这篇文章中给出的解释 ; 
*/

参考代码:

提交状体为Accepted的参考代码如下

# include<iostream>
# include<iomanip>
# include<string>
# include<cmath>
# include<map>
using namespace std;# define WEPON_MAX_NUM 3				// 根据题意一个武士拥有的最多武器件数
# define WARRIOR_KIND_NUM 5				// 武士的种类
# define SWORD_DAMAGE 2 / 10			// sword的初始攻击力为拥有者的百分比
# define SWORD_ABRASE 8 / 10			// 每使用一次攻击力为原攻击力的百分比
# define ICEMAN_LIFE_REDUCE 9			// 每前进两步iceman生命值减少量
# define ICEMAN_DAMAGE_INCREASE 20		// 每前进两部iceman攻击力增加量	
# define HEADQUARTER_INSPIRE 8			// 司令部向获胜的战士奖励的生命元个数int CITY_NUM;							// 两个司令部之间城市的数量
int TIME_NUM;							// 每组进行总的世界,以分为单位
int ARROW_DAMAGE;						// 弓箭的攻击力
int LIFE_ELEMENT;						// 一开始拥有的生命元数量
int LION_LOAYLTY_REDUCE;				// lion每经过一场未能杀死敌人的战斗,忠诚度降低值
double DRAGON_MORALE_CHANGE = 0.2;		// dragon每经过一场战斗,士气变化值
double DRAGON_MORALE_YELL = 0.8;		// dragon欢呼的判定条件之一(士气值的最小界,不包括)map<string, int> WARRIOR_LIFE;												// 制造各种武士所需的生命元
map<string, int> WARRIOR_DAMAGE;											// 每种武士的攻击力
map<string, int>WEPON_USE_TIME = { {"sword",-1},{"bomb",1},{"arrow",3} };	// 武器使用次数,-1表示可以无限次数使用			string WEPON_LIST[3] = { "sword","bomb","arrow" };											// 武器列表	
string WARRIOR_CIN_SORT[WARRIOR_KIND_NUM] = { "dragon","ninja","iceman","lion","wolf" };	// 生命值和攻击力输入顺序class CWarrior;
// 武器类
class CWepon {
public:string name;		// 武器名称int id;				// 武器编号int damage_value;	// 武器攻击力int use_time;		// 使用次数// 构造函数CWepon(int _id) :id(_id), damage_value(0) {// damage_value的赋值主要放在派生类的构造函数中进行,这里先默认设置为0name = WEPON_LIST[_id];use_time = WEPON_USE_TIME[name];}// 重载运算符实现武器之间的大小比较bool operator > (const CWepon& compare_object) {if (id > compare_object.id)return true;else return false;}// 使用武器virtual void use_attribute(CWarrior* warrior_use, CWarrior* warrior_victim) {}virtual void use_attribute(int city_num, int time_now, CWarrior* warrior_use, CWarrior* warrior_victim) {}virtual ~CWepon() {}
};// 武器派生类sword
class CSword :public CWepon {
public:// 构造函数CSword(int _id, int warrior_damage_value) :CWepon(_id) {// 初始攻击力为拥有它的武士的攻击力的20%damage_value = warrior_damage_value * SWORD_DAMAGE;}// 使用属性virtual void use_attribute(CWarrior* warrior_use, CWarrior* warrior_victim);
};// 武器派生类arrow
class CArrow :public CWepon {
public:// 构造函数CArrow(int _id, int _damage_value) :CWepon(_id) {damage_value = _damage_value;}// 使用属性virtual void use_attribute(CWarrior* warrior_use, CWarrior* warrior_victim);
};// 武器派生类bomb
class CBomb :public CWepon {
public:// 构造函数CBomb(int _id) :CWepon(_id) {// -1表示攻击力无限大damage_value = -1;}virtual void use_attribute(int city_num, int time_now, CWarrior* warrior_use, CWarrior* warrior_victim);
};class CCity;
// 武士类
class CWarrior {
public:string color;			// 所属阵营string name;			// 所属种类int id;					// 编号int life_value;			// 生命值int damage_value;		// 攻击力int wepon_num_total;	// 拥有的武器总数int has_shoot;			// 是否放过弓箭在该小时的35分放过弓箭:0表示未放过弓箭,-1表示放过弓箭,1表示放过弓箭且射死敌方CWepon* wepon[WEPON_MAX_NUM];			// 拥有的武器// 构造函数CWarrior(string _color, string _name, int _id, int _life_value, int _damage_value) :color(_color), name(_name), id(_id), life_value(_life_value), damage_value(_damage_value), wepon_num_total(0), has_shoot(0) {// 初始化拥有的武器未空for (int i = 0; i < WEPON_MAX_NUM; ++i) {wepon[i] = NULL;}}// 武士降生时获取初始武器void get_wepon_initial(int wepon_id) {CWepon* ptr_wepon = NULL;if (wepon_id == 0) {ptr_wepon = new CSword(wepon_id, WARRIOR_DAMAGE[name]);if (ptr_wepon->damage_value == 0) {// 如果初试获得的sword攻击力为0,则视为武士没有sworddelete ptr_wepon;ptr_wepon = NULL;}}else if (wepon_id == 1) {ptr_wepon = new CBomb(wepon_id);}else if (wepon_id == 2) {ptr_wepon = new CArrow(wepon_id, ARROW_DAMAGE);}// 为武士装备武器if (ptr_wepon != NULL) {wepon[wepon_num_total++] = ptr_wepon;}}// 更新自身拥有的武器总数即各种武器数量void update_wepon_num() {wepon_num_total = 0;for (int i = 0; i < WEPON_MAX_NUM; ++i) {if (wepon[i] != NULL) {++wepon_num_total;}}}// 对自身拥有的武器进行排序(编号从小到大)和更新武器数量void sort_wepon() {for (int i = WEPON_MAX_NUM - 2; i >= 0; --i) {for (int j = 0; j <= i; ++j) {if ((wepon[j] == NULL && wepon[j + 1] != NULL) || (wepon[j] != NULL && wepon[j + 1] != NULL && *wepon[j] > *wepon[j + 1])) {CWepon* tmp = wepon[j + 1];wepon[j + 1] = wepon[j];wepon[j] = tmp;}}}update_wepon_num();}// 报告自身的武器情况void print_wepon_info(int time_now) {int arrow_use_time = 0, bomb_num = 0, sword_damage = 0;for (int i = 0; i < WEPON_MAX_NUM; ++i) {if (wepon[i] != NULL) {if (wepon[i]->name == "sword")sword_damage = wepon[i]->damage_value;if (wepon[i]->name == "bomb")bomb_num = 1;if (wepon[i]->name == "arrow")arrow_use_time = wepon[i]->use_time;}}if (!arrow_use_time && !bomb_num && !sword_damage) {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << color << " " << name << " " << id<< " has no weapon";}else {int flag_first = 0, flag_second = 0;cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << color << " " << name << " " << id << " has ";if (arrow_use_time) {flag_first = 1;cout << "arrow(" << arrow_use_time << ")";}if (bomb_num && flag_first) {flag_second = 1;cout << ",bomb";}else if (bomb_num && !flag_first) {flag_second = 1;cout << "bomb";}if (sword_damage && (flag_first || flag_second)) {cout << ",sword(" << sword_damage << ")";}else if (sword_damage && !flag_first && !flag_second) {cout << "sword(" << sword_damage << ")";}}cout << endl;}// 放箭,成功放箭返回true,无箭可放返回falsevoid use_arrow(int time_now, CWarrior* warrior_victim) {int arrow_position = -1;for (int i = 0; i < WEPON_MAX_NUM; ++i) {if (wepon[i] != NULL && wepon[i]->name == "arrow") {arrow_position = i;break;}}if (arrow_position == -1) return;else has_shoot = -1;wepon[arrow_position]->use_attribute(this, warrior_victim);// 若成功放箭,则判断使用后弓箭的状态if (wepon[arrow_position]->use_time == 0) {delete wepon[arrow_position];wepon[arrow_position] = NULL;}return;}// 若有bomb,返回bomb在武器中的位置,若没有则返回-1int bomb_num() {int num = -1;for (int i = 0; i < WEPON_MAX_NUM; ++i) {if (wepon[i] != NULL && wepon[i]->name == "bomb") {num = i;break;}}return num;}// 若有sword,返回sword在武器中的位置,若没有则返回-1int sword_num() {int num = -1;for (int i = 0; i < WEPON_MAX_NUM; ++i) {if (wepon[i] != NULL && wepon[i]->name == "sword") {num = i;break;}}return num;}// 战斗获胜属性virtual void win_fight(int city_num, int time_now, CWarrior* loser) {}// 战斗平局属性virtual void peace_fight() {}// 进攻,time_flag为1表示主动进攻,为-1表示反击void attack(int city_num, int time_now, CWarrior* warrior_against, int time_flag) {// ninja被挨打不会反击if (name == "ninja" && time_flag == -1) return;// 为进攻事件进行输出if (time_flag == 1) {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << color << " " << name << " " << id << " attacked " << warrior_against->color<< " " << warrior_against->name << " " << warrior_against->id << " in city " << city_num << " with " << life_value<< " elements and force " << damage_value << endl;}else if (time_flag == -1 && name != "ninja") {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << color << " " << name << " " << id << " fought back against " << warrior_against->color<< " " << warrior_against->name << " " << warrior_against->id << " in city " << city_num << endl;}int sword_id = sword_num();if (sword_id != -1) {wepon[sword_id]->use_attribute(this, warrior_against);// 判断武器状态if (wepon[sword_id]->damage_value == 0) {delete wepon[sword_id];wepon[sword_id] = NULL;}}if (time_flag == 1)warrior_against->life_value -= damage_value;else if (time_flag == -1)warrior_against->life_value -= damage_value * 1 / 2;return;}// 若是lion,若在一场战斗中没有战死,且为进攻方,则可以进行欢呼virtual void dragon_live(int city_num, int time_now, CCity* ptr_city_list) {}// 虚析构函数virtual ~CWarrior() {for (int i = 0; i < WEPON_MAX_NUM; ++i) {if (wepon[i] != NULL)delete wepon[i];}}
};// 武士派生类dragon
class CDragon :public CWarrior {
public:double morale;					// 士气// 构造函数CDragon(string _color, string _name, int _id, int _life_value, int _damage_value, double _morale) :CWarrior(_color, _name, _id, _life_value, _damage_value), morale(_morale) {// 装备初始武器get_wepon_initial(id % 3);}// 欢呼void dragon_yell(int time_now, int city_num) {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << color << " " << name<< " " << id << " yelled in city " << city_num << endl;}// 战胜属性virtual void win_fight(int city_num, int time_now, CWarrior* loser) {morale += DRAGON_MORALE_CHANGE;}// 平局属性virtual void peace_fight() {morale -= DRAGON_MORALE_CHANGE;}// dragon获胜或平局进行欢呼virtual void dragon_live(int city_num, int time_now, CCity* ptr_city_list);
};// 武士派生类ninja
class CNinja :public CWarrior {
public:// 构造函数CNinja(string _color, string _name, int _id, int _life_value, int _damage_value) :CWarrior(_color, _name, _id, _life_value, _damage_value) {// 装备初始武器get_wepon_initial(id % 3);get_wepon_initial((id + 1) % 3);}
};// 武士派生类iceman
class CIceman :public CWarrior {
public:int step;						// 到达城市时记录一共走了几步// 构造函数CIceman(string _color, string _name, int _id, int _life_value, int _damage_value) :CWarrior(_color, _name, _id, _life_value, _damage_value), step(0) {// 装备初始武器get_wepon_initial(id % 3);}// 前进属性(攻击力变化,注意对sword的影响)void advance_attribute() {if ((++step) % 2 == 0) {// 每前进2步,在第二步完成时,生命值减少,攻击力增加life_value -= ICEMAN_LIFE_REDUCE;if (life_value <= 0)life_value = 1;damage_value += ICEMAN_DAMAGE_INCREASE;}}
};// 武士派生类lion
class CLion :public CWarrior {
public:int loyalty;							// 忠诚度CLion(string _color, string _name, int _id, int _life_value, int _damage_value, int _loyalty) :CWarrior(_color, _name, _id, _life_value, _damage_value), loyalty(_loyalty) {}virtual void peace_fight() {// 经过一场未能杀死敌人的战斗,忠诚度就降低loyalty -= LION_LOAYLTY_REDUCE;}
};// 武士派生类wolf
class CWolf :public CWarrior {
public:// 构造函数CWolf(string _color, string _name, int _id, int _life_value, int _damage_value) :CWarrior(_color, _name, _id, _life_value, _damage_value) {}// 若杀死敌人则获取敌人的武器(武器易主,注意对sword的影响)void grab_wepon(CWarrior* warrior_victim) {// 先对自身武器进行排序sort_wepon();int j;for (int i = 0; i < WEPON_MAX_NUM && wepon_num_total < WEPON_MAX_NUM; ++i) {if (warrior_victim->wepon[i] != NULL) {for (j = 0; j < wepon_num_total; ++j) {if (warrior_victim->wepon[i]->name == wepon[j]->name)break;}// 若不存在该类型武器则缴获,若缴获sword且还未使用过if (j == wepon_num_total) {// 若缴获sword且还未使用过,则更新其初始攻击力//if (warrior_victim->wepon[i]->name == "sword" && warrior_victim->wepon[i]->use_time == WEPON_USE_TIME["sword"]) {//	warrior_victim->wepon[i]->damage_value = damage_value * SWORD_DAMAGE;//}wepon[wepon_num_total++] = warrior_victim->wepon[i];warrior_victim->wepon[i] = NULL;--warrior_victim->wepon_num_total;}}}}virtual void win_fight(int city_num, int time_now, CWarrior* loser) {grab_wepon(loser);}
};// 城市类
class CCity {
public:CWarrior* warrior_red;			// 位于该城市的红方武士指针CWarrior* warrior_red_tmp;		// 辅助红方武士移动的指针CWarrior* warrior_blue;			// 位于该城市的蓝方武士指针int life_element;				// 城市中产生的生命元int red_win;					// 红方连赢次数int blue_win;					// 蓝方连赢次数int flag;						// 0代表无旗,1代表红旗,-1代表蓝旗// 构造函数CCity() :warrior_red(NULL), warrior_red_tmp(NULL), warrior_blue(NULL), life_element(0), red_win(0), blue_win(0), flag(0) {}// 判断该城市的旗帜是否改变void flag_change(int time_now, int city_num) {if (warrior_red->life_value > 0 && warrior_blue->life_value <= 0) {// 红方获胜blue_win = 0;if (flag == 1)return;if (++red_win == 2) {flag = 1;cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " red flag raised in city " << city_num << endl;}}if (warrior_blue->life_value > 0 && warrior_red->life_value <= 0) {// 蓝方获胜red_win = 0;if (flag == -1)return;if (++blue_win == 2) {flag = -1;cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " blue flag raised in city " << city_num << endl;}}if (warrior_red->life_value > 0 && warrior_blue->life_value > 0) {// 平局或使用bomb不会影响旗帜red_win = 0;blue_win = 0;}}// 析构函数~CCity() {if (warrior_red != NULL)delete warrior_red;if (warrior_blue != NULL)delete warrior_blue;}
};// 司令部类
class CHeadquarter {
public:string color;				// 所属派别int life_element;			// 生命元总数int total_num;				// 拥有的武士数量int make_num;				// 下一个要制造的武士编号int enemy_num;				// 到达该司令部的敌人数string make_sort[5];		// 制造武士的顺序// 构造函数CHeadquarter(string _color, int _life_element) :color(_color), life_element(_life_element), total_num(0), make_num(0), enemy_num(0) {if (_color == "red") {string _make_sort[5] = { "iceman", "lion", "wolf", "ninja", "dragon" };for (int i = 0; i < 5; ++i) make_sort[i] = _make_sort[i];}else if (_color == "blue") {string _make_sort[5] = { "lion","dragon","ninja","iceman","wolf" };for (int i = 0; i < 5; ++i) make_sort[i] = _make_sort[i];}}// 制造武士并投放城市void make_warrior(int time_now, CCity* ptr_city_list) {using Func_Ptr = CWarrior * (CHeadquarter::*)(int);map<string, Func_Ptr> make_warrior_map = {{"dragon", &CHeadquarter::make_warrior_dragon},{"ninja", &CHeadquarter::make_warrior_ninja},{"iceman",&CHeadquarter::make_warrior_iceman},{"lion",&CHeadquarter::make_warrior_lion},{"wolf",&CHeadquarter::make_warrior_wolf}};string name = make_sort[make_num];int life_need = WARRIOR_LIFE[name];if (life_element >= life_need) {// 可以制造,更新司令部制造完武士后的状态life_element -= life_need;++total_num;if (++make_num == WARRIOR_KIND_NUM)make_num = 0;// 输出制造信息cout << setfill('0') << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << color<< " " << name << " " << total_num << " born" << endl;// 生成武士并放入投入司令部CWarrior* ptr_warrior = (this->*make_warrior_map[name])(life_need);if (color == "red") {ptr_city_list[0].warrior_red = ptr_warrior;}else ptr_city_list[CITY_NUM + 1].warrior_blue = ptr_warrior;}}// 制造武士wolfCWarrior* make_warrior_wolf(int life_need) {CWarrior* ptr_wolf = new CWolf(color, "wolf", total_num, life_need, WARRIOR_DAMAGE["wolf"]);return ptr_wolf;}// 制造武士lionCWarrior* make_warrior_lion(int life_need) {// 计算忠诚度int loyalty = life_element;CWarrior* ptr_lion = new CLion(color, "lion", total_num, life_need, WARRIOR_DAMAGE["lion"], loyalty);// 输出其忠诚度cout << "Its loyalty is " << loyalty << endl;return ptr_lion;}// 制造武士icemanCWarrior* make_warrior_iceman(int life_need) {CWarrior* ptr_iceman = new CIceman(color, "iceman", total_num, life_need, WARRIOR_DAMAGE["iceman"]);return ptr_iceman;}// 制造武士ninjaCWarrior* make_warrior_ninja(int life_need) {CWarrior* ptr_ninja = new CNinja(color, "ninja", total_num, life_need, WARRIOR_DAMAGE["ninja"]);return ptr_ninja;}// 制造武士dragonCWarrior* make_warrior_dragon(int life_need) {// 计算士气double morale = (double)life_element / (double)life_need;CWarrior* ptr_dragon = new CDragon(color, "dragon", total_num, life_need, WARRIOR_DAMAGE["dragon"], morale);cout << "Its morale is " << fixed << setprecision(2) << morale << endl;return ptr_dragon;}// 输出拥有的生命元数量void print_life_element_info(int time_now) {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << life_element<< " elements in " << color << " headquarter" << endl;}};void CSword::use_attribute(CWarrior* warrior_use, CWarrior* warrior_victim) {// 只造成等于sword攻击力的伤害值,磨损自身,use_time用来标志是否第一次使用swordwarrior_victim->life_value -= damage_value;// 不可以写成damage_value *= SWORD_ABRASE, 因为这样SWORD_ABRASE直接被转变成0damage_value = damage_value * SWORD_ABRASE;--use_time;
}void CArrow::use_attribute(CWarrior* warrior_use, CWarrior* warrior_victim) {// 造成伤害和减少一次使用次数warrior_victim->life_value -= damage_value;if (warrior_victim->life_value <= 0) {warrior_victim->life_value = 0;warrior_use->has_shoot = 1;}--use_time;
}void CBomb::use_attribute(int city_num, int time_now, CWarrior* warrior_use, CWarrior* warrior_victim) {// 双方的生命值都变为0warrior_use->life_value = 0;warrior_victim->life_value = 0;--use_time;// 输出事件信息 cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << warrior_use->color << " " << warrior_use->name << " " << warrior_use->id<< " used a bomb and killed " << warrior_victim->color << " " << warrior_victim->name << " " << warrior_victim->id << endl;
}void CDragon::dragon_live(int city_num, int time_now, CCity* ptr_city_list) {// 一场主动进攻的战斗结束时,没有被战死,则进行欢呼if (color == "red" && morale > DRAGON_MORALE_YELL) {if (ptr_city_list[city_num].flag == 1 || (ptr_city_list[city_num].flag == 0 && city_num % 2 == 1)) {dragon_yell(time_now, city_num);}}else if (color == "blue" && morale > DRAGON_MORALE_YELL) {if (ptr_city_list[city_num].flag == -1 || (ptr_city_list[city_num].flag == 0 && city_num % 2 == 0)) {dragon_yell(time_now, city_num);}}
}// 接收数据,初始化信息
void cin_data() {// 接收生命元、城市、忠诚度变化、时间范围值cin >> LIFE_ELEMENT >> CITY_NUM >> ARROW_DAMAGE >> LION_LOAYLTY_REDUCE >> TIME_NUM;// 接收每种武士的生命值int life_value;for (int i = 0; i < WARRIOR_KIND_NUM; ++i) {cin >> life_value;WARRIOR_LIFE[WARRIOR_CIN_SORT[i]] = life_value;}// 接收每种武士的攻击力int warrior_damage;for (int i = 0; i < WARRIOR_KIND_NUM; ++i) {cin >> warrior_damage;WARRIOR_DAMAGE[WARRIOR_CIN_SORT[i]] = warrior_damage;}return;
}// 判断武士是否是lion,若是其是否会逃跑
bool Lion_ran_second(int city_num, int time_now, CWarrior* ptr_warrior) {if (ptr_warrior != NULL && ptr_warrior->name == "lion") {CLion* ptr_warrior_lion = dynamic_cast<CLion*>(ptr_warrior);if (ptr_warrior_lion->loyalty <= 0) {// 在己方司令部可能逃跑,在地方司令部不会逃跑if ((ptr_warrior_lion->color == "red" && city_num != CITY_NUM + 1) || (ptr_warrior_lion->color == "blue" && city_num != 0)) {// 输出逃跑信息,释放指针cout << setfill('0') << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60<< " " << ptr_warrior_lion->color << " lion " << ptr_warrior_lion->id << " ran away" << endl;delete ptr_warrior_lion;ptr_warrior_lion = NULL;ptr_warrior = NULL;return true;}}}return false;
}// lion逃跑事件
void Lion_ran(int city_num, int time_now, CCity* ptr_city_list) {// 先判断红方CWarrior* ptr_warrior = ptr_city_list[city_num].warrior_red;bool run_can = Lion_ran_second(city_num, time_now, ptr_warrior);if (run_can)ptr_city_list[city_num].warrior_red = NULL;// 再判断蓝方ptr_warrior = ptr_city_list[city_num].warrior_blue;run_can = Lion_ran_second(city_num, time_now, ptr_warrior);if (run_can)ptr_city_list[city_num].warrior_blue = NULL;
}// 触发武士相应的前进属性,输出前进信息,判断是否占领司令部:-1红方被占,0双方未被占,1蓝方被占
int march_info(int city_num, int time_now, CWarrior* ptr_warrior, CHeadquarter& red_quarter, CHeadquarter& blue_quarter) {// 这里的city_num表示的是到达城市的编号if (ptr_warrior->name == "iceman") {CIceman* ptr_iceman = dynamic_cast<CIceman*>(ptr_warrior);ptr_iceman->advance_attribute();}if (ptr_warrior->color == "blue" && city_num == 0) {// 抵达司令部cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << ptr_warrior->color << " " << ptr_warrior->name<< " " << ptr_warrior->id << " reached red headquarter with " << ptr_warrior->life_value<< " elements and force " << ptr_warrior->damage_value << endl;if (++red_quarter.enemy_num == 2) {// 占领红方司令部return -1;}}else if (ptr_warrior->color == "red" && city_num == CITY_NUM + 1) {// 抵达司令部cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << ptr_warrior->color << " " << ptr_warrior->name<< " " << ptr_warrior->id << " reached blue headquarter with " << ptr_warrior->life_value<< " elements and force " << ptr_warrior->damage_value << endl;if (++blue_quarter.enemy_num == 2) {// 占领蓝方司令部return 1;}}else {// 双方司令部还未占领cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << ptr_warrior->color << " " << ptr_warrior->name<< " " << ptr_warrior->id << " marched to city " << city_num << " with " << ptr_warrior->life_value<< " elements and force " << ptr_warrior->damage_value << endl;}return 0;
}// 双方士兵前进,对于红方来说city_num是出发的城市编号,对于蓝方来说city_num是到达的城市编号
int march_city(int city_num, int time_now, CCity* ptr_city_list, CHeadquarter& red_quarter, CHeadquarter& blue_quarter) {int result = 0;if (ptr_city_list[city_num + 1].warrior_blue != NULL) {// 蓝方武士向西前进ptr_city_list[city_num].warrior_blue = ptr_city_list[city_num + 1].warrior_blue;ptr_city_list[city_num + 1].warrior_blue = NULL;CWarrior* ptr_warrior = ptr_city_list[city_num].warrior_blue;// 触发武士前进属性,输出武士前进信息int tmp_result = march_info(city_num, time_now, ptr_warrior, red_quarter, blue_quarter);if (tmp_result == -1) {// 红方司令部被占领result = -1;cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " red headquarter was taken" << endl;// 这里千万不能直接return one_win,因为一旦红方被占领,若红司令部有武士要前进到city1的话就得不到输出}}if (ptr_city_list[city_num].warrior_red_tmp != NULL) {// 红方武士向东前进ptr_city_list[city_num + 1].warrior_red = ptr_city_list[city_num].warrior_red_tmp;ptr_city_list[city_num].warrior_red_tmp = NULL;CWarrior* ptr_warrior = ptr_city_list[city_num + 1].warrior_red;// 触发武士前进属性,输出武士前进信息int tmp_result = march_info(city_num + 1, time_now, ptr_warrior, red_quarter, blue_quarter);if (tmp_result == 1) {// 输出蓝方被占领result = 1;cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " blue headquarter was taken" << endl;}}return result;
}// 若某个城市只有一个武士,则武士取走生命元传回司令部
void take_element(int city_num, int time_now, CCity* ptr_city_list, CHeadquarter& red_quarter, CHeadquarter& blue_quarter) {CWarrior* warrior_red = ptr_city_list[city_num].warrior_red;CWarrior* warrior_blue = ptr_city_list[city_num].warrior_blue;CWarrior* warrior_take = NULL;int city_element = ptr_city_list[city_num].life_element;bool take_away = false;// 红方取走if (warrior_red != NULL && warrior_blue == NULL) {red_quarter.life_element += city_element;warrior_take = warrior_red;take_away = true;}// 蓝方取走else if (warrior_blue != NULL && warrior_red == NULL) {blue_quarter.life_element += city_element;warrior_take = warrior_blue;take_away = true;}// 输出事件if (take_away) {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << warrior_take->color << " " << warrior_take->name<< " " << warrior_take->id << " earned " << city_element << " elements for his headquarter" << endl;ptr_city_list[city_num].life_element = 0;}return;
}// 使用arrow事件
void shoot_arrow(int city_num, int time_now, CCity* ptr_city_list) {CWarrior* warrior_red = ptr_city_list[city_num].warrior_red;CWarrior* warrior_blue = ptr_city_list[city_num + 1].warrior_blue;if (warrior_red != NULL && warrior_blue != NULL && warrior_red->life_value > 0 && warrior_blue->life_value > 0) {// 放箭warrior_red->use_arrow(time_now, warrior_blue);warrior_blue->use_arrow(time_now, warrior_red);}
}// 判断是否放箭,以及放箭是否射死敌人
void shoot_result_second(int city_num, int time_now, CWarrior* warrior, CWarrior* enemy) {if (enemy != NULL && warrior->has_shoot == 1) {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << warrior->color << " " << warrior->name<< " " << warrior->id << " shot and killed " << enemy->color << " " << enemy->name<< " " << enemy->id << endl;warrior->has_shoot = 0;}else if (enemy != NULL && warrior->has_shoot == -1) {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << warrior->color << " " << warrior->name<< " " << warrior->id << " shot" << endl;warrior->has_shoot = 0;}return;
}// 输出放箭事件结果(因为放箭事件算发生在箭发出的城市,因此在所有放箭结束后再来判定和输出)
void shoot_result(int city_num, int time_now, CCity* ptr_city_list) {CWarrior* warrior_red = ptr_city_list[city_num].warrior_red;CWarrior* warrior_blue = ptr_city_list[city_num].warrior_blue;CWarrior* enemy_against = NULL;// 若此时战士血量小于等于0,则说明其被弓箭射死,被射死的武士暂时不被释放,因为在40分战斗开始前还要进行判断if (warrior_red != NULL) {enemy_against = ptr_city_list[city_num + 1].warrior_blue;shoot_result_second(city_num, time_now, warrior_red, enemy_against);}if (warrior_blue != NULL) {enemy_against = ptr_city_list[city_num - 1].warrior_red;shoot_result_second(city_num, time_now, warrior_blue, enemy_against);}return;
}// attack_flag为1代表attacker是主动进攻方,attack_flag为-1表示attacker是反击方,炸弹在victim手上
void throw_bomb_second(int city_num, int time_now, CWarrior* attacker, CWarrior* victim, int victim_bomb_num, int attack_flag) {// 如果victim主动进攻时能够杀死attacker,那么就不存在反击一说,因此先行判断if (attack_flag == -1) {int victim_damage = victim->damage_value;int victim_sword = victim->sword_num();int attacker_life = attacker->life_value;attacker_life -= victim_damage;if (victim_sword != -1)attacker_life -= victim->wepon[victim_sword]->damage_value;if (attacker_life <= 0)return;}int victim_life = victim->life_value;int attacker_damage = attacker->damage_value;// 反击方攻击力取自身攻击力的一半if (attack_flag == -1)attacker_damage = attacker_damage * 1 / 2;victim_life -= attacker_damage;int attacker_sword = attacker->sword_num();if (attacker_sword != -1)victim_life -= attacker->wepon[attacker_sword]->damage_value;if (victim_life <= 0)victim->wepon[victim_bomb_num]->use_attribute(city_num, time_now, victim, attacker);return;
}// 使用bomb事件
void throw_bomb(int city_num, int time_now, CCity* ptr_city_list) {CWarrior* warrior_red = ptr_city_list[city_num].warrior_red;CWarrior* warrior_blue = ptr_city_list[city_num].warrior_blue;if (warrior_red != NULL && warrior_blue != NULL && warrior_red->life_value > 0 && warrior_blue->life_value > 0) {// 若有bomb则获取bomb在武器数组中的位置,没有bomb位置将返回-1int red_bomb_num = warrior_red->bomb_num();int blue_bomb_num = warrior_blue->bomb_num();// 红方有炸弹的情况下进行判断是否使用:分为蓝方是进攻方和蓝方是反击方if (red_bomb_num != -1) {if (ptr_city_list[city_num].flag == -1 || (ptr_city_list[city_num].flag == 0 && city_num % 2 == 0)) {// 若蓝方是进攻方(插蓝旗,以及编号为偶数的无旗城市)throw_bomb_second(city_num, time_now, warrior_blue, warrior_red, red_bomb_num, 1);}else if (warrior_blue->name != "ninja" && (ptr_city_list[city_num].flag == 1 || (ptr_city_list[city_num].flag == 0 && city_num % 2 == 1))) {// 若蓝方是反击方(插红旗,以及编号为奇数的无旗城市)且不是ninja,因为ninja不会反击throw_bomb_second(city_num, time_now, warrior_blue, warrior_red, red_bomb_num, -1);}}// 蓝方有炸弹的情况下进行判断是否使用,若红方已经启用炸弹就不用判断了if (warrior_red->life_value > 0 && warrior_blue->life_value > 0 && blue_bomb_num != -1) {if (ptr_city_list[city_num].flag == 1 || (ptr_city_list[city_num].flag == 0 && city_num % 2 == 1)) {// 若红方是进攻方(插红旗,以及编号为奇数的无旗城市)throw_bomb_second(city_num, time_now, warrior_red, warrior_blue, blue_bomb_num, 1);}else if (warrior_red->name != "ninja" && (ptr_city_list[city_num].flag == -1 || (ptr_city_list[city_num].flag == 0 && city_num % 2 == 0))) {// 若红方是反击方且不是ninjathrow_bomb_second(city_num, time_now, warrior_red, warrior_blue, blue_bomb_num, -1);}}}// 有可能双方都被弓箭射死了,也有可能是双方使用bomb同归于尽了,此时可以释放if (warrior_red != NULL && warrior_blue != NULL && warrior_red->life_value <= 0 && warrior_blue->life_value <= 0) {delete warrior_red;delete warrior_blue;ptr_city_list[city_num].warrior_red = NULL;ptr_city_list[city_num].warrior_blue = NULL;}
}// 针对在战斗开始前,attcker是在这次攻击中进攻的一方,attack_flag为1代表此次为主动进攻,为-1表示反击
bool fight_against_second(int city_num, int time_now, CWarrior* attcker, CWarrior* against, CCity* ptr_city_list, int attack_flag) {attcker->attack(city_num, time_now, against, attack_flag);if (against->life_value <= 0) {cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << against->color << " " << against->name << " "<< against->id << " was killed in city " << city_num << endl;// 触发胜利属性attcker->win_fight(city_num, time_now, against);return true;}return false;
}// 战斗事件
void fight_against(int city_num, int time_now, CCity* ptr_city_list) {CWarrior* warrior_red = ptr_city_list[city_num].warrior_red;CWarrior* warrior_blue = ptr_city_list[city_num].warrior_blue;if (warrior_red != NULL && warrior_blue != NULL) {// 有一方可能已经被弓箭射死if (warrior_red->life_value > 0 && warrior_blue->life_value <= 0) {// 暂且不释放,输出司令部获取城市生命元信息(实际待奖励后再获取)warrior_red->win_fight(city_num, time_now, warrior_blue);if (warrior_red->name == "dragon")warrior_red->dragon_live(city_num, time_now, ptr_city_list);cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << warrior_red->color << " " << warrior_red->name<< " " << warrior_red->id << " earned " << ptr_city_list[city_num].life_element << " elements for his headquarter" << endl;// 刷新旗帜ptr_city_list[city_num].flag_change(time_now, city_num);}else if (warrior_blue->life_value > 0 && warrior_red->life_value <= 0) {warrior_blue->win_fight(city_num, time_now, warrior_red);if (warrior_blue->name == "dragon")warrior_blue->dragon_live(city_num, time_now, ptr_city_list);cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << warrior_blue->color << " " << warrior_blue->name<< " " << warrior_blue->id << " earned " << ptr_city_list[city_num].life_element << " elements for his headquarter" << endl;ptr_city_list[city_num].flag_change(time_now, city_num);}else if (warrior_red->life_value > 0 && warrior_blue->life_value > 0) {// 先记录战斗前的生命值int life_red = warrior_red->life_value, life_blue = warrior_blue->life_value;if (ptr_city_list[city_num].flag == 1 || (ptr_city_list[city_num].flag == 0 && city_num % 2 == 1)) {// 红方进攻,若蓝方存活则反击bool one_win = fight_against_second(city_num, time_now, warrior_red, warrior_blue, ptr_city_list, 1);if (one_win == false)fight_against_second(city_num, time_now, warrior_blue, warrior_red, ptr_city_list, -1);}else {// 蓝方进攻,若红方存活则反击bool one_win = fight_against_second(city_num, time_now, warrior_blue, warrior_red, ptr_city_list, 1);if (one_win == false)fight_against_second(city_num, time_now, warrior_red, warrior_blue, ptr_city_list, -1);}CWarrior* winner = NULL;CWarrior* loser = NULL;if (warrior_red->life_value > 0 && warrior_blue->life_value <= 0) {winner = warrior_red;loser = warrior_blue;}else if (warrior_blue->life_value > 0 && warrior_red->life_value <= 0) {winner = warrior_blue;loser = warrior_red;}else if (warrior_blue->life_value > 0 && warrior_red->life_value > 0) {// 平局,触发武士平局属性warrior_red->peace_fight();if (warrior_red->name == "dragon")warrior_red->dragon_live(city_num, time_now, ptr_city_list);warrior_blue->peace_fight();if (warrior_blue->name == "dragon")warrior_blue->dragon_live(city_num, time_now, ptr_city_list);}if (winner) {// 胜方为dragon,有可能触发其欢呼特性if (winner->name == "dragon")winner->dragon_live(city_num, time_now, ptr_city_list);// 若败方为lion,则触发其战死特性if (loser->name == "lion" && loser->color == "red")winner->life_value += life_red;else if (loser->name == "lion" && loser->color == "blue")winner->life_value += life_blue;cout << setw(3) << time_now / 60 << ":" << setw(2) << time_now % 60 << " " << winner->color << " " << winner->name<< " " << winner->id << " earned " << ptr_city_list[city_num].life_element << " elements for his headquarter" << endl;}// 刷新旗帜ptr_city_list[city_num].flag_change(time_now, city_num);}}
}// 司令部对城市中战斗获胜的武士进行奖励,inspire_flag为1表示对红方武士进行奖赏,inspire_flag为-1表示对蓝方武士进行奖赏
void inspire_warrior(int city_num, CCity* ptr_city_list, CHeadquarter& red_quarter, CHeadquarter& blue_quarter, int inspire_flag) {CWarrior* warrior_red = ptr_city_list[city_num].warrior_red;CWarrior* warrior_blue = ptr_city_list[city_num].warrior_blue;if (inspire_flag == 1) {if (warrior_red != NULL && warrior_blue != NULL && warrior_red->life_value > 0 && warrior_blue->life_value <= 0) {// 红方司令部对红武士进行奖赏if (red_quarter.life_element >= HEADQUARTER_INSPIRE) {warrior_red->life_value += HEADQUARTER_INSPIRE;red_quarter.life_element -= HEADQUARTER_INSPIRE;}}}else if (inspire_flag == -1) {if (warrior_red != NULL && warrior_blue != NULL && warrior_blue->life_value > 0 && warrior_red->life_value <= 0) {if (blue_quarter.life_element >= HEADQUARTER_INSPIRE) {warrior_blue->life_value += HEADQUARTER_INSPIRE;blue_quarter.life_element -= HEADQUARTER_INSPIRE;}}}return;
}// 清扫战场
void clean_city(int city_num, CCity* ptr_city_list) {CWarrior* warrior_red = ptr_city_list[city_num].warrior_red;CWarrior* warrior_blue = ptr_city_list[city_num].warrior_blue;if (warrior_red != NULL && warrior_red->life_value <= 0) {delete warrior_red;ptr_city_list[city_num].warrior_red = NULL;}if (warrior_blue != NULL && warrior_blue->life_value <= 0) {delete warrior_blue;ptr_city_list[city_num].warrior_blue = NULL;}return;
}// 司令部从打了胜仗的城市回收生命元
void gain_life_element(int city_num, int time_now, CCity* ptr_city_list, CHeadquarter& red_quarter, CHeadquarter& blue_quarter) {CWarrior* warrior_red = ptr_city_list[city_num].warrior_red;CWarrior* warrior_blue = ptr_city_list[city_num].warrior_blue;CWarrior* warrior_take = NULL;int life_element = ptr_city_list[city_num].life_element;if (warrior_red != NULL && warrior_blue == NULL && life_element > 0) {red_quarter.life_element += life_element;ptr_city_list[city_num].life_element = 0;}else if (warrior_blue != NULL && warrior_red == NULL && life_element > 0) {blue_quarter.life_element += life_element;ptr_city_list[city_num].life_element = 0;}return;
}// 终极版
void make_war(int case_num) {// 开始测试,接收输出,并初始化信息cin_data();// 输出测试样例组好cout << "Case " << case_num << ":" << endl;// 创建红蓝司令部和城市,将两方司令部也算作城市CHeadquarter red_quarter("red", LIFE_ELEMENT), blue_quarter("blue", LIFE_ELEMENT);CCity* ptr_city_list = new CCity[CITY_NUM + 2];int time_now = 0;cout << setfill('0');while (time_now <= TIME_NUM) {if (time_now % 60 == 0) {// 武士降生red_quarter.make_warrior(time_now, ptr_city_list);blue_quarter.make_warrior(time_now, ptr_city_list);time_now += 5;if (time_now > TIME_NUM)break;}if (time_now % 60 == 5) {// 忠诚度下降到0及以下的lion逃跑for (int i = 0; i < CITY_NUM + 2; ++i) {Lion_ran(i, time_now, ptr_city_list);}time_now += 5;if (time_now > TIME_NUM)break;}if (time_now % 60 == 10) {bool one_win = false;// 进军之前,先将所有城市中的红武士指针移动到辅助位置上for (int i = 0; i < CITY_NUM + 1; ++i) {ptr_city_list[i].warrior_red_tmp = ptr_city_list[i].warrior_red;ptr_city_list[i].warrior_red = NULL;}// 双方武士前进,注意触发iceman的前进属性for (int i = 0; i < CITY_NUM + 1; ++i) {int march_result = march_city(i, time_now, ptr_city_list, red_quarter, blue_quarter);if (march_result != 0)one_win = true;}// 确保和司令部占领同时发生的事情得到输出,因此不要在循环里面返回if (one_win)return;time_now += 10;if (time_now > TIME_NUM)break;}if (time_now % 60 == 20) {// 每个城市产出10个生命元,生命元留着城市,直到被武士取走for (int i = 1; i < CITY_NUM + 1; ++i) {ptr_city_list[i].life_element += 10;}time_now += 10;if (time_now > TIME_NUM)break;}if (time_now % 60 == 30) {// 若某个城市只有一个武士,则武士取走生命元传回司令部for (int i = 1; i < CITY_NUM + 1; ++i) {take_element(i, time_now, ptr_city_list, red_quarter, blue_quarter);}time_now += 5;if (time_now > TIME_NUM)break;}if (time_now % 60 == 35) {// 拥有arrow的武士放箭for (int i = 1; i < CITY_NUM; ++i) {shoot_arrow(i, time_now, ptr_city_list);}// 输出放箭的结果for (int i = 1; i < CITY_NUM + 1; ++i) {shoot_result(i, time_now, ptr_city_list);}time_now += 3;if (time_now > TIME_NUM)break;}if (time_now % 60 == 38) {// 评估拥有bomb的武士是否会使用bombfor (int i = 1; i < CITY_NUM + 1; ++i) {throw_bomb(i, time_now, ptr_city_list);}time_now += 2;if (time_now > TIME_NUM)break;}if (time_now % 60 == 40) {// 在有两个武士的城市,会发生战斗for (int i = 1; i < CITY_NUM + 1; ++i) {fight_against(i, time_now, ptr_city_list);}// 红方司令部对获胜的武士进行奖励for (int i = CITY_NUM; i >= 1; --i) {inspire_warrior(i, ptr_city_list, red_quarter, blue_quarter, 1);}// 蓝方司令部对获胜的武士进行奖赏for (int i = 1; i < CITY_NUM + 1; ++i) {inspire_warrior(i, ptr_city_list, red_quarter, blue_quarter, -1);}// 清扫战场for (int i = 1; i < CITY_NUM + 1; ++i) {clean_city(i, ptr_city_list);}// 双方司令部实际获取各个城市的生命元,信息也在奖赏前输出for (int i = 1; i < CITY_NUM + 1; ++i) {gain_life_element(i, time_now, ptr_city_list, red_quarter, blue_quarter);}time_now += 10;if (time_now > TIME_NUM)break;}if (time_now % 60 == 50) {// 司令部报告它拥有的武器情况red_quarter.print_life_element_info(time_now);blue_quarter.print_life_element_info(time_now);time_now += 5;if (time_now > TIME_NUM)break;}if (time_now % 60 == 55) {// 每个武士报告其拥有的武器情况(到达敌方司令部的武士也要报告)for (int i = 0; i < CITY_NUM + 2; ++i) {if (ptr_city_list[i].warrior_red != NULL)ptr_city_list[i].warrior_red->print_wepon_info(time_now);}for (int i = 0; i < CITY_NUM + 2; ++i) {if (ptr_city_list[i].warrior_blue != NULL)ptr_city_list[i].warrior_blue->print_wepon_info(time_now);}time_now += 5;if (time_now > TIME_NUM)break;}}delete[]ptr_city_list;return;
}int main() {// 接收测试样例数int case_total, case_num = 0;cin >> case_total;while (case_num != case_total) {++case_num;make_war(case_num);}return 0;
}

这篇关于魔兽世界之四:终极版(北京大学MOOC 程序设计与算法(三) C++面向对象程序设计)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095050

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

揭秘世界上那些同时横跨两大洲的国家

我们在《世界人口过亿的一级行政区分布》盘点全球是那些人口过亿的一级行政区。 现在我们介绍五个横跨两州的国家,并整理七大洲和这些国家的KML矢量数据分析分享给大家,如果你需要这些数据,请在文末查看领取方式。 世界上横跨两大洲的国家 地球被分为七个大洲分别是亚洲、欧洲、北美洲、南美洲、非洲、大洋洲和南极洲。 七大洲示意图 其中,南极洲是无人居住的大陆,而其他六个大洲则孕育了众多国家和

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象