同魔兽世界3,没什么特殊的。但这次我尝试无指针写法,尽自己所能灵活地使用“引用”这个语法糖,成功避免了在调试过程中出现RE的情况。
这次Debug还算轻松,因为少了RE。但由于功能进一步增加,所以出现了不少笔误,改这些一个两个的笔误的点耗去不少和时间。这次Debug用了3个小时,Code用了6个小时,感觉还是慢了。
出错的另一大原因是读题的问题。这里我总结我读题问题如下:
1:ninja不反击,同样,而他的对手在考虑是否使用bomb时不考虑被反击的情况
2:dragon是不死时候就欢呼,并不需要胜利
3:旗帜更换,如果原先插这红方的旗帜,蓝方两连胜之后不是把旗帜降下来变成无主城,而是直接升蓝旗,情况交换亦然(此条最坑,卡掉我一个半小时)
4:lion被吸血的情况一定不能是被射死
剩下的没什么我能想起来读题的问题了。下面上代码:(依旧加了license,转载请注明出处,且这次去掉freopen之后可以直接上OJ跑,懒得弄一眼就能看出来的错误了,所以不要逃课呦!)
//代码有点脏,没有洗调试信息,但我都已加上注释,不影响运行。通过这些脏代码希望大家在看我Debug的过程中能有所收获。
//============================================================================
// Name : WarcraftUltimate.cpp
// Author : MorroWind
// Version : 1.1
// Copyright : ©2018-2018 MorroWind. All rights reserved.
// Description : A solution to WarcraftUltimate with no pointer
//============================================================================
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
const string h[5] = {"dragon", "ninja", "iceman", "lion", "wolf"};
const int red[5] = {2, 3, 4, 1, 0};
const int blue[5] = {3, 0, 1, 2, 4};
const int interval[10] = {5, 5, 10, 10, 5, 3, 2, 10, 5, 5};
int data_set;
int M,N,R,K,T;//M:initial_health N:numbers of cities K:lion's loyalty decrease T:limit time
int cost[5];
int melee[5];
class player;
class warrior{
protected:
int kind;
int id;
int health;
int attack;
bool has_sword;
int sword_attack;
int arrow_num;
bool has_bomb;
double spirit;
void init_add_weapon(int id){
if(id==0){
has_sword = true;
sword_attack = attack * 2 / 10;
if(sword_attack<=0){
sword_attack = 0;
has_sword = false;
}
}else if(id==2) arrow_num = 3;
else if(id==1) has_bomb = true;
}
public:
warrior(): kind(-1), id(-1), health(-1), attack(-1), has_sword(false), sword_attack(0), arrow_num(-1), has_bomb(false), spirit(-1.0){}
warrior(int kind, int id, int h_left):has_sword(false), sword_attack(0), arrow_num(0), has_bomb(false){
this->kind = kind;
this->id = id;
this->health = cost[kind];
this->attack = melee[kind];
if(kind!=3&&kind!=4){
init_add_weapon(id%3);
if(kind==1) init_add_weapon((id+1)%3);
}
if(kind==0) this->spirit = (double)h_left * 1.0 / (cost[0] * 1.0);
else if(kind==3) this->spirit = (double)h_left * 1.0;
else spirit = 0;
}
void report(int col, int hour){//000:55 blue wolf 2 has arrow(2),bomb,sword(23)
printf("%03d:55 ", hour);
if(col==0) cout<<"red "; else cout<<"blue ";
cout<<h[kind];
printf(" %d has ", id);
int cnt=0;
if(arrow_num!=0){
cout<<"arrow("<<arrow_num<<")";
cnt++;
}
if(has_bomb){
if(cnt!=0) cout<<",";
cout<<"bomb";
cnt++;
}
if(has_sword){
if(cnt!=0) cout<<",";
cout<<"sword("<<sword_attack<<")";
cnt++;
}
if(cnt==0) cout<<"no weapon";
cout<<endl;
}
void report_loyalty() {printf("Its loyalty is %.0lf\n", spirit);}
void report_faith() {printf("Its morale is %.2lf\n", spirit);}
void enhance(){
health = (health-9) > 0 ? health-9 : 1;
attack += 20;
}
int get_kind() const{return this->kind;}
int get_id() const{ return this->id;}
int get_loyalty() const{return (int)spirit;}
int get_health() const{return health;}
int get_attack() const{return attack;}
int get_arrow() const{return arrow_num;}
double get_spirit() const {return spirit;}
void fire() {--arrow_num;}
void under_attack(int damage){health -= damage;}
bool can_bomb(warrior &enemy, int ishost){//1 is host while 0 isn't host
bool ret = false;
if(has_bomb){
if(ishost==1 && enemy.health > launch_attack() && enemy.kind!=1 && health <= enemy.counter_attack())
ret = true;
else if(ishost==0 && health <= enemy.launch_attack())
ret = true;
}
return ret;
}
int launch_attack() {return attack + sword_attack;}
int counter_attack() {return attack*5/10 + sword_attack;}
void sword_used() {
sword_attack = sword_attack * 8 / 10;
if(sword_attack <= 0 ){
has_sword = false;
sword_attack = 0;
}
}
void decrease_morale(){spirit -= 0.2;}
void decrease_loyalty(){spirit -= K;}
void increase_morale(){spirit += 0.2;}
void increase_health(int tmp){health += tmp;}
void grab_weapon(warrior &a){
if(!has_sword){
this->has_sword = a.has_sword;
this->sword_attack = a.sword_attack;
}
if(!this->has_bomb) this->has_bomb = a.has_bomb;
if(this->arrow_num==0) this->arrow_num = a.arrow_num;
}
};
class city{
protected:
int id;
int color;//0 red 1 blue -1 unoccupied
warrior red;
warrior blue;
int elements;
int pre;//0: draw 1: red_win 2: blue_win
int now;//-1:no fight 0: draw or the fight wasn't over 1: red_wen 2:blue_win
public:
bool has_red;
bool has_blue;
city():id(-1), color(-1), red(), blue(), elements(0), pre(0), now(-1), has_red(false), has_blue(false){}
void set_id(int id){ this->id = id; }
warrior give_red(){
warrior ret;
if(has_red){
has_red = false;
ret = red;
}
return ret;
}
warrior give_blue(){
warrior ret;
if(has_blue){
has_blue = false;
ret = blue;
}
return ret;
}
void get_red(warrior a){
has_red = false;
if(a.get_id()!=-1) has_red = true;
red = a;
if(id!=0&&a.get_kind()==2&&id%2==0) red.enhance();
}
void get_blue(warrior a){
has_blue = false;
if(a.get_id()!=-1) has_blue = true;
blue = a;
if(id!=N+1&&a.get_kind()==2&&(N+1-id)%2==0) blue.enhance();
}
void flee(int col, int hour){
if(col==0&&has_red&&red.get_kind()==3&&red.get_loyalty()<=0){
has_red = false;
printf("%03d:05 red lion %d ran away\n", hour, red.get_id());
}else if(col==1&&has_blue&&blue.get_kind()==3&&blue.get_loyalty()<=0){
has_blue = false;
printf("%03d:05 blue lion %d ran away\n", hour, blue.get_id());
}
}
void march_report(int time){
if(has_red&&id!=0&&id!=N+1){//000:10 blue lion 1 marched to city 1 with 10 elements and force 5
printf("%03d:10 ", time);
cout<<"red "<<h[red.get_kind()]<<" "<<red.get_id()<<" marched to city ";
cout<<id<<" with "<<red.get_health()<<" elements and force "<<red.get_attack()<<endl;
}else if(has_red&&id==N+1){
printf("%03d:10 ", time);
cout<<"red "<<h[red.get_kind()]<<" "<<red.get_id()<<" reached blue headquarter";
cout<<" with "<<red.get_health()<<" elements and force "<<red.get_attack()<<endl;
}
if(has_blue&&id!=0&&id!=N+1){
printf("%03d:10 ", time);
cout<<"blue "<<h[blue.get_kind()]<<" "<<blue.get_id()<<" marched to city ";
cout<<id<<" with "<<blue.get_health()<<" elements and force "<<blue.get_attack()<<endl;
}else if(has_blue&&id==0){
printf("%03d:10 ", time);
cout<<"blue "<<h[blue.get_kind()]<<" "<<blue.get_id()<<" reached red headquarter";
cout<<" with "<<blue.get_health()<<" elements and force "<<blue.get_attack()<<endl;
}
}
void produce_elements(){elements+=10;}
int give_elements(int col, int hour){//000:30 blue lion 1 earned 10 elements for his headquarter
int ret = elements;
elements = 0;
if(col==0&&ret!=0){
printf("%03d:30 red ", hour); cout<<h[red.get_kind()];
printf(" %d earned %d elements for his headquarter\n", red.get_id(), ret);
}else if(col==1&&ret!=0){
printf("%03d:30 blue ", hour); cout<<h[blue.get_kind()];
printf(" %d earned %d elements for his headquarter\n", blue.get_id(), ret);
}
return ret;
}
void red_report(int hour){//000:55 blue wolf 2 has arrow(2),bomb,sword(23)
if(has_red) red.report(0, hour);
}
void blue_report(int hour){
if(has_blue) blue.report(1, hour);
}
void judge_status(){
if(!(has_red&&has_blue)) now = -1;
else now = 0;
}
void red_fire(city &target, int hour){//更换旗帜等统一到战斗模块中进行
if(has_red&&target.has_blue&&red.get_arrow()>0){
printf("%03d:35 red ", hour); cout<<h[red.get_kind()];
printf(" %d shot", red.get_id());
red.fire();
target.blue.under_attack(R);
if(target.blue.get_health()<=0){
//target.has_blue = false;
printf(" and killed blue "); cout<<h[target.blue.get_kind()];
printf(" %d", target.blue.get_id());
//if(target.now == 0) target.now = 1;
}
printf("\n");
}
}
void blue_fire(city &target, int hour){//000:35 blue dragon 1 shot and killed red lion 4
if(has_blue&&target.has_red&&blue.get_arrow()>0){
printf("%03d:35 blue ", hour); cout<<h[blue.get_kind()];
printf(" %d shot", blue.get_id());
blue.fire();
target.red.under_attack(R);
if(target.red.get_health()<=0){
//target.has_red = false;
printf(" and killed red "); cout<<h[target.red.get_kind()];
printf(" %d", target.red.get_id());
//if(target.now == 0) target.now = 2;
}
printf("\n");
}
}
void shoot_check(){
if(now==0){
if(red.get_health()<=0) has_red = false;
if(blue.get_health()<=0) has_blue = false;
if(has_red&&has_blue) now=0;
else if(has_red&&!has_blue) now=1;
else if(!has_red&&has_blue) now=2;
else if(!has_red&&!has_blue) now=-1;
}else if(now==-1){
if(has_red&&red.get_health()<=0) has_red=false;
if(has_blue&&blue.get_health()<=0) has_blue=false;
}
}
void bomb(int hour){
if(now==0){//战斗尚未结束
int host;
if(color==-1) host = id%2==1 ? 0 : 1;//0 is red and 1 is blue
else host = color;
bool result = red.can_bomb(blue, !host);
if(!result)//the second parameter: 1: is host 0: is not host
result = blue.can_bomb(red, host);
else{//000:38 blue dragon 1 used a bomb and killed red lion 7
now = -1;
has_red = false;
has_blue = false;
printf("%03d:38 red ", hour); cout<<h[red.get_kind()];
printf(" %d used a bomb and killed blue ", red.get_id()); cout<<h[blue.get_kind()]<<" "<<blue.get_id()<<endl;
return;
}
if(result == true){
now = -1;
has_red = false;
has_blue = false;
printf("%03d:38 blue ", hour); cout<<h[blue.get_kind()];
printf(" %d used a bomb and killed red ", blue.get_id()); cout<<h[red.get_kind()]<<" "<<red.get_id()<<endl;
}
}
return;
}
void fight(int hour, player &Red, player &Blue);
int get_result() const {return now;}
void red_gain() {red.increase_health(8);}
void blue_gain() {blue.increase_health(8);}
};
class player{
private:
int order[5]; //the order making warriors
int health; //the health point the commando left
int status; //the warrior id that should be made according to the order
bool canmake;
int counter;
string name;
int num_enemy;
vector<warrior>enemies;
int accumulation;
public:
player(string name, const int *a, int health){
accumulation = 0;
counter = 0;
this->health = health;
for(int i=0; i<5; i++)
*(order+i) = *(a+i);
status = 0;
canmake = false;
if(health>=cost[order[status]]) canmake = true;
this->name = name;
num_enemy = 0;
enemies.clear();
}
~player(){enemies.clear();}
void get_enemy(warrior a){
num_enemy++;
enemies.push_back(a);
}
warrior make(){//return the kind of warrior that has been made recently,and if it can't make any warrior
//then return -1
int type = -1;
warrior p;
if(health >= cost[order[status]]){
health -= cost[order[status]];
type = order[status];
counter++;
if(type==0) p = warrior(0, counter, health);
if(type==1) p = warrior(1, counter, health);
if(type==2) p = warrior(2, counter, health);
if(type==3) p = warrior(3, counter, health);
if(type==4) p = warrior(4, counter, health);
status = (status + 1) % 5;
if(health < cost[order[status]]) {canmake = false;}
}
return p;
}
bool iscan() {
canmake = health >= cost[order[status]];
return canmake;
}
bool isover(){
return num_enemy >= 2;
}
int get_health() {return this->health;}
void get_elements(int ele){this->health+=ele;}
void report(int col, int hour){
for(unsigned int i=0; i<enemies.size(); i++){
enemies[i].report(col, hour);
}
}
void increase_accumulation(int tmp){accumulation+=tmp;}
void award(city &a, int col){
if(col==0){//red
if(a.get_result()==1&&health>=8){
a.red_gain();
health-=8;
}
}else if(col==1){
if(a.get_result()==2&&health>=8){
a.blue_gain();
health-=8;
}
}
}
void clear_accumulation(){
health += accumulation;
accumulation = 0;
}
};
void city::fight(int hour, player &Red, player &Blue){
int red_lion_health = 0, blue_lion_health = 0, tmp = now;
if(!has_blue&&!has_red) now = -1;//处理双方都被箭射死的情况
if(now==0){//先进行战斗
if(red.get_kind()==3) red_lion_health = red.get_health();
if(blue.get_kind()==3) blue_lion_health = blue.get_health();
if(color==0||(color==-1&&id%2==1)){//000:40 red iceman 1 attacked blue lion 1 in city 1 with 20 elements and force 30
blue.under_attack(red.launch_attack());red.sword_used();//001:40 blue dragon 2 fought back against red lion 2 in city 1
printf("%03d:40 red ", hour); cout<<h[red.get_kind()];
printf(" %d attacked blue ", red.get_id()); cout<<h[blue.get_kind()];
printf(" %d in city %d with %d elements and force %d\n", blue.get_id(), id, red.get_health(), red.get_attack());
if(blue.get_health()>0&&blue.get_kind()!=1){
red.under_attack(blue.counter_attack());
blue.sword_used();
printf("%03d:40 blue ", hour); cout<<h[blue.get_kind()];
printf(" %d fought back against red ", blue.get_id()); cout<<h[red.get_kind()];
printf(" %d in city %d\n", red.get_id(), id);
}
}else if(color==1||(color==-1&&id%2==0)){
red.under_attack(blue.launch_attack());blue.sword_used();
printf("%03d:40 blue ", hour); cout<<h[blue.get_kind()];
printf(" %d attacked red ", blue.get_id()); cout<<h[red.get_kind()];
printf(" %d in city %d with %d elements and force %d\n", red.get_id(), id, blue.get_health(), blue.get_attack());
if(red.get_health()>0&&red.get_kind()!=1){
blue.under_attack(red.counter_attack());
red.sword_used();
printf("%03d:40 red ", hour); cout<<h[red.get_kind()];
printf(" %d fought back against blue ", red.get_id()); cout<<h[blue.get_kind()];
printf(" %d in city %d\n", blue.get_id(), id);
}
}
if(red.get_health()>0&&blue.get_health()<=0) now = 1;
else if(red.get_health()<=0&&blue.get_health()>0) now = 2;
else if(red.get_health()>0&&blue.get_health()>0) now = 0;
}
if(now==-1) return;
else if(now==0){
if(red.get_kind()==0) red.decrease_morale();
else if(red.get_kind()==3) red.decrease_loyalty();
if(blue.get_kind()==0) blue.decrease_morale();
else if(blue.get_kind()==3) blue.decrease_loyalty();
pre = now;
if(red.get_kind()==0&&(color==0||(color==-1&&id%2==1))&&red.get_spirit()>0.8)
printf("%03d:40 red dragon %d yelled in city %d\n", hour, red.get_id(), id);
if(blue.get_kind()==0&&(color==1||(color==-1&&id%2==0))&&blue.get_spirit()>0.8)
printf("%03d:40 blue dragon %d yelled in city %d\n", hour, blue.get_id(), id);
}else if(now==1){//red win
has_blue = false;
if(blue.get_kind()==3) red.increase_health(blue_lion_health);
//001:40 red lion 2 was killed in city 1
if(tmp==0){
printf("%03d:40 blue ", hour); cout<<h[blue.get_kind()];
printf(" %d was killed in city %d\n", blue.get_id(), id);
}
//003:40 blue dragon 2 yelled in city 4
if(red.get_kind()==0){
red.increase_morale();
if((color==0||(color==-1&&id%2==1))&&red.get_spirit()>0.8)//003:40 blue dragon 2 yelled in city 4
printf("%03d:40 red dragon %d yelled in city %d\n", hour, red.get_id(), id);
}else if(red.get_kind()==4){
red.grab_weapon(blue);
}
//001:40 blue dragon 2 earned 10 elements for his headquarter
if(elements>0){
Red.increase_accumulation(elements);
printf("%03d:40 red ", hour); cout<<h[red.get_kind()];
printf(" %d earned %d elements for his headquarter\n", red.get_id(), elements);
elements = 0;
}
//004:40 blue flag raised in city 4
if(pre==1){
if(color!=0){
color = 0;
printf("%03d:40 red flag raised in city %d\n", hour, id);
}
}
pre = now;
}else if(now == 2){ //blue win
has_red = false;
if(red.get_kind()==3) blue.increase_health(red_lion_health);
//001:40 red lion 2 was killed in city 1
if(tmp==0){
printf("%03d:40 red ", hour); cout<<h[red.get_kind()];
printf(" %d was killed in city %d\n", red.get_id(), id);
}
//003:40 blue dragon 2 yelled in city 4
if(blue.get_kind()==0){
blue.increase_morale();
//if(hour==41) printf("%d %d ", color, id);
if((color==1||(color==-1&&id%2==0))&&blue.get_spirit()>0.8)//003:40 blue dragon 2 yelled in city 4
printf("%03d:40 blue dragon %d yelled in city %d\n", hour, blue.get_id(), id);
}else if(blue.get_kind()==4){
blue.grab_weapon(red);
}
//001:40 blue dragon 2 earned 10 elements for his headquarter
if(elements>0){
Blue.increase_accumulation(elements);
printf("%03d:40 blue ", hour); cout<<h[blue.get_kind()];
printf(" %d earned %d elements for his headquarter\n", blue.get_id(), elements);
elements = 0;
}
//004:40 blue flag raised in city 4
if(pre==2){
if(color!=1){
color = 1;
printf("%03d:40 blue flag raised in city %d\n", hour, id);
}
}
pre = now;
}
//if(id==15) printf("%d %d %d\n", pre, now, color);
}
vector <city> cities;
warrior global_red;
warrior global_blue;
int main() {
freopen("data.in","r",stdin);
freopen("ans.out","w",stdout);
scanf("%d", &data_set);
int case_time = 1;
while(case_time <= data_set){
cin>>M>>N>>R>>K>>T;
for(int i=0;i<=N+1;i++){
cities.push_back(city());
cities[i].set_id(i);
}
for(int i=0;i<5;i++) cin>>cost[i];
for(int i=0;i<5;i++) cin>>melee[i];
player Red(string("red"), red, M);
player Blue(string("blue"), blue, M);
printf("Case %d:\n", case_time);
for(int timing=0, con=0, hour=-1; timing<=T; timing+=interval[con], con=(con+1)%10){
if(con==0) hour++;
if(con==0){
if(Red.iscan()){
global_red = Red.make();
printf("%03d:%02d red ", hour, timing-60*hour);
cout<<h[global_red.get_kind()]<<" "<<global_red.get_id()<<" born"<<endl;
if(global_red.get_kind()==3) global_red.report_loyalty();
else if(global_red.get_kind()==0) global_red.report_faith();
}else global_red = warrior();
if(Blue.iscan()){
global_blue = Blue.make();
printf("%03d:%02d blue ", hour, timing-60*hour);
cout<<h[global_blue.get_kind()]<<" "<<global_blue.get_id()<<" born"<<endl;
if(global_blue.get_kind()==3) global_blue.report_loyalty();
else if(global_blue.get_kind()==0) global_blue.report_faith();
}else global_blue = warrior();
cities[0].get_red(global_red);
cities[N+1].get_blue(global_blue);
}
if(con==1){
cities[0].flee(0, hour);
for(int i=1;i<=N;i++) {
cities[i].flee(0, hour);
cities[i].flee(1, hour);
}
cities[N+1].flee(1, hour);
}
if(con==2){
for(int i=0;i<=N;i++) cities[i].get_blue(cities[i+1].give_blue());
for(int i=N+1;i>=1;i--) cities[i].get_red(cities[i-1].give_red());
cities[0].march_report(hour);
if(cities[0].has_blue) Red.get_enemy(cities[0].give_blue());
bool isover = Red.isover();
if(Red.isover()) printf("%03d:10 red headquarter was taken\n", hour);
for(int i=1;i<=N;i++) cities[i].march_report(hour);
cities[N+1].march_report(hour);
if(cities[N+1].has_red) Blue.get_enemy(cities[N+1].give_red());
isover = Blue.isover() || isover;
if(Blue.isover()) printf("%03d:10 blue headquarter was taken\n", hour);
if(isover) break;
for(int i=1;i<=N;i++) cities[i].judge_status();
}
if(con==3){
for(int i=1; i<=N; i++)
cities[i].produce_elements();
}
if(con==4){
for(int i=1; i<=N; i++){
if(cities[i].has_blue==false&&cities[i].has_red==true)
Red.get_elements(cities[i].give_elements(0,hour));
else if(cities[i].has_blue==true&&cities[i].has_red==false)
Blue.get_elements(cities[i].give_elements(1,hour));
}
}
if(con==5){
cities[1].red_fire(cities[2], hour);
for(int i=2;i<=N-1;i++){
cities[i].red_fire(cities[i+1], hour);
cities[i].blue_fire(cities[i-1], hour);
}
cities[N].blue_fire(cities[N-1], hour);
for(int i=1; i<=N; i++)
cities[i].shoot_check();
}
if(con==6){
for(int i=1;i<=N;i++)
cities[i].bomb(hour);
}
if(con==7){
for(int i=1; i<=N; i++)
cities[i].fight(hour, Red, Blue);
for(int i=1; i<=N; i++)
Red.award(cities[i], 0);
for(int i=N; i>=1; i--)
Blue.award(cities[i], 1);
Red.clear_accumulation();
Blue.clear_accumulation();
}
if(con==8){
printf("%03d:50 %d elements in red headquarter\n", hour, Red.get_health());
printf("%03d:50 %d elements in blue headquarter\n", hour, Blue.get_health());
}
if(con==9){
for(int i=1; i<=N; i++) cities[i].red_report(hour);
Blue.report(0, hour);
Red.report(1, hour);
for(int i=1; i<=N; i++) cities[i].blue_report(hour);
}
}
++case_time;
cities.clear();
}
return 0;
}