红色警戒终极版
Description
在一局红色警戒游戏中,你代表的是英国势力,此时你迫切需要生产坦克来应对敌人的进攻,坦克分为灰熊坦克、幻影坦克、光棱坦克、天启坦克四种,价格分别为600、1000、1200、1750,生产时间分别为1、2、4、6单位时间,灰熊坦克为基础坦克无特殊属性,只有普通攻击、防御、血量三种属性,其余坦克除基础属性外,幻影坦克有变形属性,可幻化成为树木,光棱坦克有光棱攻击属性,不采用普通攻击属性,天启坦克有更强的防御能力。目前你手中共有m金币,坦克建造顺序为灰熊、幻影、光棱、天启作为循环,注意一个例子剩余金钱不够用于生产天启坦克,那么将开始下一循环,尝试生产灰熊,如果任何坦克都不能开始生产,立刻中断生产。
下面是不同坦克所具有的属性。每次攻击造成的伤害计算公式为:己方坦克攻击力减去敌方防御属性。坦克每次受到的伤害将从其血量中扣去,坦克受到某次伤害后血量小于等于0时,坦克被消灭。
其中幻影具有变形属性,它每次被击中后,同一回合内下次被攻击必定可以躲避而不受伤害(普通攻击、光棱攻击都可以躲避);光棱坦克攻击坦克使用光棱攻击属性,可以无视对方防御属性;天启具配备有更强的装甲,进行伤害计算时,还可以再减免掉即将所受20%的伤害。例如灰熊攻击天启,每次攻击将造成(30-20)×(1-0.2)=8点伤害。光棱攻击天启,无视天启防御值,但天启伤害减免仍有效,每次攻击将造成50×(1-0.2)= 40点伤害。
由于敌人的间谍在x单位时间后入侵了你的发电厂,你的坦克生产在x单位时间后将会停止生产,这时双方共同从基地派出坦克,向对方发起进攻。
会战的地点在一处狭窄峡谷,所以两方每次只能从基地派出一辆坦克进行作战,坦克派出顺序按照建造顺序,两方坦克从各自基地出发抵达峡谷都需要5个单位时间,到达峡谷在中间相遇时,开始这一回合的对战,双方将同时发起进攻互相攻击,双方坦克将同时受到伤害,坦克攻击完一次后,1个单位时间后再进行下一次攻击(例如灰熊对战灰熊,每次攻击将对敌方造成30-15=15点伤害,因此经过7个单位时间后,双方将同归于尽)。直到其中一方坦克爆炸被消灭或者双方坦克同归于尽,将结束这一回合的对战。本回合胜方坦克将返回基地进行修理,从峡谷中央返回基地也需要5个单位时间,(如果目前队伍只剩余最后这一辆坦克,将不再返回基地维修,停留在峡谷中央,原地等待对方坦克到达后,开始下一回合的对战)在胜方坦克掉头返回基地的同一时刻,双方军队的下一个坦克单位也开始从各自基地出发前往峡谷(也需5个单位时间),双方坦克都抵达峡谷中央后,下一回合的对战开始,以此持续下去,直到一方坦克数量为零,比赛结束。
下图为峡谷对战示意图。被击败报废的坦克将自动从战场上移除。
每回合对战胜利的坦克到达它的基地后将开始维修,维修速度是每单位时间回复4点生命值,回复到满血量或轮到该坦克再次出战离开基地时则立即停止维修,每辆回来维修的坦克都自动补到当前出战顺序的队尾,以备下次出战(基地可以同时维修多辆坦克,不设上限,坦克只要回到基地都可以进行维修)。如某回合双方对战坦克同归于尽,则没有坦克返回基地维修。
当你被敌方间谍入侵电厂的同时,你拥有的间谍也将出发渗入敌方的战车工厂,你能派出间谍类型可能有三种,3星间谍会乘坐直升机前往,将在5个单位时间后抵达敌方基地,2星间谍将乘车前往需要20个单位时间到达,1星间谍步行前往需要40个单位时间到达。当间谍抵达敌方基地后,还需要再经过0.5个单位时间破获敌方的战车工厂的坦克制造细节并发送回资料,此时你的所有仍在基地的坦克将会提高一个星级(注意,已经出发在路上或在返回途中而不在基地的坦克不会升星,而已经返回到基地维修的坦克会升星),升星的坦克攻击、防御值将提高5点。
Input
输入为:你拥有的金币值,敌方坦克及派出顺序,敌方间谍入侵你电厂的时间,你拥有的间谍的星级。
在输入、输出敌方坦克名称或者己方坦克名称时,用Bear代表灰熊,Phantom代表幻影,Prism代表光棱,Apocalypse代表天启,当坦克升星后,统一在名称后添加一个*
Output
你需要输出的是:当坦克停止生产时(不止一种情况),你需要输出此时时间,停止生产的原因(如果同时发生则都输出,见样例一)和你坦克的派出顺序(例:Money is empty或 Invaded by enemy spies and production stalled, Bear Phantom.)。当被敌方间谍入侵,需要输出此时间。当每回合对战开始时,你要输出当前时间和对战双方坦克类型,每回合对战决出胜负后,你要输出当前时间和战斗结果(You won the encounter! You lost the encounter!Deadlock!)和在基地里将要派出的坦克顺序(如基地中没有坦克能再派出,则不输出),当你的间谍成功渗入敌方战车工厂窃取到资料时,你需要按派出顺序输出此时有哪些坦克升星(例如,Spy successfullysteal enemy tank technology, Phantom Prism Bear will be upgraded!如果基地中没有坦克可以升星,则只输出Spy successfullysteal enemy tank technology.)。当对方或者我方坦克数量为零时,战争结束,你需要输出战争结果(You won the war! You lost the war!It ended in a draw!)。
Sample Input 1
2500 Bear Bear Phantom 4 3
Sample Output 1
Time:4 Money is empty, Invaded by enemy spies and production stalled, Bear Phantom Bear. Time:9 Round 1 Start, Bear vs Bear. Time:9.5 Spy successfully steal enemy tank technology, Phantom Bear will be upgraded! Time:16 Round 1 End, Deadlock! Phantom* Bear*. Time:21 Round 2 Start, Phantom* vs Bear. Time:25 Round 2 End, You won the encounter! Bear*. Time:30 Round 3 Start, Bear* vs Phantom. Time:35 Round 3 End, You lost the encounter! Phantom*. Time:40 Round 4 Start, Phantom* vs Phantom. Time:43 Round 4 End, You won the encounter! You won the war!
Sample Input 2
0 Bear Bear Phantom 5 3
Sample Output 2
Time:0 You lost the war!
Sample Input 3
1600 Bear Phantom 5 1
Sample Output 3
Time:3 Money is empty and production stalled, Bear Phantom. Time:5 Invaded by enemy spies. Time:10 Round 1 Start, Bear vs Bear. Time:17 Round 1 End, Deadlock! Phantom. Time:22 Round 2 Start, Phantom vs Phantom. Time:29 Round 2 End, Deadlock! It ended in a draw!
Sample Input 4
3500 Bear Phantom Phantom Bear 10 3
Sample Output 4
Time:8 Money is empty and production stalled, Bear Phantom Prism Bear. Time:10 Invaded by enemy spies. Time:15 Round 1 Start, Bear vs Bear. Time:15.5 Spy successfully steal enemy tank technology, Phantom Prism Bear will be upgraded! Time:22 Round 1 End, Deadlock! Phantom* Prism* Bear*. Time:27 Round 2 Start, Phantom* vs Phantom. Time:34 Round 2 End, You won the encounter! Prism* Bear*. Time:39 Round 3 Start, Prism* vs Phantom. Time:42 Round 3 End, You won the encounter! Bear* Phantom*. Time:47 Round 4 Start, Bear* vs Bear. Time:52 Round 4 End, You won the encounter! Phantom* Prism*. You won the war!
Hint
样例一的具体时间点分析:
Time 1 完成灰熊生产。
Time 3 完成幻影生产。
Time 4 完成灰熊生产,同时钱不足,被敌方间谍入侵停止生产,我方拥有灰熊、幻影、灰熊(为派出顺序)三辆坦克。同时第一辆坦克灰熊从基地派出前往峡谷,我方三星间谍派出前往敌方基地。敌方灰熊也从敌方基地出发前往峡谷。
Time 9 我方灰熊与敌方灰熊都抵达峡谷(5个单位时间路程),开始第一回合对战。我方三星间谍同时抵达敌方基地。
Time 9.5 间谍破获敌方坦克细节,在我军基地的幻影,灰熊完成升星。
Time 16 第一回合双方同归于尽(战斗经过7个单位时间,每单位时间互相造成30-15=15点伤害),同时我方一星幻影坦克出发前往峡谷。敌方灰熊也从基地出发前往峡谷。
Time 21 我方一星幻影与敌方灰熊抵达峡谷,开始第二回合对战。
Time 25 第二回合结束,我方一星幻影击败敌方灰熊(一星幻影每次攻击造成45-15=30伤害,4个单位时间击败灰熊,同时灰熊对一星幻影造成10+0+10+0=20点伤害,一星幻影还剩80生命值),一星幻影此时将从峡谷返回基地维修,我方一星灰熊从基地出发前往峡谷。敌方幻影也出发。
Time 30 我方一星灰熊与敌方幻影抵达峡谷,开始第三回合对战。同时我方一星幻影抵达基地,开始维修。
Time 35 第三回合结束,我方一星灰熊被敌方幻影击败(一星灰熊对敌方幻影造成20+0+20+0+20=60伤害),我方一星幻影将立刻结束维修,从基地出发前往峡谷(一星幻影在基地维修了5个单位时间,总共回复5×4=20点生命值,一星幻影目前状态为80+20=100生命值),敌方幻影仅剩自己一辆坦克,无法返回基地维修(只剩40生命值),留在峡谷等待,继续战斗。
Time 40 我方一星幻影抵达峡谷,开始第四回合对战。
Time 43 第四回合结束,我方一星幻影击败地方幻影(敌方幻影只剩40生命值,我方一星幻影对敌方造成30+0+30=60伤害,三个单位时间消灭地方幻影),敌方全军覆没,我军胜利
我一开始写了很久答案一直不对,总是有各种小错误,在用了学长的正确代码进行答案对比后,终于找出了所有的错误,给大家借鉴借鉴
答案:
#include <iostream>
#include <string>
#include<list>
#include<sstream>
using namespace std;
class tank
{
private:int maxlife = 0;//生命值上限int attack=0;//攻击力,光凌的光凌攻击也算在这里int defense=0;//防御int life=0;//生命值string name;//名字bool transform = false;//是否变形string plus;//升级的后缀
public:void renew(){transform = false;}//回合取消变形void attacked(int x,string attacker){if (name == "Bear")life -= x-defense;if (name == "Phantom"){if (transform){transform = false; return;}else {transform = true;life -= x-defense;}}if (name == "Prism")life -= x-defense;if (name == "Apocalypse"){if (attacker == "Prism"){life -= x * 8 / 10;return;}else{life -= (x - defense) * 8 / 10;return;}}if (attacker == "Prism")life -= defense;}//被攻击,输入值为攻击力以及攻击者名字用来判断如何扣血int attackk(){return attack;}//返回攻击力tank(int a, int b, int c, string d){maxlife = c;attack = a;defense = b;life = c;name = d;}//坦克的构造函数bool alive(){if (life <= 0)return false;else return true;}//坦克是否还活着string nam(){return name;}//读取名字string andplus(){return plus;}//加上升星后缀void cure(){if (life < maxlife){life += 4;}if (life >= maxlife){life = maxlife;}}//每个单位时间回4点血void addplus(){plus = "*";attack += 5;defense += 5;}//可以升星了
};class center {int money=0;//总经济list<tank> fighter;int time = 0;//计算制造时间,后面输出到主函数中int invaded = 0;//预计被侵入时间int star = 0;//间谍星级int plustime = 0;//预计间谍进入地方大本营时间
public:int thept(){return plustime;}//输出预计间谍进入敌方大本营时间int thestar(){return star;}//输出星级void addplus(){list<tank>::iterator p = fighter.begin();for (; p != fighter.end(); p++){p->addplus();}}//所有在基地内的都升级void cure(){list<tank>::iterator p = fighter.begin();for (; p != fighter.end(); p++){p->cure();}}//所有在基地内的都治疗4点血void outcount1(){outcount2();if (fighter.size() != 0){cout << '.';}}//可作为结尾,输出基地内所有坦克void outcount2(){list<tank>::iterator p = fighter.begin();for (int x = 0; x < fighter.size(); x++, p++){cout << " ";cout << p->nam() << p->andplus();}}//输出基地内所有坦克void add(tank &a){fighter.push_back(a);}//插到队尾tank fight(){tank temper = *fighter.begin();fighter.pop_front();return temper;}//坦克出发int outtime(){return time;}//将初步计算后的时间输出bool exist(){return (fighter.size() > 0);}//基地内还有坦克吗void create(){int turn = 1;while(money>=600&&(invaded-time)>=1){ if (turn == 1){if (money >= 600){fighter.push_back(tank(30, 15, 100, "Bear"));money -= 600;turn++;time += 1;continue;}else return;}if (turn == 2){if (money >= 1000){if ((invaded - time) < 2){return;}fighter.push_back(tank(40, 15, 100, "Phantom"));money -= 1000;turn++;time += 2;continue;}else { turn = 1; continue; }}if (turn == 3){if (money >= 1200){if ((invaded - time) < 4){return;}fighter.push_back(tank(50, 10, 100, "Prism"));money -= 1200;turn++;time += 4;continue;}else { turn = 1; continue; }}if (turn == 4){if (money >= 1750){if ((invaded - time) < 6){return;}fighter.push_back(tank(60, 20, 120, "Apocalypse"));money -= 1750;turn = 1;time += 6;continue;}else { turn = 1; continue; }}}}//开始制造,造不下去直接停止center(int x,int c,int s) {star = s;if (star == 3){plustime = c + 5;}else if (star == 2){plustime = c + 20;}else if (star == 1){plustime = c + 40;}invaded = c;money = x;if (money >= 600){create();}else return;if (money >= 600){if (time <= invaded){time = invaded;cout << "Time:" << time << " Invaded by enemy spies ";}}if (money < 600){if (time < invaded){cout << "Time:" << time << " Money is empty ";}if (time ==invaded){cout << "Time:" << time << " Money is empty, Invaded by enemy spies ";}}cout << "and production stalled,";list<tank>::iterator p = fighter.begin();for (;p!=fighter.end();p++){cout << ' ' << p->nam();}cout<<'.' << endl;if (money < 600){if (time < invaded){time = invaded;cout << "Time:" << time;cout << " Invaded by enemy spies." << endl;return;}}time = invaded;}//确定定义的一系列数值,包括对先没钱还是先被侵入的判断
};class enemy
{list<tank> fighter;
public:void cure(){list<tank>::iterator p = fighter.begin();for (; p != fighter.end(); p++){p->cure();}}void add(tank& a){fighter.push_back(a);}tank fight(){tank temper = *fighter.begin();fighter.pop_front();return temper;}bool exist(){return (fighter.size() > 0);}void in(string x){if (x == "Bear"){fighter.push_back(tank(30, 15, 100, "Bear"));}if (x == "Phantom"){fighter.push_back(tank(40, 15, 100, "Phantom"));}if (x == "Prism"){fighter.push_back(tank(50, 10, 100, "Prism"));}if (x == "Apocalypse"){fighter.push_back(tank(60, 20, 120, "Apocalypse"));}}
};//地方大本营,基本所有内容与center对应void outime(double x)
{cout << "Time:" << x << " ";
}//输出时间void instarwithoutendl(center& my, int time)
{if (my.thept() == time){outime(time * 1.0 + 0.5);cout << "Spy successfully steal enemy tank technology";if (my.exist()){cout << ',';my.outcount2();cout << " will be upgraded!" << endl;my.addplus();}else{cout << '.' << endl;}}
}//一个不包含回车的升星void instarwithendl(center& my, int time)
{if (my.thept() == time){cout << endl;outime(time * 1.0 + 0.5);cout << "Spy successfully steal enemy tank technology";if (my.exist()){cout << ',';my.outcount2();cout << " will be upgraded!";my.addplus();}else{cout << '.';}}
}
//一个不包含回车的升星(回车问题确实是难题)
void service(center &my, enemy&enemy,int &time)
{for (int i = 0; i < 5; i++){my.cure();enemy.cure();time++;if (i != 4)instarwithendl(my, time);}
}//不断回血五次,用于在路上的时间bool afterfight(center& my, enemy& enemy, int& time, int& round,tank& mytank,tank&youtank)
{if (mytank.alive())//己方胜利了吗{if (enemy.exist())//敌方还有吗{outime(time);cout << "Round " << round << " End, You won the encounter!";my.outcount1();if (my.exist())//己方还有吗{tank temp = mytank;mytank = my.fight(); youtank = enemy.fight();//都有就都派出新坦克instarwithendl(my, time);service(my, enemy, time);my.add(temp);//旧坦克最后时刻才到}else{youtank = enemy.fight();//己方没有只有对方派出instarwithendl(my, time);service(my, enemy, time);}}else{outime(time);cout << "Round " << round << " End, You won the encounter!";my.outcount1();cout << " You won the war!" << endl;;return true;}//敌方没坦克了我直接获胜}elseif (youtank.alive())//对面赢了?{if (my.exist())//我还有吗{outime(time);cout << "Round " << round << " End, You lost the encounter!";my.outcount1();if (enemy.exist()){tank temp = youtank;mytank = my.fight(); youtank = enemy.fight();//双方都有坦克就都派出新的instarwithendl(my, time);service(my, enemy, time);enemy.add(temp);}else{mytank = my.fight();instarwithendl(my, time);service(my, enemy, time);}}else//己方没有坦克了直接失败{outime(time);cout << "Round " << round << " End, You lost the encounter!";my.outcount1();cout << " You lost the war!" << endl;;return true;}}else//同归于尽了{if (my.exist()){if (enemy.exist()){outime(time);cout << "Round " << round << " End, Deadlock!";my.outcount1();mytank = my.fight(); youtank = enemy.fight();//大家都有就派出新的instarwithendl(my, time);service(my, enemy, time);}else {outime(time);cout << "Round " << round << " End, Deadlock!";my.outcount1();cout << " You won the war!" << endl;;return true;}//我有对面没有直接获胜}else if (enemy.exist())//对面有我没有直接失败{outime(time);cout << "Round " << round << " End, Deadlock!";my.outcount1();cout << " You lose the war!" << endl; ;return true;}else {outime(time);cout << "Round " << round << " End, Deadlock!";my.outcount1();cout << " It ended in a draw!" << endl;;return true;}//大家都没了算平局}return false;
}//一个回合打完了判断一下战况,返回true战斗结束,在主函数中直接结束所有进程int main()
{int n;//钱string a;//坦克名称int ctime=0;//侵入时间int star;//间谍星级cin >> n;enemy enemy;//敌方大本营while (cin >> a){if (a == "Bear" || a == "Phantom" || a == "Prism" || a == "Apocalypse")enemy.in(a);else{istringstream is(a);//网上找的一个算法,把string转化为intis >> ctime;break;}}cin >> star;center my(n,ctime,star);//己方大本营int round = 1;//这是第几个回合?int time = my.outtime();//导出初步时间if (my.exist()) {}else{outime(time);cout << "You lost the war!" << endl;return 0;}//什么都没造出来直接认输time += 5;tank mytank = my.fight(), youtank = enemy.fight();//这两步没有写在while里,是将while完全认为是回合开始后的操作,也方便后续一些数值的处理(很大占比是本人水平受限)while (1){outime(time);cout << "Round " << round << " Start, ";cout << mytank.nam() <<mytank.andplus()<< " vs " << youtank.nam()<<youtank.andplus()<< '.' << endl;//开始了instarwithoutendl(my, time);//升星的时间比较特殊,安排在每一个整数时间输出后,避免出现时间错误if (mytank.nam() == "Phantom")mytank.renew();if (youtank.nam() == "Phantom")youtank.renew();//phantom的变形在一个新的回合中不算数while (mytank.alive() && youtank.alive())//干起来{mytank.attacked(youtank.attackk(), youtank.nam());youtank.attacked(mytank.attackk(), mytank.nam());my.cure(); enemy.cure();time++;if (mytank.alive() && youtank.alive())instarwithoutendl(my, time);//新时间变化后查看是否到升星时间,同时最后一个回合打完后不输出,以免出现时间倒挂}bool judge=afterfight(my, enemy, time, round, mytank, youtank);if (judge)return 0;//战斗结束了直接return0;cout << endl;round++;//进入下一个回合}return 0;
}
其实可以更简洁,但是我也懒得在写一遍了,对于一个初学者来说不错了。