【程设作业】魔兽世界终极版

题面戳这里

写了半个下午,de了一个晚上。

不知道代码能力有没有提升呜呜呜

呜呜,有点细节挺烦的

特别是射箭的方面

细节明天补上~

估计没有机会重构代码变好看了 数据戳这里

一个花费不少时间的错误是,虚常成员函数和虚成员函数不构成重载关系,导致我在派生类里的从来不会被调用。sigh

结果还是不会用 typedef pair< … , int > PAIRS,当 … 作为 函数指针 时。

不知道有没有契机去优化代码


关于射箭的城市是下一步到达的城市,举一个例子,在同一个周期中,城市 2 的一个武士,前进一步到达城市 3,然后考虑如果城市 4 有敌人并且有箭,会对城市 4 的敌人进行射箭操作。

对于炸弹操作,当自己会死才会爆炸,如果红方蓝方都有炸弹,红方先用

在射箭完成之后不要直接像 Bomb 结算,到攻击阶段的时候再去结算。

对于攻击结算,如果同一个城市的两个人都被射死了,相当于什么事情都不会发生,可以类比炸弹炸死

如果两个人都没有被射死,那么是正常的操作,否则如果其中一个被射死,剩下一个存活,本质上是视作存活的那个人的战斗胜利,相关的胜利结算操作都要进行,比如说可能会进行旗帜的更改。

被攻击杀死仅在战斗开始前没有被箭射死,血量大于0,但是战斗结束后血量为0。

每次用sword攻击只有一轮,也就是主动发起攻击和反击,然后就结算战斗。不像三里面会一直攻击下去。

lion初始没有武器,对于lion死后会给对方的补血,要注意只有在对方没死的情况下才能进行。

因为是两个敌人到达司令部游戏才结束,所以到达司令部的武士也要报告状态,除了报告状态其它就不变了,注意保存一下到达司令部的武士,并且它不会前进,也就是除非第二个到达司令部游戏结束,不然司令部所拥有的士兵的状态不会被改变。


推荐hzwer学长的优雅代码

http://hzwer.com/8689.html


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
#include<iomanip>
#include<cstdlib>
#include<assert.h>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<string>
using std::cerr;
using std::cout;
using std::string;
using std::endl;
using std::vector;
using std::min;
#define DRAGON 0
#define NINJA 1
#define ICEMAN 2
#define LION 3
#define WOLF 4
#define RED 0
#define BLUE 1
#define NOBODY 2
int initHP[5],initATK[5],N,R,K;
bool gameover;
const string warriors_name[5] = {"dragon","ninja","iceman","lion","wolf"};
const string weapon_name[3] = {"sword","bomb","arrow"};
const int L[2][5] = {{ICEMAN,LION,WOLF,NINJA,DRAGON},{LION,DRAGON,NINJA,ICEMAN,WOLF}};
int timeclock;//全局变量 时间戳
bool vis_val[2];//是否被占领过
int element[23];
int lastwin[23];//上一次win的是哪个
int flag[23]; //是不是插旗了
//RED表示红色旗帜
//BLUE表示蓝色旗帜
auto out_time = [](){
printf("%03d:%02d ",timeclock/60,timeclock%60);
};

