爐石傳說
《爐石傳說:魔獸英雄傳》(Hearthstone: Heroes of Warcraft,簡稱爐石傳說)是暴雪娛樂開發的一款集換式卡牌遊戲(如下圖所示)。遊戲在一個戰鬥棋盤上進行,由兩名玩家輪流進行操作,本題所使用的爐石傳說遊戲的簡化規則如下: * 玩家會控制一些角色,每個角色有自己的生命值和攻擊力。當生命值小於等於 0 時,該角色死亡。角色分爲英雄和隨從。
- 玩家各控制一個英雄,遊戲開始時,英雄的生命值爲 30,攻擊力爲 0。當英雄死亡時,遊戲結束,英雄未死亡的一方獲勝。
- 玩家可在遊戲過程中召喚隨從。棋盤上每方都有 7 個可用於放置隨從的空位,從左到右一字排開,被稱爲戰場。當隨從死亡時,它將被從戰場上移除。
- 遊戲開始後,兩位玩家輪流進行操作,每個玩家的連續一組操作稱爲一個回合。
- 每個回合中,當前玩家可進行零個或者多個以下操作:
- 召喚隨從:玩家召喚一個隨從進入戰場,隨從具有指定的生命值和攻擊力。
- 隨從攻擊:玩家控制自己的某個隨從攻擊對手的英雄或者某個隨從。
- 結束回合:玩家聲明自己的當前回合結束,遊戲將進入對手的回合。該操作一定是一個回合的最後一個操作。
- 當隨從攻擊時,攻擊方和被攻擊方會同時對彼此造成等同於自己攻擊力的傷害。受到傷害的角色的生命值將會減少,數值等同於受到的傷害。例如,隨從 X 的生命值爲 HX、攻擊力爲 AX,隨從 Y 的生命值爲 HY、攻擊力爲 AY,如果隨從 X 攻擊隨從 Y,則攻擊發生後隨從 X 的生命值變爲 HX - AY,隨從 Y 的生命值變爲 HY - AX。攻擊發生後,角色的生命值可以爲負數。
本題將給出一個遊戲的過程,要求編寫程序模擬該遊戲過程並輸出最後的局面。
輸入
輸入第一行是一個整數 n,表示操作的個數。接下來 n 行,每行描述一個操作,格式如下:
<action> <arg1> <arg2> …
其中表示操作類型,是一個字符串,共有 3 種:summon表示召喚隨從,attack表示隨從攻擊,end表示結束回合。這 3 種操作的具體格式如下:
* summon :當前玩家在位置召喚一個生命值爲、攻擊力爲的隨從。其中是一個 1 到 7 的整數,表示召喚的隨從出現在戰場上的位置,原來該位置及右邊的隨從都將順次向右移動一位。
* attack :當前玩家的角色攻擊對方的角色 。是 1 到 7 的整數,表示發起攻擊的本方隨從編號,是 0 到 7 的整數,表示被攻擊的對方角色,0 表示攻擊對方英雄,1 到 7 表示攻擊對方隨從的編號。
* end:當前玩家結束本回合。
注意:隨從的編號會隨着遊戲的進程發生變化,當召喚一個隨從時,玩家指定召喚該隨從放入戰場的位置,此時,原來該位置及右邊的所有隨從編號都會增加 1。而當一個隨從死亡時,它右邊的所有隨從編號都會減少 1。任意時刻,戰場上的隨從總是從1開始連續編號。
輸出
輸出共 5 行。
第 1 行包含一個整數,表示這 n 次操作後(以下稱爲 T 時刻)遊戲的勝負結果,1 表示先手玩家獲勝,-1 表示後手玩家獲勝,0 表示遊戲尚未結束,還沒有人獲勝。
第 2 行包含一個整數,表示 T 時刻先手玩家的英雄的生命值。
第 3 行包含若干個整數,第一個整數 p 表示 T 時刻先手玩家在戰場上存活的隨從個數,之後 p 個整數,分別表示這些隨從在 T 時刻的生命值(按照從左往右的順序)。
第 4 行和第 5 行與第 2 行和第 3 行類似,只是將玩家從先手玩家換爲後手玩家。
樣例輸入
8
summon 1 3 6
summon 2 4 2
end
summon 1 4 5
summon 1 2 1
attack 1 2
end
attack 1 1
樣例輸出
0
30
1 2
30
1 2
思路
綜述
比平常訓練的模擬題要簡單許多,按部就班的模擬就能過。
變量解釋
隨從
定義了攻擊力,生命值,位置,排序按照位置來排序
struct Follower{
int attack_power;
int HP;
int position;
Follower(int pos=1,int attack=1,int hp=1):position(pos),HP(hp),attack_power(attack){}
bool operator < (const Follower & P)const {
if(position != P.position) return position < P.position;
}
};
英雄
定義了生命值,隨從數組
struct Hero{
int HP;
vector<Follower> followers;
hero(){
HP = 30;
followers.clear();
}
};
生成隨從
比較簡單,怎麼說的怎麼模擬即可,沒有發現坑點。
void _summon(){
int pos,hp,attack;
cin>>pos>>attack>>hp;
Follower per(pos,attack,hp);
sort(hero[now].followers.begin(),hero[now].followers.end());
for(int i=pos-1;i<hero[now].followers.size();i++){
hero[now].followers[i].position++;
}
hero[now].followers.push_back(per);
sort(hero[now].followers.begin(),hero[now].followers.end());
}
進行攻擊
也是按部就班的模擬;
注意區分隨從攻擊英雄和攻擊隨從的效果是不一樣的;
void _attack(){
int attacker,defender;
cin>>attacker>>defender;
int attack_pos = attacker-1;
int defender_pos = defender-1;
int rival = !now;
int attack_value = hero[now].followers[attack_pos].attack_power;
int defend_value;
if(defender!=0){
defend_value = hero[rival].followers[defender_pos].attack_power;
}else{
defend_value=0;
}
//攻擊方
hero[now].followers[attack_pos].HP -= defend_value;
if(hero[now].followers[attack_pos].HP <= 0 ){
for(int i = attack_pos;i<hero[now].followers.size()-1;i++){
hero[now].followers[i] = hero[now].followers[i+1];
hero[now].followers[i].position--;
}
hero[now].followers.pop_back();
}
//承受攻擊方
if(defender == 0){
//攻擊英雄
hero[rival].HP -= attack_value;
}else{
//攻擊隨從
hero[rival].followers[defender_pos].HP -= attack_value;
if(hero[rival].followers[defender_pos].HP <= 0 ){
for(int i = defender_pos;i<hero[rival].followers.size()-1;i++){
hero[rival].followers[i] = hero[rival].followers[i+1];
hero[rival].followers[i].position--;
}
hero[rival].followers.pop_back();
}
}
}
小技巧
如下所示,定義now變量,因爲只有兩個英雄,則定義英雄數組,hero[2],則hero[now]表示當前操作的英雄,如果出現end,只需要操作now=!now即可
int now = 0;//0代表先手,1代表後手
end操作:
void _end(){
//轉換
now = !now;
}
總結
第一次沒有過,原因是題意沒看清楚,如果A攻擊C,則A收到的傷害是C的攻擊力,C收到的傷害是A的攻擊力。
第二次沒過原因是,如果A攻擊的是英雄,則A不會受到0點傷害值;
我遇到的坑點
- 攻擊英雄和攻擊隨從不一樣
- 英雄的生命值爲0或者負數,輸出兩者任意一個均可
如下圖所示,上面提交的是英雄死亡輸出負數,下面提交的是英雄死亡輸出的是0,都可以過(題外話,下面提交的時間是0ms。。哎不知道爲什麼,絕殺???)
代碼
完整代碼
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
//隨從
struct Follower{
int attack_power;
int HP;
int position;
Follower(int pos=1,int attack=1,int hp=1):position(pos),HP(hp),attack_power(attack){}
bool operator < (const Follower & P)const {
if(position != P.position) return position < P.position;
}
};
//英雄
struct Hero{
int HP;
vector<Follower> followers;
hero(){
HP = 30;
followers.clear();
}
};
int n;
const string actions[3] = {"summon","attack","end"};
Hero hero[2];
int now = 0;//0代表先手,1代表後手
void _summon(){
int pos,hp,attack;
cin>>pos>>attack>>hp;
Follower per(pos,attack,hp);
sort(hero[now].followers.begin(),hero[now].followers.end());
for(int i=pos-1;i<hero[now].followers.size();i++){
hero[now].followers[i].position++;
}
hero[now].followers.push_back(per);
sort(hero[now].followers.begin(),hero[now].followers.end());
}
void _attack(){
int attacker,defender;
cin>>attacker>>defender;
int attack_pos = attacker-1;
int defender_pos = defender-1;
int rival = !now;
int attack_value = hero[now].followers[attack_pos].attack_power;
int defend_value;
if(defender!=0){
defend_value = hero[rival].followers[defender_pos].attack_power;
}else{
defend_value=0;
}
// cout<<"attack:"<<attack_value<<endl;
//攻擊方
hero[now].followers[attack_pos].HP -= defend_value;
if(hero[now].followers[attack_pos].HP <= 0 ){
for(int i = attack_pos;i<hero[now].followers.size()-1;i++){
hero[now].followers[i] = hero[now].followers[i+1];
hero[now].followers[i].position--;
}
hero[now].followers.pop_back();
}
//承受攻擊方
if(defender == 0){
//攻擊英雄
hero[rival].HP -= attack_value;
}else{
//攻擊隨從
hero[rival].followers[defender_pos].HP -= attack_value;
if(hero[rival].followers[defender_pos].HP <= 0 ){
for(int i = defender_pos;i<hero[rival].followers.size()-1;i++){
hero[rival].followers[i] = hero[rival].followers[i+1];
hero[rival].followers[i].position--;
}
hero[rival].followers.pop_back();
}
}
}
void _end(){
//轉換
now = !now;
}
void output(){
//輸出結果
int winner;
if(hero[0].HP > 0 && hero[1].HP <= 0) winner = 1;
else if (hero[0].HP <= 0 && hero[1].HP > 0 ) winner = -1;
else winner = 0;
cout<<winner<<endl;
if(hero[0].HP)cout<<hero[0].HP<<endl;
else cout<<0<<endl;
cout<<hero[0].followers.size();
for(int i=0;i<hero[0].followers.size();i++){
cout<<" "<<hero[0].followers[i].HP;
}
cout<<endl;
if(hero[1].HP)cout<<hero[1].HP<<endl;
else cout<<0<<endl;
cout<<hero[1].followers.size();
for(int i=0;i<hero[1].followers.size();i++){
cout<<" "<<hero[1].followers[i].HP;
}
}
void init(){
hero[0].HP = hero[1].HP = 30;
}
int main(){
cin>>n;
string arg;
init();
while(n--){
cin>>arg;
if(arg == actions[0]){
_summon();
}else if (arg == actions[1]){
_attack();
}else if (arg == actions[2]){
_end();
}
}
output();
}