CSP 201609-3 爐石傳說

爐石傳說

《爐石傳說:魔獸英雄傳》(Hearthstone: Heroes of Warcraft,簡稱爐石傳說)是暴雪娛樂開發的一款集換式卡牌遊戲(如下圖所示)。遊戲在一個戰鬥棋盤上進行,由兩名玩家輪流進行操作,本題所使用的爐石傳說遊戲的簡化規則如下: 在這裏插入圖片描述* 玩家會控制一些角色,每個角色有自己的生命值和攻擊力。當生命值小於等於 0 時,該角色死亡。角色分爲英雄和隨從。

  • 玩家各控制一個英雄,遊戲開始時,英雄的生命值爲 30,攻擊力爲 0。當英雄死亡時,遊戲結束,英雄未死亡的一方獲勝。
  • 玩家可在遊戲過程中召喚隨從。棋盤上每方都有 7 個可用於放置隨從的空位,從左到右一字排開,被稱爲戰場。當隨從死亡時,它將被從戰場上移除。
  • 遊戲開始後,兩位玩家輪流進行操作,每個玩家的連續一組操作稱爲一個回合。
  • 每個回合中,當前玩家可進行零個或者多個以下操作:
  1. 召喚隨從:玩家召喚一個隨從進入戰場,隨從具有指定的生命值和攻擊力。
  2. 隨從攻擊:玩家控制自己的某個隨從攻擊對手的英雄或者某個隨從。
  3. 結束回合:玩家聲明自己的當前回合結束,遊戲將進入對手的回合。該操作一定是一個回合的最後一個操作。
  • 當隨從攻擊時,攻擊方和被攻擊方會同時對彼此造成等同於自己攻擊力的傷害。受到傷害的角色的生命值將會減少,數值等同於受到的傷害。例如,隨從 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();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章