class Warrior{
int cnt,warriors_id,type;
int curcity,color;
string scolor,stype;
static int total;
protected:
int HP,ATK;
public:
int sword;//武器的攻击力
int arrow;//剩下的次数
int bomb;//是否有炸弹
//sword,bomb,用过的arrow,没用过的arrow
Warrior(string scolor,int type,int warriors_id,int weapon1 = -1,int weapon2 = -1)
:warriors_id(warriors_id),type(type),color((scolor == (string)"red") ? RED : BLUE),
scolor(scolor),stype(warriors_name[type]),
HP(initHP[type]),ATK(initATK[type])
{
curcity = color == RED ? 0 : N+1;
static int tmp[3] = {0,0,0};
tmp[0] = tmp[1] = tmp[2] = 0;
if(weapon1 != -1) tmp[weapon1] = 1;
if(weapon2 != -1) tmp[weapon2] = 1;
sword = tmp[0] ? ATK/5 : 0;
bomb = tmp[1] ? 1 : 0;
arrow = tmp[2] ? 3 : 0;
out_time();
cout << this -> outstr() << " born" << endl;
//(1)武士降生
}
virtual ~Warrior(){}
string outstr() const {return scolor + " " + stype + " " + std::to_string(warriors_id);}
int get_HP() const {return HP;}
int get_ATK() const {return ATK;}
int get_curcity() const {return curcity;}
bool dead() const {return HP==0;}
bool survive() const{return HP>0;}
virtual void Forward(){};
virtual bool runaway(){return false;};
virtual void cheering(){};
virtual void snatch(Warrior* opponent){}

void drop_HP(int val){
HP -= val;
if(HP < 0) HP = 0;
}


virtual void fight(Warrior* opponent){
out_time();
cout << outstr() << " attacked " << opponent -> outstr() << " in city " << this -> curcity << " with " << this -> HP << " elements and force " << this -> ATK << endl;
//(6)武士主动进攻
int val = ATK + sword;
sword = sword * 4 / 5;
opponent -> drop_HP(val);
}//主要是看是否结束
virtual void fight_back(Warrior* opponent){
out_time();
cout << outstr() << " fought back against " << opponent -> outstr() << " in city " << this -> curcity << endl;
//(7)武士反击
int val = ATK / 2 + sword;
sword = sword * 4 / 5;//变钝
opponent -> drop_HP(val);
}

virtual void forward(){
if(this -> color == RED) curcity ++; else curcity--;

if(1 <= curcity && curcity <= N){
out_time();
cout << this -> outstr() << " marched to city " << this -> curcity << " with " << this -> HP << " elements and force " << this -> ATK << endl;
//(3)武士前进到某一城市
}else{
auto opp = [](int x) -> string {return ((x) == RED) ? "blue" : "red";};
assert((this -> color == RED && curcity == N+1) || (this -> color == BLUE && curcity == 0));
out_time();
cout << this -> outstr() << " reached " << opp(this -> color) << " headquarter with " << this -> HP << " elements and force " << this -> ATK << endl;
//(12)武士抵达敌军司令部
if(vis_val[this -> color]) {
out_time();
cout << opp(this -> color) << " headquarter was taken" << endl;
gameover = true;
}vis_val[this -> color] = true;
//(13)司令部被占领
}
}

void report(){
out_time();
cout << outstr() << " has";
if(arrow==0&&sword==0&&bomb==0) cout << " no weapon" ;
bool first=true;
if(arrow) cout << (first?" ":",") << "arrow(" << arrow << ")",first=false;
if(bomb) cout << (first?" ":",") << "bomb",first=false;
if(sword) cout << (first?" ":",") << "sword(" << sword << ")",first=false;
cout << endl;
}//(15)武士报告武器情况

void debug(){
cout << "--------------------debug------------------" << endl;
cout << outstr() << endl;
cout << "ATK/HP:" << ATK << " " << HP << endl;
cout << "SWORD:" << sword << ",BOMB:" << bomb << ",ARROW:" << arrow << endl;
cout << "-------------------------------------------" << endl;
}
virtual bool iswolf() const{return false;}
virtual bool isninja() const{return false;}
virtual bool islion() const{return false;}
virtual void add_morale(double){}
virtual void add_loyalty(int){}
};

class Dragon : public Warrior{
double morale;
public:
Dragon(string color,int warriors_id,double morale):
Warrior(color,DRAGON,warriors_id,warriors_id%3),morale(morale){
cout << "Its morale is " << std::fixed << std::setprecision(2) << morale << endl;
//(1)武士降生
}
void cheering(){
if(morale > 0.8){
out_time();
cout << this -> outstr() << " yelled in city " << this -> get_curcity() << endl;
//(9)武士欢呼
}
}
void add_morale(double val){morale += val;}
};
class Ninja : public Warrior{
public:
Ninja(string color,int warriors_id):
Warrior(color,NINJA,warriors_id,warriors_id%3,(warriors_id+1)%3){
}
bool isninja()const{
return true;
}
void fight_back(Warrior* opponent){
assert(false);
//do nothing
}
};
class Iceman : public Warrior{
int ppp;
public:
Iceman(string color,int warriors_id):
Warrior(color,ICEMAN,warriors_id,warriors_id%3){
ppp = 0;
}
void forward(){
if(!(ppp^=1)){
HP -= 9;
ATK += 20;
if(HP <= 0) HP = 1;
}
this -> Warrior::forward();
}//会减血
};
class Lion : public Warrior{
private:
int loyalty;
public:
Lion(string color,int warriors_id,int loyalty):
Warrior(color,LION,warriors_id),loyalty(loyalty){
cout << "Its loyalty is " << loyalty << endl;
//(1)武士降生
}
bool runaway(){
//到了终点看上去就不会调用这个了
if(loyalty <= 0){
out_time();
cout << outstr() << " ran away" << endl;
//(2)lion逃跑
return true;
}
return false;
}//虚函数,runaway
bool islion() const{return true;}
void add_loyalty(int val){loyalty += val;}
};
class Wolf : public Warrior{
public:
Wolf(string color,int warriors_id):Warrior(color,WOLF,warriors_id){}
bool iswolf()const{return true;}
void snatch(Warrior* opponent){
if(!this -> sword) this -> sword = opponent -> sword;
if(!this -> bomb) this -> bomb = opponent -> bomb;
if(!this -> arrow) this -> arrow = opponent -> arrow;
}
};

