[SDOI2010]猪国杀

前段时间无聊写的

这题OOP确实好写一点

爆写12KB,写代码3h左右,调试2h左右。。。

其实还是有些不足的,有些需要使用方法的地方直接修改了,而且变量还是放在private里好一些。

代码开头写了点心路历程

应该会写琪露诺的冰雪小屋,那个写完就真该退役了(笑
 
  1 前段时间无聊写的
  2 
  3 这题OOP确实好写一点
  4 
  5 爆写12KB,写代码3h左右,调试2h左右。。。
  6 
  7 其实还是有些不足的,有些需要使用方法的地方直接修改了,而且变量还是放在private里好一些。
  8 
  9 代码开头写了点心路历程
 10 
 11 应该会写琪露诺的冰雪小屋,那个写完就真该退役了(笑
 12 
 13 // ver 1.0: 第一次提交,WA 0.
 14 // ver 2.0: 第二次提交,修改了牌堆堆顶没有从 1 开始的 bug,WA 10.
 15 // ver 3.0: 第三次提交,修改了决斗扣血写反了的bug,WA 30.
 16 // ver 4.0: 第四次提交,修改了无懈可击会在首次循环就退出,导致无法使用无懈可击的 Bug,WA 55.
 17 // ver 5.0: 第五次提交,修改了在主公获胜后仍然获取 bonus 牌的 bug, WA 85.
 18 // ver 6.0: 第六次提交,修改了修改第 3 个 bug 时产生的 bug. 调用扣血方法时用错了对象,AC.
 19 #include <bits/stdc++.h>
 20 #define IT std::vector<Card>::iterator
 21 
 22 struct Card {
 23   char kind;
 24   bool free;
 25 };
 26 
 27 class Input {
 28  public:
 29   void main_input();
 30   void n_m_input();
 31   void status_input();
 32   void heap_input();
 33 };
 34 
 35 class Pig {
 36  public:
 37   Pig();
 38   // 方法
 39   void start_round();  // 开始新回合
 40   void draw_card();    // 抽牌
 41   void play_card();    // 出牌
 42 
 43   void use_card(IT it);     // 使用卡牌
 44   bool find_card(char ch);  // 找牌
 45   void increase_HP();       // 续命
 46   void decrease_HP();       // 被续
 47   void hurt(Pig &that);     // 造成伤害
 48   void pith(Pig &that);     // 杀死
 49   void pithed();            // 被杀死
 50   void jump();              //
 51   bool to_be_dead();        // 濒死
 52   void become_antilike();   // 进入类反
 53   void exit_antilike();     // 退出类反
 54 
 55   bool accessible(char ch);  // 卡牌可用性
 56 
 57   int find_kill();       // 寻找杀的人
 58   void kill(Pig &that);  //
 59   bool kill_respond();   // 回应杀
 60 
 61   int find_duel();       // 寻找决斗对象
 62   void duel(Pig &that);  // 决斗
 63 
 64   void south_attack();          // 南蛮入侵
 65   bool south_attack_respond();  // 回应南蛮入侵
 66 
 67   void arrows_shot();          // 万箭齐发
 68   bool arrows_shot_respond();  // 回应万箭齐发
 69 
 70   bool invulnerability(Pig &that);  // 无懈可击
 71   bool invulnerability_respond();   // 回应无懈可击
 72 
 73   void equip_crossbow();    // 装备诸葛连弩
 74   void unequip_crossbow();  // 卸下诸葛连弩
 75 
 76   // 变量
 77   std::vector<Card> hand;  // 手牌
 78   int array_index;         // 数组下标
 79   char status;             // 身份
 80   int HP;                  // 生命
 81   bool dead;               // 挂了
 82   bool crossbow;           // 装备了诸葛连弩
 83   bool kill_used;          // 出过杀
 84   bool antilike;           // 类反
 85   bool jumped;             // 跳了
 86 };
 87 
 88 int n, m;          // 工 具 人
 89 int king;          // 主公的下标
 90 int anti;          // 反猪数
 91 int heap_top = 1;  // 牌堆顶
 92 char winner;       // 胜利者
 93 char heap[5005];   // 牌堆
 94 bool gameover;     // 游戏结束
 95 Input in;          // 读入对象
 96 Pig pig[15];       // 猪群
 97 
 98 const bool debug = false;  // 调试入口
 99 
100 void print();  // 输出函数
101 
102 signed main() {
103   in.main_input();
104   if (!anti) {
105     winner = 'M';
106     print();
107     return 0;
108   }
109   pig[king].jump();
110   int pig_now = 0;
111   while (1) {  // 主进程
112     pig_now = pig_now % n + 1;
113     if (pig[pig_now].dead) continue;
114     pig[pig_now].start_round();
115     if (gameover) {
116       print();
117       return 0;
118     }
119   }
120 }
121 
122 void print() {
123   printf("%s\n", winner == 'M' ? "MP" : "FP");
124   for (int i = 1; i <= n; ++i) {
125     if (pig[i].dead)
126       puts("DEAD");
127     else {
128       for (IT it = pig[i].hand.begin(); it != pig[i].hand.end(); ++it) {
129         if (it->free) printf("%c ", it->kind);
130       }
131       puts("");
132     }
133   }
134 }
135 
136 void Input::n_m_input() { scanf("%d%d", &n, &m); }
137 
138 void Input::status_input() {
139   char sta[7], tmp;
140   for (int i = 1; i <= n; ++i) {
141     scanf("%s", sta);
142     if (sta[0] == 'M')
143       king = i;
144     else if (sta[0] == 'F')
145       ++anti;
146     pig[i].array_index = i;
147     pig[i].status = sta[0];
148     do {
149       tmp = getchar();
150       if (isalpha(tmp)) pig[i].hand.push_back((Card){tmp, true});
151     } while (tmp != '\n');
152   }
153 }
154 
155 void Input::heap_input() {
156   char tmp = getchar();
157   for (int i = 1; i <= m; ++i) {
158     while (!isalpha(tmp)) tmp = getchar();
159     heap[i] = tmp, tmp = getchar();
160   }
161 }
162 
163 void Input::main_input() {
164   n_m_input();
165   status_input();
166   heap_input();
167   for (int i = m + 1; i <= 5000; ++i) heap[i] = heap[m];
168 }
169 
170 Pig::Pig() {
171   HP = 4;
172   dead = false;
173   crossbow = false;
174   kill_used = false;
175   antilike = false;
176   jumped = false;
177 }
178 
179 void Pig::draw_card() { hand.push_back((Card){heap[heap_top++], true}); }
180 
181 void Pig::increase_HP() { ++HP; }
182 void Pig::decrease_HP() { --HP; }
183 
184 void Pig::equip_crossbow() { crossbow = true; }
185 void Pig::unequip_crossbow() { crossbow = false; }
186 
187 void Pig::pithed() { dead = true; }
188 
189 void Pig::jump() { jumped = true; }
190 
191 void Pig::become_antilike() { antilike = true; }
192 void Pig::exit_antilike() { antilike = false; }
193 
194 bool Pig::kill_respond() { return find_card('D'); }
195 
196 bool Pig::arrows_shot_respond() { return find_card('D'); }
197 
198 bool Pig::south_attack_respond() { return find_card('K'); }
199 
200 void Pig::start_round() {
201   draw_card(), draw_card();  // 抽两张牌
202   if (debug) {
203     printf("now its %d's round.\n", this->array_index);
204     for (int i = 1; i <= n; ++i) {
205       if (pig[i].dead) continue;
206       printf("%d %c %d:", pig[i].array_index, pig[i].status, pig[i].HP);
207       for (auto x : pig[i].hand)
208         if (x.free) printf("%c ", x.kind);
209       puts("");
210     }
211   }
212   play_card();  // 出牌
213   if (kill_used) kill_used = false;
214 }
215 
216 void Pig::play_card() {
217   bool flag = true;
218   while (flag) {
219     flag = false;
220     for (IT it = hand.begin(); it != hand.end(); ++it) {
221       if (it->free && accessible(it->kind)) {  // 可以使用
222         use_card(it);
223         if (dead || gameover) return;
224         flag = true;
225         it = hand.begin() - 1;
226       }
227     }
228   }
229 }
230 
231 void Pig::use_card(IT it) {
232   char kind = it->kind;
233   int tmp;
234   switch (kind) {
235     case 'P':  //
236       if (debug) {
237         printf("%d eats a peach!\n", array_index);
238       }
239       it->free = false;
240       increase_HP();
241       break;
242     case 'K':  //
243       tmp = find_kill();
244       if (!tmp) return;
245       if (debug) {
246         printf("%d uses Kill. -> %d\n", array_index, pig[tmp].array_index);
247       }
248       it->free = false;
249       kill(pig[tmp]);
250       break;
251     case 'F':  // 决斗
252       tmp = find_duel();
253       if (!tmp) return;
254       if (debug) {
255         printf("%d uses Duel. -> %d\n", array_index, pig[tmp].array_index);
256       }
257       it->free = false;
258       duel(pig[tmp]);
259       break;
260     case 'N':  // 南蛮入侵
261       it->free = false;
262       if (debug) {
263         printf("%d uses South Attack.\n", array_index);
264       }
265       south_attack();
266       break;
267     case 'W':  // 万箭齐发
268       it->free = false;
269       if (debug) {
270         printf("%d uses Arrows.\n", array_index);
271       }
272       arrows_shot();
273       break;
274     case 'Z':  // 诸葛连弩
275       it->free = false;
276       if (debug) {
277         printf("%d uses Crossbow.\n", array_index);
278       }
279       equip_crossbow();
280       break;
281   }
282 }
283 
284 bool Pig::find_card(char ch) {
285   for (IT it = hand.begin(); it != hand.end(); ++it) {
286     if (it->kind == ch && it->free) {
287       if (debug) {
288         printf("%d uses %c\n", array_index, it->kind);
289       }
290       it->free = false;
291       return true;
292     }
293   }
294   return false;
295 }
296 
297 void Pig::hurt(Pig &that) {
298   that.decrease_HP();
299   if (debug) {
300     printf("%d hurts %d. left %d %d HP.\n", array_index, that.array_index,
301            that.array_index, that.HP);
302   }
303   if (!that.HP && that.to_be_dead()) {
304     if (debug) {
305       printf("%d killed %d.\n", array_index, that.array_index);
306     }
307     this->pith(that);
308   }
309 }
310 
311 void Pig::pith(Pig &that) {
312   that.pithed();
313   switch (that.status) {
314     case 'M':
315       winner = 'F';
316       gameover = true;
317       break;
318 
319     case 'F':
320       --anti;
321       if (!anti) {
322         winner = 'M';
323         gameover = true;
324         return;
325       }
326       draw_card(), draw_card(), draw_card();
327       break;
328 
329     case 'Z':
330       if (this->status == 'M') {
331         for (IT it = this->hand.begin(); it != this->hand.end(); ++it)
332           it->free = false;
333         this->unequip_crossbow();
334       }
335       break;
336   }
337 }
338 
339 bool Pig::to_be_dead() {
340   for (IT it = hand.begin(); it != hand.end(); ++it) {
341     if (it->kind == 'P' && it->free) {
342       it->free = false;
343       increase_HP();
344       return false;
345     }
346   }
347   return true;
348 }
349 
350 bool Pig::accessible(char ch) {
351   switch (ch) {
352     case 'P':
353       if (HP < 4) return true;
354       break;
355 
356     case 'K':
357       if (find_kill()) return true;
358       break;
359 
360     case 'F':
361       if (find_duel()) return true;
362       break;
363 
364     case 'N':
365       return true;
366       break;
367 
368     case 'W':
369       return true;
370       break;
371 
372     case 'Z':
373       return true;
374       break;
375   }
376   return false;
377 }
378 
379 int Pig::find_kill() {
380   if (kill_used && !crossbow) return 0;
381   switch (status) {
382     case 'M':
383       for (int i = array_index % n + 1; i != array_index; i = i % n + 1) {
384         if (pig[i].dead) continue;
385         if (pig[i].antilike || (pig[i].status == 'F' && pig[i].jumped))
386           return i;
387         else
388           return 0;
389       }
390       break;
391     case 'Z':
392       for (int i = array_index % n + 1; i != array_index; i = i % n + 1) {
393         if (pig[i].dead) continue;
394         if (pig[i].status == 'F' && pig[i].jumped)
395           return i;
396         else
397           return 0;
398       }
399       break;
400     case 'F':
401       for (int i = array_index % n + 1; i != array_index; i = i % n + 1) {
402         if (pig[i].dead) continue;
403         if (pig[i].status != 'F' && pig[i].jumped)
404           return i;
405         else
406           return 0;
407       }
408       break;
409   }
410 }
411 
412 void Pig::kill(Pig &that) {
413   jump();
414   exit_antilike();
415   kill_used = true;
416   if (!that.kill_respond()) hurt(that);
417 }
418 
419 int Pig::find_duel() {
420   switch (status) {
421     case 'M':
422       for (int i = array_index % n + 1; i != array_index; i = i % n + 1) {
423         if (pig[i].dead) continue;
424         if (pig[i].antilike || (pig[i].status == 'F' && pig[i].jumped))
425           return i;
426       }
427       break;
428     case 'Z':
429       for (int i = array_index % n + 1; i != array_index; i = i % n + 1) {
430         if (pig[i].dead) continue;
431         if (pig[i].status == 'F' && pig[i].jumped) return i;
432       }
433       break;
434     case 'F':
435       return king;
436       break;
437   }
438   return 0;
439 }
440 
441 void Pig::duel(Pig &that) {
442   jump();
443   if (status == 'F') exit_antilike();
444   if (invulnerability(that)) return;
445   if (status == 'M' && that.status == 'Z') {
446     hurt(that);
447     return;
448   }
449   int tmp;
450   while (1) {
451     if (!that.find_card('K')) {
452       tmp = 1;
453       break;
454     }
455     if (!find_card('K')) {
456       tmp = 2;
457       break;
458     }
459   }
460   if (tmp == 1)
461     hurt(that);
462   else
463     that.hurt(*this);
464 }
465 
466 void Pig::south_attack() {
467   for (int i = array_index % n + 1; i != array_index; i = i % n + 1) {
468     if (pig[i].dead) continue;
469     if (debug) {
470       printf("%d suffers a South Attack.\n", pig[i].array_index);
471     }
472     if (invulnerability(pig[i])) continue;
473     if (!pig[i].south_attack_respond()) {
474       hurt(pig[i]);
475       if (!jumped && pig[i].status == 'M') become_antilike();
476       if (gameover) return;
477     }
478   }
479 }
480 
481 void Pig::arrows_shot() {
482   for (int i = array_index % n + 1; i != array_index; i = i % n + 1) {
483     if (pig[i].dead) continue;
484     if (invulnerability(pig[i])) continue;
485     if (debug) {
486       printf("%d suffers a Arrow.\n", pig[i].array_index);
487     }
488     if (!pig[i].arrows_shot_respond()) {
489       hurt(pig[i]);
490       if (!jumped && pig[i].status == 'M') become_antilike();
491       if (gameover) return;
492     }
493   }
494 }
495 
496 bool Pig::invulnerability(Pig &that) {
497   if (!that.jumped) {
498     return false;
499   }
500   bool firstloop = true;
501   for (int i = array_index; i != array_index || firstloop; i = i % n + 1) {
502     firstloop = false;
503     if (pig[i].dead) continue;
504     if (pig[i].status == 'M' && that.status == 'F') continue;
505     if (pig[i].status == 'Z' && that.status == 'F') continue;
506     if (pig[i].status == 'F' && that.status == 'M') continue;
507     if (pig[i].status == 'F' && that.status == 'Z') continue;
508     if (pig[i].find_card('J')) {
509       pig[i].jump();
510       return !pig[i].invulnerability_respond();
511     }
512   }
513   return false;
514 }
515 
516 bool Pig::invulnerability_respond() {
517   for (int i = array_index % n + 1; i != array_index; i = i % n + 1) {
518     if (pig[i].dead) continue;
519     if (status == 'M' && pig[i].status == 'Z') continue;
520     if (status == 'Z' && pig[i].status == 'M') continue;
521     if (status == 'Z' && pig[i].status == 'Z') continue;
522     if (status == 'F' && pig[i].status == 'F') continue;
523     if (pig[i].find_card('J')) {
524       pig[i].jump();
525       return !pig[i].invulnerability_respond();
526     }
527   }
528   return false;
529 }
View Code

 

posted @ 2019-10-02 16:00  Gekoo  阅读(...)  评论(...编辑  收藏