OpenJudge 3433 R:魔兽世界终极版
第一次魔兽世界: 这题 tm 是个啥啊? (挠头)
第二次魔兽世界: 勇敢重构,不怕困难!
终极魔兽世界
纪念一下花了我两天写 + 调试出来的有史以来最长代码!(过了成就感满满)
重要的是写好类,类写好了剩下的框架搭建起来很清楚,调试起来也很方便
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
const int RED = 0;
const int BLUE = 1;
int cost[5], force[5];
int arrowForce, loyaltyDecline;
int tim;
inline int getSide(string flag) { return flag == "blue"; }
inline int oppositeSide(int x) { return x ^ 1; }
inline void printTime() { cout << setfill('0') << setw(3) << tim << ":"; }
class Warrior;
class City;
class Weapon {
public:
int typ;
int hp, damage;
Warrior* owner;
Weapon(int Typ, int Hp, int Damage, Warrior* Owner) : typ(Typ), hp(Hp), damage(Damage), owner(Owner) {}
void checkBroken();
};
class Sword : public Weapon {
public:
Sword(int Damage, Warrior* Owner) : Weapon(0, Damage, Damage, Owner) {}
void used() {
hp = floor(0.8L * hp);
damage = floor(0.8L * damage);
} // call checkBroken manually
};
class Arrow : public Weapon {
public:
Arrow(int Damage, Warrior* Owner) : Weapon(1, 3, Damage, Owner) {}
void used() { --hp; }
void attack(City*);
};
class Bomb {
public:
Warrior* owner;
Bomb(Warrior* Owner) : owner(Owner) {}
void checkAndBlast();
};
class City {
public:
int gen, id;
int genPool;
int winStatus[2];
string flag;
Warrior* warriorIn[2];
City() {}
void init(int Id) {
id = Id;
gen = 0;
genPool = 0;
winStatus[0] = winStatus[1] = -2;
flag = "neutral";
warriorIn[0] = NULL;
warriorIn[1] = NULL;
}
virtual void getGen() {}
void produceGen() { gen += 10; }
void updateWinStatus(int curStatus) {
winStatus[1] = winStatus[0];
winStatus[0] = curStatus;
}
void checkFlag() {
if (winStatus[0] == winStatus[1] && winStatus[0] != -2 && winStatus[0] != -1) {
if (flag == "neutral" || getSide(flag) != winStatus[0]) {
flag = (winStatus[0] ? "blue" : "red");
printTime();
cout << "40 " << flag << " flag raised in city " << id << endl;
}
}
}
};
class Warrior {
public:
int id;
string side, typ;
int hp, damage;
City* inCity;
Sword* sword;
Arrow* arrow;
Bomb* bomb;
Warrior(int Hp, int Damage, int Id, string Side, string Type) :
hp(Hp), damage(Damage), id(Id), side(Side), typ(Type) {
printTime();
cout << "00 ";
printName();
cout << " born" << endl;
sword = NULL;
arrow = NULL;
bomb = NULL;
}
~Warrior() {
inCity->warriorIn[getSide(side)] = NULL;
if (sword) delete sword;
if (arrow) delete arrow;
if (bomb) delete bomb;
}
void printName() { cout << side << " " << typ << " " << id; }
void printWeapon() {
printTime();
cout << "55 ";
printName();
cout << " has ";
if (sword || arrow || bomb) {
if (arrow) {
cout << "arrow" << "(" << arrow->hp << ")";
if (bomb || sword) cout << ",";
}
if (bomb) {
cout << "bomb";
if (sword) cout << ",";
}
if (sword) {
cout << "sword" << "(" << sword->damage << ")";
}
cout << endl;
return;
}
cout << "no weapon" << endl;
}
void printAttack(Warrior* target, bool fightBack) {
printTime();
cout << "40 ";
printName();
cout << (fightBack ? " fought back against " : " attacked ");
target->printName();
cout << " in city " << inCity->id;
if (fightBack == false)
cout << " with " << hp << " elements and force " << damage;
cout << endl;
}
void printKilled(Warrior* obj) {
printTime();
cout << "40 ";
obj->printName();
cout << " was killed in city ";
cout << obj->inCity->id << endl;
}
virtual int attack(Warrior* target, bool fightBack) {
if (hp == 0) {
if (target->hp == 0) {
delete target;
delete this;
return -2;
} else {
return target->attack(this, true);
}
} else {
if (target->hp == 0) {
delete target;
return getSide(side);
} else {
int swordDamage = 0, hpBeforeBattle = target->hp;
if (sword) {
swordDamage = sword->damage;
sword->used();
sword->checkBroken();
}
target->hp -= (swordDamage + (fightBack ? floor(0.5L * damage) : damage));
printAttack(target, fightBack);
if (target->hp <= 0) {
printKilled(target);
if (target->typ == "lion")
hp += hpBeforeBattle;
delete target;
return getSide(side);
} else if (fightBack == false && target->typ != "ninja") {
return target->attack(this, true);
} else return -1;
}
}
}
virtual void printMarch(City* targetCity) {
printTime();
cout << "10 ";
printName();
cout << " marched to city " << targetCity->id;
cout << " with " << hp << " elements and force " << damage << endl;
}
virtual void march(City* targetCity) {
inCity->warriorIn[getSide(side)] = NULL;
targetCity->warriorIn[getSide(side)] = this;
inCity = targetCity;
}
void marchInBoarder();
virtual void takeGen(City* headquarter, int min) {
printTime();
cout << min << " ";
printName();
cout << " earned " << inCity->gen << " elements for his headquarter" << endl;
headquarter->genPool += inCity->gen;
inCity->gen = 0;
}
virtual void moraleChange(int mode) {} // functions for dragon
virtual void hail() {}
virtual void strengthen() {} // functions for iceman
virtual void flee() {} // functions for lion
virtual void takeWeapon(Warrior* target) {} // functions for wolf
};
class Dragon : public Warrior {
public:
double morale;
Dragon(int Id, string Side, string Name, City* loc) : Warrior(cost[0], force[0], Id, Side, Name) {
morale = (double)loc->gen / cost[0];
inCity = loc;
inCity->warriorIn[getSide(Side)] = this;
if (Id % 3 == 0) {
sword = new Sword(floor(0.2L * damage), this);
sword->checkBroken();
}
if (Id % 3 == 1)
bomb = new Bomb(this);
if (Id % 3 == 2)
arrow = new Arrow(arrowForce, this);
cout << "Its morale is ";
cout << fixed << setprecision(2) << morale;
cout << endl;
}
void moraleChange(int mode) { morale += mode * 0.2; }
void hail() { // declare war can hail
if (morale > 0.8) {
printTime();
cout << "40 ";
printName();
cout << " yelled in city " << inCity->id << endl;
}
}
virtual int attack(Warrior* target, bool fightBack) {
if (hp == 0) {
if (target->hp == 0) {
delete target;
delete this;
return -2;
} else {
return target->attack(this, true);
}
} else {
if (target->hp == 0) {
if (fightBack == false) hail();
delete target;
return getSide(side);
} else {
int swordDamage = 0, hpBeforeBattle = target->hp;
if (sword) {
swordDamage = sword->damage;
sword->used();
sword->checkBroken();
}
target->hp -= (swordDamage + (fightBack ? floor(0.5L * damage) : damage));
printAttack(target, fightBack);
if (target->hp <= 0) {
printKilled(target);
if (target->typ == "lion")
hp += hpBeforeBattle;
delete target;
moraleChange(1);
if (fightBack == false) hail();
return getSide(side);
} else if (fightBack == false && target->typ != "ninja") {
moraleChange(-1);
int recordWinner = target->attack(this, true);
if (recordWinner != getSide(target->side)) hail();
return recordWinner;
} else {
moraleChange(-1);
if (fightBack == false) hail();
return -1;
}
}
}
}
};
class Ninja : public Warrior {
public:
Ninja(int Id, string Side, string Name, City* loc) : Warrior(cost[1], force[1], Id, Side, Name) {
inCity = loc;
inCity->warriorIn[getSide(Side)] = this;
if (Id % 3 == 0) {
sword = new Sword(floor(0.2L * damage), this);
bomb = new Bomb(this);
sword->checkBroken();
}
if (Id % 3 == 1) {
arrow = new Arrow(arrowForce, this);
bomb = new Bomb(this);
}
if (Id % 3 == 2) {
arrow = new Arrow(arrowForce, this);
sword = new Sword(floor(0.2L * damage), this);
sword->checkBroken();
}
}
};
class Iceman : public Warrior {
public:
int count;
Iceman(int Id, string Side, string Name, City* loc) : Warrior(cost[2], force[2], Id, Side, Name) {
inCity = loc;
count = 0;
inCity->warriorIn[getSide(Side)] = this;
if (Id % 3 == 0) {
sword = new Sword(floor(0.2L * damage), this);
sword->checkBroken();
}
if (Id % 3 == 1)
bomb = new Bomb(this);
if (Id % 3 == 2)
arrow = new Arrow(arrowForce, this);
}
virtual void strengthen() { // call this function after every march
++count;
if (count == 2) {
count = 0;
damage += 20;
hp -= 9;
if (hp <= 0) hp = 1;
}
}
virtual void printMarch(City* targetCity) {
strengthen();
printTime();
cout << "10 ";
printName();
cout << " marched to city " << targetCity->id;
cout << " with " << hp << " elements and force " << damage << endl;
}
virtual void march(City* targetCity) {
inCity->warriorIn[getSide(side)] = NULL;
targetCity->warriorIn[getSide(side)] = this;
inCity = targetCity;
}
};
class Lion : public Warrior {
public:
int loyalty;
Lion(int Id, string Side, string Name, City* loc) : Warrior(cost[3], force[3], Id, Side, Name) {
inCity = loc;
inCity->warriorIn[getSide(Side)] = this;
loyalty = loc->gen;
cout << "Its loyalty is " << loyalty << endl;
}
void flee() {
if (loyalty <= 0) {
printTime();
cout << "05 ";
printName();
cout << " ran away" << endl;
delete this;
}
}
int attack(Warrior* target, bool fightBack) { // call when city has two opposite warriors
if (hp == 0) {
if (target->hp == 0) { // all killed by arrows
delete target;
delete this;
return -2;
} else { // only self killed by arrows
return target->attack(this, true);
}
} else {
if (target->hp == 0) { // only enemy killed by arrows
delete target;
return getSide(side);
} else { // self first attack enemy
int hpBeforeBattle = target->hp;
target->hp -= (fightBack ? floor(0.5L * damage) : damage);
printAttack(target, fightBack);
if (target->hp <= 0) { // enemy been killed
printKilled(target);
if (target->typ == "lion")
hp += hpBeforeBattle;
delete target;
return getSide(side);
} else if (fightBack == false && target->typ != "ninja") { // enemy alive and fightback
loyalty -= loyaltyDecline;
return target->attack(this, true);
} else { // draw
loyalty -= loyaltyDecline;
return -1;
}
}
}
}
};
class Wolf : public Warrior {
public:
Wolf(int Id, string Side, string Name, City* loc) : Warrior(cost[4], force[4], Id, Side, Name) {
inCity = loc;
}
void takeWeapon(Warrior* target) {
if (!sword && target->sword) {
sword = target->sword;
target->sword->owner = this;
target->sword = NULL;
}
if (!arrow && target->arrow) {
arrow = target->arrow;
target->arrow->owner = this;
target->arrow = NULL;
}
if (!bomb && target->bomb) {
bomb = target->bomb;
target->bomb->owner = this;
target->bomb = NULL;
}
}
virtual int attack(Warrior* target, bool fightBack) {
if (hp == 0) {
if (target->hp == 0) {
delete target;
delete this;
return -2;
} else {
return target->attack(this, true);
}
} else {
if (target->hp == 0) {
takeWeapon(target);
delete target;
return getSide(side);
} else {
int swordDamage = 0, hpBeforeBattle = target->hp;
if (sword) {
swordDamage = sword->damage;
sword->used();
sword->checkBroken();
}
target->hp -= (swordDamage + (fightBack ? floor(0.5L * damage) : damage));
printAttack(target, fightBack);
if (target->hp <= 0) {
printKilled(target);
takeWeapon(target);
if (target->typ == "lion")
hp += hpBeforeBattle;
delete target;
return getSide(side);
} else if (fightBack == false && target->typ != "ninja") {
return target->attack(this, true);
} else return -1;
}
}
}
};
class Headquarter : public City {
int cur, tot;
int produceList[5];
public:
int holdEnemy;
Warrior* inEnemy[5];
friend void Warrior::marchInBoarder();
Headquarter(string side) {
flag = side;
if (flag == "red") {
produceList[0] = 2;
produceList[1] = 3;
produceList[2] = 4;
produceList[3] = 1;
produceList[4] = 0;
}
if (flag == "blue") {
produceList[0] = 3;
produceList[1] = 0;
produceList[2] = 1;
produceList[3] = 2;
produceList[4] = 4;
}
}
void init(int Id, int Gen) {
while (holdEnemy) {
delete inEnemy[holdEnemy];
holdEnemy--;
}
if (warriorIn[0]) delete warriorIn[0];
if (warriorIn[1]) delete warriorIn[1];
cur = 0, tot = 0, genPool = 0;
id = Id, gen = Gen;
}
void produceWarrior() {
int curProduce = produceList[cur];
if (gen < cost[curProduce]) return;
gen -= cost[curProduce];
++tot;
switch(curProduce) {
case 0:
warriorIn[getSide(flag)] = new Dragon(tot, flag, "dragon", this);
break;
case 1:
warriorIn[getSide(flag)] = new Ninja(tot, flag, "ninja", this);
break;
case 2:
warriorIn[getSide(flag)] = new Iceman(tot, flag, "iceman", this);
break;
case 3:
warriorIn[getSide(flag)] = new Lion(tot, flag, "lion", this);
break;
default:
warriorIn[getSide(flag)] = new Wolf(tot, flag, "wolf", this);
break;
}
++cur;
if (cur == 5) cur = 0;
}
void awardGen(Warrior* winWarrior) {
if (gen < 8) return;
gen -= 8;
winWarrior->hp += 8;
}
void printGen() {
printTime();
cout << "50 ";
cout << gen << " elements in " << flag << " headquarter" << endl;
}
void getGen() {
gen += genPool;
genPool = 0;
}
bool checkTaken() {
if (holdEnemy >= 2) {
printTime();
cout << "10 ";
cout << flag << " headquarter was taken" << endl;
return true;
}
return false;
}
} base[2] = {Headquarter("red"), Headquarter("blue")};
void Warrior::marchInBoarder() {
int opposide = oppositeSide(getSide(side));
base[opposide].holdEnemy++;
base[opposide].inEnemy[base[opposide].holdEnemy] = this;
strengthen();
printTime();
cout << "10 ";
printName();
cout << " reached " << base[oppositeSide(getSide(side))].flag << " headquarter with ";
cout << hp << " elements and force " << damage << endl;
inCity->warriorIn[getSide(side)] = NULL;
}
void Weapon::checkBroken() {
if (hp > 0) return;
if (typ == 0)
owner->sword = NULL;
if (typ == 1)
owner->arrow = NULL;
delete this;
}
void Arrow::attack(City* targetCity) {
int enemySide = oppositeSide(getSide(owner->side));
Warrior* targetEnemy = targetCity->warriorIn[enemySide];
if (targetEnemy) {
printTime();
cout << "35 ";
owner->printName();
cout << " shot";
targetEnemy->hp -= damage;
if (targetEnemy->hp <= 0) {
targetEnemy->hp = 0; // enter fake death status
cout << " and killed ";
targetEnemy->printName();
}
cout << endl;
used();
checkBroken();
}
}
void Bomb::checkAndBlast() {
int enemySide = oppositeSide(getSide(owner->side));
Warrior* targetEnemy = owner->inCity->warriorIn[enemySide];
if (!targetEnemy) return;
if (owner->hp <= 0 || targetEnemy->hp <= 0)
return;
bool initiate = false;
if (owner->side == owner->inCity->flag)
initiate = true;
if (owner->inCity->flag == "neutral" && getSide(owner->side) == (owner->inCity->id & 1 ^ 1))
initiate = true;
int ownerSword = 0, enemySword = 0;
if (owner->sword)
ownerSword = owner->sword->damage;
if (targetEnemy->sword)
enemySword = targetEnemy->sword->damage;
if (initiate) {
if (targetEnemy->hp <= owner->damage + ownerSword) return;
if (targetEnemy->typ == "ninja") return;
if (owner->hp > enemySword + floor(0.5L * targetEnemy->damage)) return;
} else {
if (owner->hp > enemySword + targetEnemy->damage) return;
}
printTime();
cout << "38 ";
owner->printName();
cout << " used a bomb and killed ";
targetEnemy->printName();
cout << endl;
delete owner;
delete targetEnemy;
}
int t;
int M, N, T;
City city[25];
void newWarrior() {
base[0].produceWarrior();
base[1].produceWarrior();
}
void checkFlee() {
if (base[0].warriorIn[0])
base[0].warriorIn[0]->flee();
for (int i = 1; i <= N; ++i) {
if (city[i].warriorIn[0])
city[i].warriorIn[0]->flee();
if (city[i].warriorIn[1])
city[i].warriorIn[1]->flee();
}
if (base[1].warriorIn[1])
base[1].warriorIn[1]->flee();
}
bool march() {
bool res = false;
if (city[1].warriorIn[1])
city[1].warriorIn[1]->marchInBoarder();
if (base[0].checkTaken()) res = true;
for (int i = 1; i <= N; ++i) {
Warrior* pre, * nxt;
if (i == 1)
pre = base[0].warriorIn[0];
else
pre = city[i - 1].warriorIn[0];
if (i == N)
nxt = base[1].warriorIn[1];
else
nxt = city[i + 1].warriorIn[1];
if (pre)
pre->printMarch(city + i);
if (nxt)
nxt->printMarch(city + i);
}
if (city[N].warriorIn[0])
city[N].warriorIn[0]->marchInBoarder();
if (base[1].checkTaken()) res = true;
for (int i = N; i >= 1; --i) {
Warrior* pre;
if (i == 1)
pre = base[0].warriorIn[0];
else
pre = city[i - 1].warriorIn[0];
if (pre)
pre->march(city + i);
}
for (int i = 1; i <= N; ++i) {
Warrior* nxt;
if (i == N)
nxt = base[1].warriorIn[1];
else
nxt = city[i + 1].warriorIn[1];
if (nxt)
nxt->march(city + i);
}
return res;
}
void produceGen() {
for (int i = 1; i <= N; ++i)
city[i].produceGen();
}
void takeGen() {
for (int i = 1; i <= N; ++i) {
if (city[i].warriorIn[0] && !city[i].warriorIn[1])
city[i].warriorIn[0]->takeGen(&base[0], 30);
if (city[i].warriorIn[1] && !city[i].warriorIn[0])
city[i].warriorIn[1]->takeGen(&base[1], 30);
}
}
void useArrow() {
if (base[0].warriorIn[0] && base[0].warriorIn[0]->arrow)
base[0].warriorIn[0]->arrow->attack(city + 1);
for (int i = 1; i <= N; ++i) {
Warrior* w1 = city[i].warriorIn[0],
* w2 = city[i].warriorIn[1];
if (w1 && w1->arrow && i < N)
w1->arrow->attack(city + i + 1);
if (w2 && w2->arrow && i > 1)
w2->arrow->attack(city + i - 1);
}
if (base[1].warriorIn[1] && base[1].warriorIn[1]->arrow)
base[1].warriorIn[1]->arrow->attack(city + N);
}
void useBomb() {
for (int i = 1; i <= N; ++i) {
if (city[i].warriorIn[0] && city[i].warriorIn[0]->bomb)
city[i].warriorIn[0]->bomb->checkAndBlast();
if (city[i].warriorIn[1] && city[i].warriorIn[1]->bomb)
city[i].warriorIn[1]->bomb->checkAndBlast();
}
}
void combat() {
int winSide[25];
for (int i = 1; i <= N; ++i) winSide[i] = -2;
for (int i = 1; i <= N; ++i) {
if (!city[i].warriorIn[0] && city[i].warriorIn[1] && city[i].warriorIn[1]->hp == 0)
delete city[i].warriorIn[1];
if (!city[i].warriorIn[1] && city[i].warriorIn[0] && city[i].warriorIn[0]->hp == 0)
delete city[i].warriorIn[0];
if (city[i].warriorIn[0] && city[i].warriorIn[1]) {
if (city[i].flag == "red")
winSide[i] = city[i].warriorIn[0]->attack(city[i].warriorIn[1], false);
else if (city[i].flag == "blue")
winSide[i] = city[i].warriorIn[1]->attack(city[i].warriorIn[0], false);
else if (i & 1)
winSide[i] = city[i].warriorIn[0]->attack(city[i].warriorIn[1], false);
else
winSide[i] = city[i].warriorIn[1]->attack(city[i].warriorIn[0], false);
if (winSide[i] == 0)
city[i].warriorIn[0]->takeGen(base, 40);
if (winSide[i] == 1)
city[i].warriorIn[1]->takeGen(base + 1, 40);
if (winSide[i] != -2)
city[i].updateWinStatus(winSide[i]);
city[i].checkFlag();
}
}
for (int i = N; i >= 1; --i)
if (winSide[i] == 0)
base[0].awardGen(city[i].warriorIn[0]);
for (int i = 1; i <= N; ++i)
if (winSide[i] == 1)
base[1].awardGen(city[i].warriorIn[1]);
base[0].getGen();
base[1].getGen();
}
void printWeapon() {
if (base[0].warriorIn[0])
base[0].warriorIn[0]->printWeapon();
for (int i = 1; i <= N; ++i) {
if (city[i].warriorIn[0])
city[i].warriorIn[0]->printWeapon();
}
for (int i = 1; i <= base[1].holdEnemy; ++i)
base[1].inEnemy[i]->printWeapon();
if (base[1].warriorIn[1])
base[1].warriorIn[1]->printWeapon();
for (int i = 1; i <= base[0].holdEnemy; ++i)
base[0].inEnemy[i]->printWeapon();
for (int i = 1; i <= N; ++i) {
if (city[i].warriorIn[1])
city[i].warriorIn[1]->printWeapon();
}
}
void empty() {
for (int i = 1; i <= N; ++i) {
if (city[i].warriorIn[0])
delete city[i].warriorIn[0];
if (city[i].warriorIn[1])
delete city[i].warriorIn[1];
}
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
cin >> t;
for (int ca = 1; ca <= t; ++ca) {
cout << "Case " << ca << ":" << endl;
tim = 0;
cin >> M >> N >> arrowForce >> loyaltyDecline >> T;
base[0].init(0, M);
base[1].init(N + 1, M);
for (int i = 1; i <= N; ++i)
city[i].init(i);
for (int i = 0; i < 5; ++i)
cin >> cost[i];
for (int i = 0; i < 5; ++i)
cin >> force[i];
int countMin = 0;
while (countMin <= T) {
newWarrior(); // 00
countMin += 5;
if (countMin > T) break;
checkFlee(); // 05
countMin += 5;
if (countMin > T) break;
if (march()) break; // 10
countMin += 10;
if (countMin > T) break;
produceGen(); // 20
countMin += 10;
if (countMin > T) break;
takeGen(); // 30
countMin += 5;
if (countMin > T) break;
useArrow(); // 35
countMin += 3;
if (countMin > T) break;
useBomb(); // 38
countMin += 2;
if (countMin > T) break;
combat(); // 40
countMin += 10;
if (countMin > T) break;
base[0].printGen(); // 50
base[1].printGen(); // 50
countMin += 5;
if (countMin > T) break;
printWeapon(); // 55
++tim;
countMin += 5;
}
empty();
}
return 0;
}