class Factory{
private:
int total;
string scolor;
public:
Factory(string scolor):total(0),scolor(scolor){}
~Factory(){}
Warrior* operator () (const int type,const int rem){
int warriors_id = ++total;
Warrior* cur = 0;
if(type==DRAGON) cur = new Dragon(scolor,warriors_id,1.0 * rem / initHP[DRAGON]);
if(type==NINJA) cur = new Ninja(scolor,warriors_id);
if(type==ICEMAN) cur = new Iceman(scolor,warriors_id);
if(type==LION) cur = new Lion(scolor,warriors_id,rem);
if(type==WOLF) cur = new Wolf(scolor,warriors_id);
return cur;
}
};//工厂类

class Headquarter{
private:
const int *lis;
Factory myfactory;
string scolor;
int curCreate,M;//当前要造那个,司令部血量
bool flag_End_Create = false;
public:
Warrior* vec[22];//要么就是NULL,要么就是有,有的话就可以前进
Headquarter(int id,int M0):
lis(id==0?L[0]:L[1]),myfactory(Factory(id==0?"red":"blue")),scolor(id==0?"red":"blue"),M(M0){
curCreate = 0;
for(int i=0;i<22;++i) vec[i] = NULL;
}
~Headquarter(){
for(int i=0;i<=N+1;++i) if(vec[i]){
delete vec[i];
vec[i] = NULL;
}
}
void Create(){
if(M >= initHP[lis[curCreate]]){
int cur = lis[curCreate];
M -= initHP[cur];//开始制造?
curCreate = (curCreate + 1) % 5;
vec[scolor=="red"?0:N+1] = myfactory(cur,M);
}
}
void report() const{
out_time();
cout << M << " elements in " << scolor << " headquarter" << endl;
//(14)司令部报告生命元数量
}
int get_element() const{return M;}
void gain_element(int val){M += val;}
};

