北大mooc,程序设计与算法(三)
题目
描述
魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市,城市从西向东依次编号为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个蓝武士和一个红武士),就会发生战斗。战斗的规则是:
在奇数编号城市,红武士先发起攻击
在偶数编号城市,蓝武士先发起攻击
战斗开始前,双方先对自己的武器排好使用顺序,然后再一件一件地按顺序使用。编号小的武器,排在前面。若有多支arrow,用过的排在前面。排好序后,攻击者按此排序依次对敌人一件一件地使用武器。如果一种武器有多件,那就都要用上。每使用一件武器,被攻击者生命值要减去武器攻击力。如果任何一方生命值减为0或小于0即为死去。有一方死去,则战斗结束。
双方轮流使用武器,甲用过一件,就轮到乙用。某一方把自己所有的武器都用过一轮后,就从头开始再用一轮。如果某一方没有武器了,那就挨打直到死去或敌人武器用完。武器排序只在战斗前进行,战斗中不会重新排序。
如果双方武器都用完且都还活着,则战斗以平局结束。如果双方都死了,也算平局。
有可能由于武士自身攻击力太低,而导致武器攻击力为0。攻击力为0的武器也要使用。如果战斗中双方的生命值和武器的状态都不再发生变化,则战斗结束,算平局。
战斗的胜方获得对方手里的武器。武士手里武器总数不超过10件。缴获武器时,按照武器种类编号从小到大缴获。如果有多件arrow,优先缴获没用过的。
如果战斗开始前双方都没有武器,则战斗视为平局。如果先攻击方没有武器,则由后攻击方攻击。
不同的武士有不同的特点。
编号为n的dragon降生时即获得编号为n%3 的武器。dragon在战斗结束后,如果还没有战死,就会欢呼。
编号为n的ninjia降生时即获得编号为n%3 和(n+1)%3的武器。ninja 使用bomb不会让自己受伤。
编号为n的iceman降生时即获得编号为n%3 的武器。iceman每前进一步,生命值减少10%(减少的量要去尾取整)。
编号为n的lion降生时即获得编号为n%3 的武器。lion 有“忠诚度”这个属性,其初始值等于它降生之后其司令部剩余生命元的数目。每前进一步忠诚度就降低K。忠诚度降至0或0以下,则该lion逃离战场,永远消失。但是已经到达敌人司令部的lion不会逃跑。lion在己方司令部可能逃跑。
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分开始到此时间为止的所有事件按顺序输出。事件及其对应的输出样例如下:
-
武士降生
输出样例:000:00 blue dragon 1 born
表示在0点0分,编号为1的蓝魔dragon武士降生
如果造出的是lion,那么还要多输出一行,例:
000:00 blue lion 1 born
Its loyalty is 24
表示该lion降生时的忠诚度是24 -
lion逃跑
输出样例:000:05 blue lion 1 ran away
表示在0点5分,编号为1的蓝魔lion武士逃走 -
武士前进到某一城市
输出样例:
000:10 red iceman 1 marched to city 1 with 20 elements and force 30
表示在0点10分,红魔1号武士iceman前进到1号城市,此时他生命值为20,攻击力为30
对于iceman,输出的生命值应该是变化后的数值 -
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。为简单起见,武器不写复数形式 -
报告战斗情况
战斗只有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
注意,把红武士写前面 -
武士欢呼
输出样例:003:40 blue dragon 2 yelled in city 4 -
武士抵达敌军司令部
输出样例:001:10 red iceman 1 reached blue headquarter with 20 elements and force 30
(此时他生命值为20,攻击力为30)对于iceman,输出的生命值和攻击力应该是变化后的数值 -
司令部被占领
输出样例:003:10 blue headquarter was taken -
司令部报告生命元数量
000:50 100 elements in red headquarter
000:50 120 elements in blue headquarter
表示在0点50分,红方司令部有100个生命元,蓝方有120个 -
武士报告情况
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
自己代码
分别有武器类、士兵类、阵营类和战斗系统单独成一类;
类别不同的武器继承武器类,类别不同的士兵继承士兵类;
武器用指针数组进行存放,作为士兵类的成员对象。士兵用指针数组进行存放,作为阵营类的成员对象;
士兵前进后统计每个士兵的位置,打包成数组放进阵营里;
设置战斗结束标志位。
#include <iostream>
#include <cstring>
#include <iomanip>
#include <algorithm>
using namespace std;
#define endl '\n'
class Weapon{
public:
int weaponId, ad, available;
string typeName;
Weapon(int weaponId_, int ad_, int available_, string typeName_): weaponId(weaponId_), ad(ad_), available(available_), typeName(typeName_) {}
};
class Sword: public Weapon{
public:
Sword(int weaponId_, int ad_): Weapon(weaponId_, ad_, 999, "sword") {}
};
class Bomb: public Weapon{
public:
Bomb(int weaponId_, int ad_): Weapon(weaponId_, ad_, 1, "bomb") {}
};
class Arrow: public Weapon{
public:
Arrow(int weaponId_, int ad_): Weapon(weaponId_, ad_, 2, "arrow") {}
};
class Soldier{
public:
//所属阵营,武士编号,生命,攻击,武器数量,武士类型,武士位置,忠诚度
int headId, soldierId, hp, ad, weaponNumber, type, location, loyalty;
//各类别的武器数量
int weaponClass[3];
string typeName;
Weapon* weaponList[10];
Soldier(int headId_, int soldierId_, int hp_, int ad_, int location_, int type_, string typeName_, int loyalty_ = 999): headId(headId_), soldierId(soldierId_), hp(hp_), ad(ad_), type(type_), typeName(typeName_), location(location_), loyalty(loyalty_), weaponNumber(0) {
for(int i = 0; i < 10; ++i)
weaponList[i] = nullptr;
memset(weaponClass, 0, sizeof(weaponClass));
}
void ChooseWeapon (int n) {
switch(n) {
case 0: weaponList[weaponNumber++] = new Sword(0, ad * 2 / 10);
++weaponClass[0];
break;
case 1: weaponList[weaponNumber++] = new Bomb(1, ad * 4 / 10);
++weaponClass[1];
break;
case 2: weaponList[weaponNumber++] = new Arrow(2, ad * 3 / 10);
++weaponClass[2];
break;
default: cout << "!!武器选择错误" << endl;
}
return;
}
~Soldier() {
for(int i = 0; i < 10; ++i)
delete weaponList[i];
}
};
class Dragon: public Soldier{
public:
Dragon(int headId_, int soldierId_, int hp_, int ad_, int location_): Soldier(headId_, soldierId_, hp_, ad_, location_, 0, "dragon") {
ChooseWeapon(soldierId % 3);
}
};
class Ninja: public Soldier{
public:
Ninja(int headId_, int soldierId_, int hp_, int ad_, int location_): Soldier(headId_, soldierId_, hp_, ad_, location_, 1, "ninja") {
ChooseWeapon(soldierId % 3);
ChooseWeapon((soldierId+1) % 3);
}
};
class Iceman: public Soldier{
public:
Iceman(int headId_, int soldierId_, int hp_, int ad_, int location_): Soldier(headId_, soldierId_, hp_, ad_, location_, 2, "iceman") {
ChooseWeapon(soldierId % 3);
}
};
class Lion: public Soldier{
public:
Lion(int headId_, int soldierId_, int hp_, int ad_, int loyalty_, int location_): Soldier(headId_, soldierId_, hp_, ad_, location_, 3, "lion", loyalty_) {
ChooseWeapon(soldierId % 3);
}
};
class Wolf: public Soldier{
public:
Wolf(int headId_, int soldierId_, int hp_, int ad_, int location_): Soldier(headId_, soldierId_, hp_, ad_, location_, 4, "wolf") { }
};
class Headquarter{
public:
int hp, number, headId;
int whereSoldier[24];
//造兵顺序
int* order;
int* p = order;
Soldier* soldierList[110];
Headquarter(int hp_, int headId_, int* order_): hp(hp_), headId(headId_), order(order_), number(0) {
for(int i = 0; i < 110; ++i)
soldierList[i] = nullptr;
memset(whereSoldier, 0, sizeof(whereSoldier));
}
void MakeSoldier(int* hpSoldier, int* adSoldier, int cityNumber, int times) {
if(hp > hpSoldier[*p]) {
switch(*p) {
case 0: hp -= hpSoldier[0];
++number;
soldierList[number-1] = new Dragon(headId, number, hpSoldier[0], adSoldier[0], headId*(cityNumber+1));
whereSoldier[headId*(cityNumber+1)] = number;
break;
case 1: hp -= hpSoldier[1];
++number;
soldierList[number-1] = new Ninja(headId, number, hpSoldier[1], adSoldier[1], headId*(cityNumber+1));
whereSoldier[headId*(cityNumber+1)] = number;
break;
case 2: hp -= hpSoldier[2];
++number;
soldierList[number-1] = new Iceman(headId, number, hpSoldier[2], adSoldier[2], headId*(cityNumber+1));
whereSoldier[headId*(cityNumber+1)] = number;
break;
case 3: hp -= hpSoldier[3];
++number;
soldierList[number-1] = new Lion(headId, number, hpSoldier[3], adSoldier[3], hp, headId*(cityNumber+1));
whereSoldier[headId*(cityNumber+1)] = number;
break;
case 4: hp -= hpSoldier[4];
++number;
soldierList[number-1] = new Wolf(headId, number, hpSoldier[4], adSoldier[4], headId*(cityNumber+1));
whereSoldier[headId*(cityNumber+1)] = number;
break;
default: p = order;
cout << "!!武士选择错误" << endl;
}
if(headId == 0) {
cout << setw(3) << setfill('0') << times/60 << ':' << setw(2) << setfill('0') << times%60 << " red " << soldierList[number-1]->typeName << ' ' << number << " born" << endl;
if(*p == 3)
cout << "Its loyalty is " << soldierList[number-1]->loyalty << endl;
}
else if(headId == 1) {
cout << setw(3) << setfill('0') << times/60 << ':' << setw(2) << setfill('0') << times%60 << " blue " << soldierList[number-1]->typeName << ' ' << number << " born" << endl;
if(*p == 3)
cout << "Its loyalty is " << soldierList[number-1]->loyalty << endl;
}
if(p == order + 4)
p = order;
else
++p;
}
return;
}
~Headquarter() {
for(int i = 0; i < 110; ++i)
delete soldierList[i];
}
};
//战斗系统
class CombatSystem {
public:
int times = 0;
//lion忠诚度判断
void IfLoyalty(Headquarter& red, Headquarter& blue, int cityNumber) {
for(int i = 0; i <= cityNumber+1; ++i) {
int idr = red.whereSoldier[i]-1;
int idb = blue.whereSoldier[i]-1;
if(red.whereSoldier[i] != 0 && red.soldierList[idr]->type == 3 && red.soldierList[idr]->loyalty <= 0) {
red.whereSoldier[i] = 0;
cout << setw(3) << setfill('0') << times/60 << ':' << setw(2) << setfill('0') << times%60 << " red lion " << idr+1 << " ran away" << endl;
delete red.soldierList[idr];
red.soldierList[idr] = nullptr;
}
if(blue.whereSoldier[i] != 0 && blue.soldierList[idb]->type == 3 && blue.soldierList[idb]->loyalty <= 0) {
blue.whereSoldier[i] = 0;
cout << setw(3) << setfill('0') << times/60 << ':' << setw(2) << setfill('0') << times%60 << " blue lion " << idb+1 << " ran away" << endl;
delete blue.soldierList[idb];
blue.soldierList[idb] = nullptr;
}
}
}
//武器排序比较函数
static int WeaponCmp(Weapon*& w1, Weapon*& w2) {
if(w1->available == 0)
return 0;
else if(w2->available == 0)
return 1;
else if(w1->weaponId < w2->weaponId)
return 1;
else if(w1->weaponId > w2->weaponId)
return 0;
else if(w1->weaponId == 2)
return w1->available < w2->available;
else
return 0;
}
//武器排序并统计该武士各类武器数量及武器总数
void CountWeaponNumber(Soldier*& s) {
sort(s->weaponList, s->weaponList + s->weaponNumber, WeaponCmp);
int weaponNum = 0;
int weaponClassNum[3] = {0, 0, 0};
for(int i = 0; i < s->weaponNumber; ++i) {
if(s->weaponList[i] != nullptr && s->weaponList[i]->available != 0) {
weaponNum += 1;
weaponClassNum[s->weaponList[i]->weaponId] += 1;
}
}
s->weaponNumber = weaponNum;
s->weaponClass[0] = weaponClassNum[0];
s->weaponClass[1] = weaponClassNum[1];
s->weaponClass[2] = weaponClassNum[2];
if(s->weaponClass[0] + s->weaponClass[1] + s->weaponClass[2] != s->weaponNumber)
cout << "!!武器统计错误" << endl;
return;
}
//统计各武士位置
void CountSoldier(Headquarter& h) {
memset(h.whereSoldier, 0, sizeof(h.whereSoldier));
for(int i = 0; i < h.number; ++i) {
if(h.soldierList[i] != nullptr) {
CountWeaponNumber(h.soldierList[i]);
h.whereSoldier[h.soldierList[i]->location] = h.soldierList[i]->soldierId;
}
}
return;
}
//武士前进
int SoldierGo(Headquarter& red, Headquarter& blue, int k, int cityNumber) {
int headWinFlag = 0;
for(int i = 0; i <= cityNumber+1; ++i) {
if(red.whereSoldier[i] != 0) {
int idr = red.whereSoldier[i]-1;
red.soldierList[idr]->location++;
if(red.soldierList[idr]->type == 3 && red.soldierList[idr]->location != (1-red.headId)*(cityNumber+1))
red.soldierList[idr]->loyalty -= k;
else if(red.soldierList[idr]->type == 2)
red.soldierList[idr]->hp -= red.soldierList[idr]->hp / 10;
}
if(blue.whereSoldier[i] != 0) {
int idb = blue.whereSoldier[i]-1;
blue.soldierList[idb]->location--;
if(blue.soldierList[idb]->type == 3 && blue.soldierList[idb] -> location != (1-blue.headId)*(cityNumber+1))
blue.soldierList[idb]->loyalty -= k;
else if(blue.soldierList[idb]->type == 2)
blue.soldierList[idb]->hp -= blue.soldierList[idb]->hp / 10;
}
}
CountSoldier(red);
CountSoldier(blue);
for(int i = 0; i <= cityNumber+1; ++i) {
if(red.whereSoldier[i] != 0) {
int idr = red.whereSoldier[i]-1;
//判断是否到达敌方司令部
if(red.soldierList[idr]->location >= cityNumber+1) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " reached blue headquarter with " << red.soldierList[idr]->hp << " elements and force " << red.soldierList[idr]->ad << endl;
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " blue headquarter was taken" << endl;
headWinFlag = 1;
}
else
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " marched to city " << red.soldierList[idr]->location << " with " << red.soldierList[idr]->hp << " elements and force " << red.soldierList[idr]->ad << endl;
}
if(blue.whereSoldier[i] != 0) {
int idb = blue.whereSoldier[i]-1;
//判断是否到达敌方司令部
if(blue.soldierList[idb]->location <= 0) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " reached red headquarter with " << blue.soldierList[idb]->hp << " elements and force " << blue.soldierList[idb]->ad << endl;
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " red headquarter was taken" << endl;
headWinFlag = 1;
}
else
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " marched to city " << blue.soldierList[idb]->location << " with " << blue.soldierList[idb]->hp << " elements and force " << blue.soldierList[idb]->ad << endl;
}
}
return headWinFlag;
}
//缴获武器
void GrabWeapon(Soldier*& s1, Soldier*& s2) {
for(int w1 = s1->weaponNumber, w2 = 0; w1 < 10, w2 < s2->weaponNumber; ++w1, ++w2) {
if(s2->weaponList[w2]->available > 0) {
s1->ChooseWeapon(s2->weaponList[w2]->weaponId);
s1->weaponList[s1->weaponNumber-1]->available = s2->weaponList[w2]->available;
s2->weaponList[w2]->available = 0;
}
}
CountWeaponNumber(s1);
CountWeaponNumber(s2);
return;
}
//wolf抢武器
void WolfGrabWeapon(Headquarter& red, Headquarter& blue, int cityNumber) {
for(int i = 0; i <= cityNumber+1; ++i) {
int idr = red.whereSoldier[i]-1, idb = blue.whereSoldier[i]-1;
if(red.whereSoldier[i] != 0 && red.soldierList[idr]->type == 4 && blue.whereSoldier[i] != 0 && blue.soldierList[idb]->type != 4) {
//被抢方从第一件武器开始找,可用便依次放在wolf的武器列表后面
for(int w1 = red.soldierList[idr]->weaponNumber, w2 = 0; w1 < 10, w2 < blue.soldierList[idb]->weaponNumber; ++w1, ++w2) {
//wolf得到对应武器
red.soldierList[idr]->ChooseWeapon(blue.soldierList[idb]->weaponList[w2]->weaponId);
//被抢方的武器可用次数赋值给wolf得到的武器可用次数
red.soldierList[idr]->weaponList[red.soldierList[idr]->weaponNumber - 1]->available = blue.soldierList[idb]->weaponList[w2]->available;
//清空被抢方的武器可用次数
blue.soldierList[idb]->weaponList[w2]->available = 0;
//wolf只抢一类武器,判断若下一件武器为另一类武器 或没有下一件武器或 wolf自身武器已满10 则结束抢夺,跳出循环并输出抢夺信息
if(w1 >= 10 || w2 >= blue.soldierList[idb]->weaponNumber || blue.soldierList[idb]->weaponList[w2+1] == nullptr || blue.soldierList[idb]->weaponList[w2+1]->available <= 0 || blue.soldierList[idb]->weaponList[w2]->weaponId != blue.soldierList[idb]->weaponList[w2+1]->weaponId) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " red wolf " << idr+1 << " took " << w2+1 << ' ' << blue.soldierList[idb]->weaponList[w2]->typeName << " from blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " in city " << i << endl;
break;
}
}
//抢夺后,重新武器排序并统计数量
CountWeaponNumber(red.soldierList[idr]);
}
else if(blue.whereSoldier[i] != 0 && blue.soldierList[idb]->type == 4 && red.whereSoldier[i] != 0 && red.soldierList[idr]->type != 4) {
for(int w1 = blue.soldierList[idb]->weaponNumber, w2 = 0; w1 < 10, w2 < red.soldierList[idr]->weaponNumber; ++w1, ++w2) {
blue.soldierList[idb]->ChooseWeapon(red.soldierList[idr]->weaponList[w2]->weaponId);
blue.soldierList[idb]->weaponList[blue.soldierList[idb]->weaponNumber - 1]->available = red.soldierList[idr]->weaponList[w2]->available;
red.soldierList[idr]->weaponList[w2]->available = 0;
if(w1 >= 10 || w2 >= red.soldierList[idr]->weaponNumber || red.soldierList[idr]->weaponList[w2+1] == nullptr || red.soldierList[idr]->weaponList[w2+1]->available <= 0 || red.soldierList[idr]->weaponList[w2]->weaponId != red.soldierList[idr]->weaponList[w2+1]->weaponId) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " blue wolf " << idb+1 << " took " << w2+1 << ' ' << red.soldierList[idr]->weaponList[w2]->typeName << " from red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " in city " << i << endl;
break;
}
}
CountWeaponNumber(blue.soldierList[idb]);
}
}
return;
}
//检验状态是否改变
int CheckState(Soldier*& s1, Soldier*& s2) {
int s1WeaponNum = 0, s2WeaponNum = 0, s1TotalAd = 0, s2TotalAd = 0;
int s1WeaponClassNum[3] = {0, 0, 0}, s2WeaponClassNum[3] = {0, 0, 0};
for(int i = 0; i < s1->weaponNumber; ++i) {
if(s1->weaponList[i] != nullptr && s1->weaponList[i]->available != 0) {
s1WeaponNum += 1;
s1WeaponClassNum[s1->weaponList[i]->weaponId] += 1;
if(s1->weaponList[i]->weaponId == 0)
s1TotalAd += s1->weaponList[i]->ad;
}
}
for(int j = 0; j < s2->weaponNumber; ++j) {
if(s2->weaponList[j] != nullptr && s2->weaponList[j]->available != 0) {
s2WeaponNum += 1;
s2WeaponClassNum[s2->weaponList[j]->weaponId] += 1;
if(s2->weaponList[j]->weaponId == 0)
s2TotalAd += s2->weaponList[j]->ad;
}
}
if((s1WeaponNum == 0 && s2WeaponNum == 0) || (s1TotalAd == 0 && s2TotalAd == 0 && s1WeaponClassNum[1] == 0 && s2WeaponClassNum[1] == 0 && s1WeaponClassNum[2] == 0 && s2WeaponClassNum[2] == 0))
return 1;
else
return 0;
}
//战斗
int Combat(Soldier*& s1, Soldier*& s2) {
int i1 = 0, i2 = 0, winflag = 0;
while(winflag == 0) {
//round一次回合中找武器的次数,找遍了都没有说明他没有可用武器了
int round1 = 0, round2 = 0;
//判断该武器是否可用,若不可用,找到可用次数大于0的武器
while(round1 < s1->weaponNumber && s1->weaponList[i1]->available == 0) {
++i1;
if(i1 >= s1->weaponNumber)
i1 = 0;
++round1;
}
//s1攻击s2
if(round1 < s1->weaponNumber) {
s2->hp -= s1->weaponList[i1]->ad;
//炸弹反伤
if(s1->weaponList[i1]->weaponId == 1 && s1->type != 1) {
s1->hp -= (s1->weaponList[i1]->ad / 2);
}
if(s1->weaponList[i1]->weaponId != 0) {
--s1->weaponList[i1]->available;
}
//使用后换武器
++i1;
if(i1 >= s1->weaponNumber)
i1 = 0;
}
//战斗结果判断
if(s2->hp <= 0 && s1->hp <= 0) {
winflag = 3; //两败俱伤
break;
}
else if(s2->hp <= 0 && s1->hp > 0) {
winflag = 1; //第一个人赢
break;
}
else if(s2->hp > 0 && s1->hp <= 0) {
winflag = 2; //第二个人赢
break;
}
while(round2 < s2->weaponNumber && s2->weaponList[i2]->available == 0) {
++i2;
if(i2 >= s2->weaponNumber)
i2 = 0;
++round2;
}
//s2攻击s1
if(round2 < s2->weaponNumber) {
s1->hp -= s2->weaponList[i2]->ad;
if(s2->weaponList[i2]->weaponId == 1 && s2->type != 1) {
s2->hp -= (s2->weaponList[i2]->ad/2);
}
if(s2->weaponList[i2]->weaponId != 0) {
--s2->weaponList[i2]->available;
}
//使用后换武器
++i2;
if(i2 >= s2->weaponNumber)
i2 = 0;
}
if(s2->hp <= 0 && s1->hp <= 0) {
winflag = 3; //两败俱伤
break;
}
else if(s2->hp <= 0 && s1->hp > 0) {
winflag = 1; //第一个人赢
break;
}
else if(s2->hp > 0 && s1->hp <= 0) {
winflag = 2; //第二个人赢
break;
}
else if(round1 >= s1->weaponNumber && round2 >= s2->weaponNumber) {
winflag = 4; //两边都无可用武器,平局
break;
}
else if(CheckState(s1, s2) == 1) {
winflag = 4; //双方无交手,状态不变,平局
break;
}
}
return winflag;
}
//寻找战场
void FindCombat(Headquarter& red, Headquarter& blue, int cityNumber) {
for(int i = 0; i <= cityNumber+1; ++i) {
if(red.whereSoldier[i] != 0 && blue.whereSoldier[i] != 0) {
int idr = red.whereSoldier[i]-1;
int idb = blue.whereSoldier[i]-1;
int winflag = 0; //战斗结果标记,1第一个人赢,2第二个人赢,3两败俱伤,4都活着
if(i % 2 == 1) {
winflag = Combat(red.soldierList[idr], blue.soldierList[idb]);
if(winflag == 1) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " killed blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " in city " << i << " remaining " << red.soldierList[idr]->hp << " elements" <<endl;
GrabWeapon(red.soldierList[idr], blue.soldierList[idb]);
blue.whereSoldier[i] = 0;
delete blue.soldierList[idb];
blue.soldierList[idb] = nullptr;
}
else if(winflag == 2) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " killed red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " in city " << i << " remaining " << blue.soldierList[idb]->hp << " elements" <<endl;
GrabWeapon(blue.soldierList[idb], red.soldierList[idr]);
red.whereSoldier[i] = 0;
delete red.soldierList[idr];
red.soldierList[idr] = nullptr;
}
else if(winflag == 3) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " both red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " and blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " died in city " << i <<endl;
red.whereSoldier[i] = 0;
delete red.soldierList[idr];
red.soldierList[idr] = nullptr;
blue.whereSoldier[i] = 0;
delete blue.soldierList[idb];
blue.soldierList[idb] = nullptr;
}
else {
CountWeaponNumber(red.soldierList[idr]);
CountWeaponNumber(blue.soldierList[idb]);
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " both red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " and blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " were alive in city " << i <<endl;
}
}
else {
winflag = Combat(blue.soldierList[idb], red.soldierList[idr]);
if(winflag == 2) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " killed blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " in city " << i << " remaining " << red.soldierList[idr]->hp << " elements" <<endl;
GrabWeapon(red.soldierList[idr], blue.soldierList[idb]);
blue.whereSoldier[i] = 0;
delete blue.soldierList[idb];
blue.soldierList[idb] = nullptr;
}
else if(winflag == 1) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " killed red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " in city " << i << " remaining " << blue.soldierList[idb]->hp << " elements" <<endl;
GrabWeapon(blue.soldierList[idb], red.soldierList[idr]);
red.whereSoldier[i] = 0;
delete red.soldierList[idr];
red.soldierList[idr] = nullptr;
}
else if(winflag == 3) {
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " both red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " and blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " died in city " << i <<endl;
red.whereSoldier[i] = 0;
delete red.soldierList[idr];
red.soldierList[idr] = nullptr;
blue.whereSoldier[i] = 0;
delete blue.soldierList[idb];
blue.soldierList[idb] = nullptr;
}
else {
CountWeaponNumber(red.soldierList[idr]);
CountWeaponNumber(blue.soldierList[idb]);
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " both red " << red.soldierList[idr]->typeName << ' ' << idr+1 << " and blue " << blue.soldierList[idb]->typeName << ' ' << idb+1 << " were alive in city " << i <<endl;
}
}
//dragon欢呼
if(red.soldierList[idr] != nullptr && red.soldierList[idr]->type == 0 && red.soldierList[idr]->hp > 0)
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " red dragon " << idr+1 << " yelled in city " << i << endl;
if(blue.soldierList[idb] != nullptr && blue.soldierList[idb]->type == 0 && blue.soldierList[idb]->hp > 0)
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " blue dragon " << idb+1 << " yelled in city " << i << endl;
}
}
return;
}
//武士报告自己的情况
void SoldierReport(Headquarter& red, Headquarter& blue, int cityNumber) {
for(int i = 0; i <= cityNumber+1; ++i) {
if(red.whereSoldier[i] != 0) {
int idr = red.whereSoldier[i]-1;
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " red " << red.soldierList[idr]->typeName << " " << idr+1 << " has " << red.soldierList[idr]->weaponClass[0] << " sword " << red.soldierList[idr]->weaponClass[1] << " bomb " << red.soldierList[idr]->weaponClass[2] << " arrow and " << red.soldierList[idr]->hp << " elements" << endl;
}
if(blue.whereSoldier[i] != 0) {
int idb = blue.whereSoldier[i]-1;
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << " blue " << blue.soldierList[idb]->typeName << " " << idb+1 << " has " << blue.soldierList[idb]->weaponClass[0] << " sword " << blue.soldierList[idb]->weaponClass[1] << " bomb " << blue.soldierList[idb]->weaponClass[2] << " arrow and " << blue.soldierList[idb]->hp << " elements" << endl;
}
}
return;
}
//阵营双方开始交战
void start() {
int t = 0;
cin >> t;
for(int t0 = 1; t0 <= t; ++t0) {
int M, N, K, T; //司令部生命,城市数,忠诚度下降系数,截至时间
cin >> M >> N >> K >> T;
int hpSoldier[5];
for(int i = 0; i < 5; cin >> hpSoldier[i++]);
int adSoldier[5];
for(int i = 0; i < 5; cin >> adSoldier[i++]);
cout << "Case " << t0 << ":" << endl;
int orderRed[5] = {2, 3, 4, 1, 0}, orderBlue[5] = {3, 0, 1, 2, 4};
Headquarter red(M, 0, orderRed);
Headquarter blue(M, 1, orderBlue);
times = 0;
while(times <= T) {
red.MakeSoldier(hpSoldier,adSoldier, N, times);
blue.MakeSoldier(hpSoldier,adSoldier, N, times);
times += 5;
if(times > T) break;
IfLoyalty(red, blue, N);
times += 5;
if(times > T) break;
if(SoldierGo(red, blue, K, N) == 1) break; //到达敌方司令部则跳出
times += 25;
if(times > T) break;
WolfGrabWeapon(red, blue, N);
times += 5;
if(times > T) break;
FindCombat(red, blue, N);
times += 10;
if(times > T) break;
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << ' ' << red.hp << " elements in red headquarter" << endl;
cout << setw(3) << setfill('0') << times/60 << ':' << times%60 << ' ' << blue.hp << " elements in blue headquarter" << endl;
times += 5;
if(times > T) break;
SoldierReport(red, blue, N);
times += 5;
if(times > T) break;
}
}
return;
}
};
int main() {
CombatSystem c;
c.start();
return 0;
}