Month3--炉石传说

题目原文

题目描述

《炉石传说:魔兽英雄传》(Hearthstone: Heroes of Warcraft,简称炉石传说)是暴雪娱乐开发的一款集换式卡牌游戏(如下图所示)。游戏在一个战斗棋盘上进行,由两名玩家轮流进行操作,本题所使用的炉石传说游戏的简化规则如下:


炉石传说.png

 * 玩家会控制一些角色,每个角色有自己的生命值和攻击力。当生命值小于等于 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> ...
  其中<action>表示操作类型,是一个字符串,共有 3 种:summon表示召唤随从,attack表示随从攻击,end表示结束回合。这 3 种操作的具体格式如下:
  * summon <position> <attack> <health>:当前玩家在位置<position>召唤一个生命值为<health>、攻击力为<attack>的随从。其中<position>是一个 1 到 7 的整数,表示召唤的随从出现在战场上的位置,原来该位置及右边的随从都将顺次向右移动一位。
  * attack <attacker> <defender>:当前玩家的角色<attacker>攻击对方的角色 <defender>。<attacker>是 1 到 7 的整数,表示发起攻击的本方随从编号,<defender>是 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

解题思路

建立结构体存储每个随从(英雄)信息,其中包括初始生命(其实可以删去),实时生命和攻击力。定义两个结构体数组存储两名玩家的英雄和随从信息,定义布尔型数组vis1[],vis2[]标记当前随从是否存活(其实也可以删去,用当前生命值是否小于等于零标记。。)。

首先根据读入字符串判断操作类型,再在操作类型中判断当前操作玩家(根据记录的当前"end"个数cnt判断当前操作玩家),并进行相应操作。

需要注意的是死亡随从会被更新,如果在一次攻击中,玩家一随从死亡,先处理的玩家一攻击力改变,无法正确计算二号玩家的随从生命值减少量,所以需要在开始将攻击对象双方的战斗力存入g1,g2中。

实现代码

#include<iostream>
using namespace std;
const int maxn=1010;

bool vis1[8];
bool vis2[8];

struct player{
    
    int g,s;
    int ns; //当前生命状态 

    operator=(const player a){
        
    }
}a[9],b[9];

int main(){
    vis1[0]=vis2[0]=1;
    //初始化 
    a[0].ns=b[0].ns=30;
    a[0].g=b[0].g=0;
    
    int n,cnt=0;
    //标记输赢 
    int  mark=0;
    cin>>n;
    string s;
    for(int p=1;p<=n;p++){
        cin>>s;
        if(s=="end"){
            cnt++;//记录第几回合结束 
            continue;
        }
        
        //召唤随从 
            else if(s=="summon")
            {
                int i;
                cin>>i;
                //判断是玩家一操作回合 
                if(cnt%2==0)
                {
                    if(vis1[i]==0)
                    {
                        //如果召唤位置没有随从 
                        cin>>a[i].g>>a[i].s;
                        a[i].ns=a[i].s;
                        vis1[i]=1;
                    } 
                    else
                    {
                        //如果召唤位置有随从 
                        int j=i;
                        while(vis1[++j]){} 
                            vis1[j]=1;
                        for(int k=j;k>i;k--){
                            a[k].s=a[k-1].s; 
                            a[k].g=a[k-1].g;
                            a[k].ns=a[k-1].ns;
                        } 
                        cin>>a[i].g>>a[i].s;
                        a[i].ns=a[i].s;
                        //vis1[i]=1;
                    }
                }
                else
                {
                    //判断是玩家二操作回合 
                    if(vis2[i]==0)
                    {
                        //如果召唤位置没有随从 
                        cin>>b[i].g>>b[i].s;
                        b[i].ns=b[i].s;
                        vis2[i]=1;
                    } 
                    else
                    {
                        //如果召唤位置有随从 
                        int j=i;
                        while(vis2[++j]){} 
                            vis2[j]=1;
                        for(int k=j;k>i;k--){
                            b[k].s=b[k-1].s; 
                            b[k].g=b[k-1].g;
                            b[k].ns=b[k-1].ns;
                        } 
                        cin>>b[i].g>>b[i].s;
                        b[i].ns=b[i].s;
                        //vis2[i]=1;
                    }
                }
            }
            
            //任意一方发起攻击 
            else if(s=="attack")
            {
                int i1,i2;
                int g1,g2;//记录双方战斗力,防止战斗过程中一方侍从战败,信息清零,导致另一方不掉血 
                
                //此时只需根据判断操作玩家判断随从归属,后续操作相同 
                if(cnt%2==0){
                    cin>>i1>>i2;
                }
                else{
                    cin>>i2>>i1;
                }
                
            //攻击操作开始
                 //对玩家一指定随从进行操作 
                g1=a[i1].g;
                g2=b[i2].g;
                a[i1].ns-=g2;
                if(a[i1].ns<=0){
                    
                    //后手玩家获胜
                    ///判断一号玩家英雄是否阵亡 
                    if(i1==0&&mark==0)
                    {
                        mark=-1;
                    }
                    //游戏未结束 
                    else
                    {
                        int k=i1;
                        while(1)
                        {   
                            //将指定随从后方随从前移 
                            if(k==7)break; 
                            a[k].s=a[k+1].s; 
                            a[k].g=a[k+1].g;
                            a[k].ns=a[k+1].ns;
                            vis1[k]=vis1[k+1];
                            k++;
                        }
                        vis1[7]=0;
                        a[7].s=0;
                        a[7].ns=0;
                        a[7].g=0; 
                        
                    }
                    if(a[i1].ns==0)
                    vis1[i1]=0;
                    
                }
                
                //对玩家二指定随从进行操作 
                b[i2].ns-=g1;
                if(b[i2].ns<=0)
                {
                    //先手玩家获胜 
                    ///判断二号玩家英雄是否阵亡 
                    if(i2==0&&mark==0)
                    {
                        mark=1;
                    }
                    //游戏未结束 
                    else
                    {
                        int k=i2;
                        while(1){
                            //将指定随从后方随从前移 
                            if(!vis2[k])break;
                            b[k].s=b[k+1].s; 
                            b[k].g=b[k+1].g;
                            b[k].ns=b[k+1].ns;
                            vis2[k]=vis2[k+1]; 
                            k++;
                        }
                        b[7].s=0;
                        b[7].ns=0;
                        b[7].g=0; 
                        vis2[7]=0;
                    }
                    if(b[i2].ns==0)
                    vis2[i2]=0; 
                }
            }
        //} 
        
    }
    
    //计算赛后存活随从个数 (不包括英雄) 
    int cnt1=0,cnt2=0;
        for(int i=1;i<=7;i++)
        {
            if(a[i].ns){
                cnt1++;
            }
                
            if(b[i].ns){
                cnt2++; 
            }
                
        } 

        //输出结果 
        cout<<mark<<endl;
        cout<<a[0].ns<<endl;
        cout<<cnt1;
        for(int i=1;i<8;i++)
        {
            if(vis1[i])
            cout<<" "<<a[i].ns;
        }cout<<endl;
        
        cout<<b[0].ns<<endl;
        cout<<cnt2;
        for(int i=1;i<8;i++)
        {
            if(vis2[i])
            cout<<" "<<b[i].ns;
        }cout<<endl;
    return 0;
} 

小结

写题时可以慢一点,不要上手就做,不然可能定义很多不必要的变量,不仅占用空间大,代码的长度也会增加,需要注意的细节也会变多,完成代码耗时较长。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容