namespace War4{

Headquarter *Red,*Blue;
void Create(){
Red -> Create();
Blue -> Create();
}//武士降生

void Runaway(){
for(int i=0;i<=N+1;++i){
if(Red -> vec[i] && Red -> vec[i] -> runaway()){
delete Red -> vec[i];
Red -> vec[i] = NULL;
}
if(Blue -> vec[i] && Blue -> vec[i] -> runaway()){
delete Blue -> vec[i];
Blue -> vec[i] = NULL;
}
}
} // lion逃跑
void Forward(){
for(int i=0;i<=N+1;++i){
//目的地是i的城市
if(i >= 1 && Red -> vec[i-1])
Red -> vec[i-1] -> forward();
if(i <= N && Blue -> vec[i+1])
Blue -> vec[i+1] -> forward();
}

if(Red -> vec[N]){
if(Red -> vec[N+1]) delete Red -> vec[N+1];
Red -> vec[N+1] = Red -> vec[N];
}
for(int i=N-1;i>=0;i--)
Red -> vec[i+1] = Red -> vec[i];//vec[N+1]不动
Red -> vec[0] = NULL;
if(Blue -> vec[1]){
if(Blue -> vec[0]) delete Blue -> vec[0];
Blue -> vec[0] = Blue -> vec[1];
}
for(int i=2;i<=N+1;++i)
Blue -> vec[i-1] = Blue -> vec[i];//vec[0]不动
Blue -> vec[N+1] = NULL;
} // 武士前进到某一城市
void Create_element(){
for(int i=1;i<=N;++i) element[i] += 10;//每个城市产出10个生命元
}
void Get_element(){
auto xornull = [](auto a,auto b){
return (a&&!b)||(b&&!a);
};
for(int i=1;i<=N;++i) if(xornull(Red -> vec[i],Blue -> vec[i])) {
if(Red -> vec[i]) Red -> gain_element(element[i]);
if(Blue -> vec[i]) Blue -> gain_element(element[i]);
string tmp = Red -> vec[i] ? Red -> vec[i] -> outstr() : Blue -> vec[i] -> outstr();
out_time();
cout << tmp << " earned " << element[i] << " elements for his headquarter" << endl;
//(10) 武士获取生命元
element[i] = 0;
}
}
void Arrow(){
//放箭!
auto afunction = [](Warrior* a,Warrior* b){
out_time();
cout << a -> outstr() << " shot";
if(b -> dead()) cout << " and killed " << b -> outstr();
cout << endl;
//(4)武士放箭
};
for(int i=1;i<=N;++i){
if(i<=N && Red -> vec[i] && Blue -> vec[i+1] && Red -> vec[i] -> arrow){
Red -> vec[i] -> arrow -= 1;
Blue -> vec[i+1] -> drop_HP(R);
afunction(Red -> vec[i],Blue -> vec[i+1]);
}
if(i>=1 && Blue -> vec[i] && Red -> vec[i-1] && Blue -> vec[i] -> arrow){
Blue -> vec[i] -> arrow -= 1;
Red -> vec[i-1] -> drop_HP(R);
afunction(Blue -> vec[i],Red -> vec[i-1]);
}
}
}

void Bomb(){
auto check_dead = [](Warrior*a,Warrior*b) -> int{
int HPa = a -> get_HP(),HPb = b -> get_HP();
assert(HPa > 0 && HPb > 0);
HPb -= a -> get_ATK() + a -> sword;
if(HPb>0&&!b->isninja()) HPa -= b -> get_ATK() / 2 + b -> sword;
if(HPa>0&&HPb>0) return NOBODY;
if(HPa<=0) return RED;
return BLUE;
};
auto rev = [](int x)->int{return x==NOBODY?NOBODY:(x==RED?BLUE:RED);};

for(int i=1;i<=N;++i) if(Red -> vec[i] && Blue -> vec[i]){
if(Red -> vec[i] -> dead() || Blue -> vec[i] -> dead()) continue;//如果其中有一个被射死了,就不会用炸弹了
int first = ((flag[i] == RED) || ((flag[i] == NOBODY) && (i % 2 == 1))) ? RED : BLUE;
int who_dead = first==RED ? check_dead(Red -> vec[i],Blue -> vec[i]) : rev(check_dead(Blue -> vec[i],Red -> vec[i]));
bool willed = (Blue->vec[i]->bomb && who_dead == BLUE) || (Red->vec[i]->bomb && who_dead == RED);
if(willed){
out_time();
Warrior* tmp1 = (Red->vec[i]->bomb && who_dead == RED) ? Red -> vec[i] : Blue -> vec[i];
Warrior* tmp2 = (Red->vec[i]->bomb && who_dead == RED) ? Blue -> vec[i] : Red -> vec[i];
cout << tmp1 -> outstr() << " used a bomb and killed " << tmp2 -> outstr() << endl;
//(5)武士使用bomb
delete Red -> vec[i];
delete Blue -> vec[i];
Red -> vec[i] = NULL;
Blue -> vec[i] = NULL;
}
}
}

void Attack(){
auto fight = [](Warrior* a,Warrior* b){//first表示哪个先开始
int prea = a -> get_HP();
int preb = b -> get_HP();
if(a -> survive() && b -> survive()) a -> fight(b);
if(a -> survive() && b -> survive() && !(b -> isninja())) b -> fight_back(a);

auto report8 = [](Warrior *x){
out_time();
cout << x -> outstr() << " was killed in city " << x -> get_curcity() << endl;
//(8)武士战死
};
if(prea>0 && a -> dead()) report8(a);
if(preb>0 && b -> dead()) report8(b);

if(a -> dead() && b -> survive() && a -> islion()) b -> drop_HP(-prea);//加血!
if(b -> dead() && a -> survive() && b -> islion()) a -> drop_HP(-preb);//加血!

if(a -> dead() && b -> survive()) b -> snatch(a);
if(b -> dead() && a -> survive()) a -> snatch(b);
};
static int need[23];//用来表示是否应该奖励生命元
for(int i=1;i<=N;++i){
need[i] = NOBODY;
if(Red -> vec[i] && Blue -> vec[i] && (Red -> vec[i] -> survive() || Blue -> vec[i] -> survive()) ){
//至少一人幸存
int first = (flag[i] == RED || (flag[i] == NOBODY && i % 2 == 1)) ? RED : BLUE;
if(first == RED) fight(Red -> vec[i],Blue -> vec[i]);
else fight(Blue -> vec[i],Red -> vec[i]);
int fred = Red -> vec[i] -> survive();
int fblue = Blue -> vec[i] -> survive();
int whowin = fred ^ fblue ? (fred ? RED : BLUE) : NOBODY;
Red -> vec[i] -> add_morale( whowin == RED ? 0.2 : -0.2 );
Blue -> vec[i] -> add_morale( whowin == BLUE ? 0.2 : -0.2);//dragon的
if(whowin != RED) Red -> vec[i] -> add_loyalty(-K);
if(whowin != BLUE) Blue -> vec[i] -> add_loyalty(-K);
if(first == RED && whowin != BLUE) Red -> vec[i] -> cheering();
if(first == BLUE && whowin != RED) Blue -> vec[i] -> cheering();
need[i] = whowin;
if(whowin == NOBODY){
lastwin[i] = NOBODY;
}else{

string tmp = whowin==RED ? Red -> vec[i] -> outstr() : Blue -> vec[i] -> outstr();
out_time();
cout << tmp << " earned " << element[i] << " elements for his headquarter" << endl;

if(lastwin[i] == whowin && flag[i] != whowin){
flag[i] = whowin;
out_time();
cout << (whowin==RED?"red":"blue") << " flag raised in city " << i << endl;//(11)旗帜升起
}
lastwin[i] = whowin;
}
}
if(Red -> vec[i] && Red -> vec[i] -> dead()){delete Red -> vec[i];Red -> vec[i] = NULL;}
if(Blue -> vec[i] && Blue -> vec[i] -> dead()){delete Blue -> vec[i];Blue -> vec[i] = NULL;}
}

//然后奖励生命元
auto i_will_be_strong = [](Headquarter* H,int i){
if(H -> get_element() >= 8 && H -> vec[i]){
H -> vec[i] -> drop_HP(-8);
H -> gain_element(-8);
}
};
for(int i=1;i<=N;++i) if(need[i] == BLUE) i_will_be_strong(Blue,i);
for(int i=N;i>=1;--i) if(need[i] == RED) i_will_be_strong(Red,i);
//然后收割生命元
for(int i=1;i<=N;++i){
if(need[i] == BLUE) Blue -> gain_element(element[i]);
if(need[i] == RED) Red -> gain_element(element[i]);
if(need[i] != NOBODY) element[i] = 0;
}
};
void Report1(){
Red -> report();
Blue -> report();
};
void Report2(){
for(int i=0;i<=N+1;++i) if(Red -> vec[i]) Red -> vec[i] -> report();
for(int i=0;i<=N+1;++i) if(Blue -> vec[i]) Blue -> vec[i] -> report();
};
void main(){
vis_val[0] = vis_val[1] = false;
gameover = false;
#define mp std::make_pair
void (*func[10])() = {
Create,Runaway,Forward,Create_element,Get_element,
Arrow,Bomb,Attack,Report1,Report2
};
const int addtime[10] = {5,5,10,10,5,3,2,10,5,5};
static int M,T;
scanf("%d%d%d%d%d",&M,&N,&R,&K,&T);
for(int i=0;i<5;++i) scanf("%d",&initHP[i]);
for(int i=0;i<5;++i) scanf("%d",&initATK[i]);
Red = new Headquarter(0,M);
Blue = new Headquarter(1,M);
for(int i=1;i<=N;++i) flag[i] = NOBODY,lastwin[i] = NOBODY,element[i] = 0;
timeclock = 0;
int cur = 0;
while(timeclock <= T){
func[cur]();
timeclock += addtime[cur];
cur = (cur + 1) % 10;
if(gameover){
delete Red;
delete Blue;
break;
}
}
}
};

int main(){
#ifdef LOCAL
FILE *filein = freopen("datapub.in","r",stdin);
FILE *fileout = freopen("myout.out","w",stdout);
#endif
int T;
scanf("%d",&T);
for(int i=1;i<=T;++i){
std::cerr << i << endl;
printf("Case %d:\n",i);
War4::main();
// return 0;
}
#ifdef LOCAL
fclose(filein);
fclose(fileout);
#endif
}

嗯……

以及感叹一下竟然会有学弟翻到这个百度和谷歌都搜不到的网页

本来想着能写点什么给学弟学妹,比如学习方法啊,或者写点科普。然而发现其实自己好像真的没有什么学习方法,相关的感兴趣的东西也只是感兴趣而已其实什么都不会。反正大家都加油啊!

(不过还只是一个想偷偷的发点牢骚和感想的地方呢)

陈老师现在是在UCB当研究员了呢,我呢,依然是对他数年不变的憧憬与膜拜。