[SDOI2010]猪国杀
Posted gekoo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 }
以上是关于[SDOI2010]猪国杀的主要内容,如果未能解决你的问题,请参考以下文章