zoukankan      html  css  js  c++  java
  • [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
    ", 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 != '
    ');
    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.
    ", 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!
    ", 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
    ", 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
    ", 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.
    ", array_index);
    264       }
    265       south_attack();
    266       break;
    267     case 'W':  // 万箭齐发
    268       it->free = false;
    269       if (debug) {
    270         printf("%d uses Arrows.
    ", array_index);
    271       }
    272       arrows_shot();
    273       break;
    274     case 'Z':  // 诸葛连弩
    275       it->free = false;
    276       if (debug) {
    277         printf("%d uses Crossbow.
    ", 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
    ", 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.
    ", 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.
    ", 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.
    ", 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.
    ", 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
  • 相关阅读:
    打开CAD时出现“acvmtools.arx ARX命令中发生异常
    VS2010编译错: #error : This file requires _WIN32_WINNT to be #defined at least to 0x0403...的解决方法
    CAD中的相对坐标和绝对坐标
    CAD中的文本编排操作
    使用VS2008,VS2010编译64位的应用程序
    已知两切线和半径画圆弧和圆
    AutoCAD2012启动错误 1308 源文件未找到
    C++中的static修饰的变量和函数
    VS2010创建C++静态链接库创建和使用
    Python中同时用多个分隔符分割字符串的问题
  • 原文地址:https://www.cnblogs.com/gekoo/p/11617602.html
Copyright © 2011-2022 走看看