猪国杀题解

· · 个人记录

猪国杀的题解

猪国杀原题

写了三个晚上终于AC了猪国杀,放代码。

不过放代码之前先唠叨唠叨题解。

  1. 游戏开始时身份都是不明确的,除了主猪,因此主猪其实是整个游戏开始和结束的关键,是各个猪跳忠和跳反的开始。除此之外,南猪入侵和万箭齐发也可导致其他猪(主猪)有所反应,但这两张牌不能决定跳忠还是跳反。
  2. 有些牌出出去就会亮明身份,比如杀,决斗,无懈可击。尤其是决斗,只要反猪一拿到决斗,目标必是主猪,同时亮明身份。忠猪拿到决斗,只要场上有已亮明身份的反猪就会决斗,并亮明身份。
  3. 有一种特殊的情况,就是某只猪在自己的回合里挂掉了(比如决斗),这时要对这种情况作出判断,并及时停掉他的回合。
  4. 每次有猪挂掉时不仅要判断摸牌与弃牌,还要判断游戏是否已经结束了。
  5. 看似复杂的无懈可击其实是个补丁,但是无懈要分成无懈其他锦囊牌(即献殷勤)和无懈掉无懈(即表敌意)两种情况。
  6. 凡是用过的牌,不管生没生效,先弃掉。
  7. 题目的bug:如果牌堆里没有牌,要一直摸最后一张(我也不知道这是什么逻辑)。
  8. 南猪入侵和万箭齐发会不会干掉某个人与身份无关,因为是普遍攻击,但当他使用无懈即将生效时要考虑身份问题。
  9. 有一些牌使用后会使得前面的牌变得可用,要从头扫描牌(比如由于万箭齐发、南猪入侵、决斗亮明身份和诸葛连弩使用杀)。

其他的写在代码里吧。

/*写在前面: 
MP 主猪   ZP  忠猪   FP  反猪
基本牌 
    P:桃   K:杀   D:闪 
锦囊牌:
    F决斗
    N南猪入侵
    W万箭齐发
    J无懈可击 
按编号依次行动
1.摸牌:堆顶 2 张,加入队尾 
2.出牌:出任意张除“杀”K以外的牌
            已经摸到过/本来就有Z (pig[i].zgln==1):任意张K;
            pig[i].zgln==0:一张K;

决斗: 
    反贼决斗目标一定是主公,
    忠臣决斗目标一定是表明身份的反贼,
    主公决斗目标是表明身份的反贼或类反贼。
    可能进攻发起者会GG,此时要停止他的回合
    主公认为对面是类反贼,实际上是忠臣,忠臣要牺牲一滴血
    在决斗时,发起者会明确身份;
    在万箭齐发(南蛮入侵)时,可能并不会,但有可能成为类反贼

*/
#include<bits/stdc++.h>
using namespace std;
bool end=false;     //判断游戏是否结束
char paidui[2010]; 
char kn[12]={'0','M'};  //主猪眼里这只猪的身份
int fanzhu,deadfan;   //统计反猪数量和死掉的反猪数量
int n,m;
char sss[10]; //方便输入用的临时字符串
struct juese{
    int life;  //生命
    char id;   //identity身份
    char shoupai[2010];
    int cardsize;//手牌数
    bool zgln;   //诸葛连弩
    int next,last; //前后猪的衔接
}pig[12];

void initpig(int x)      //猪的初始化
{
    for(int j=1;j<2010;j++) 
    pig[x].shoupai[j]='0';   //‘0’表示没有牌
    scanf("%s",sss);
    pig[x].id=sss[0];
    if(pig[x].id=='F')  fanzhu++;
    for(int i=1;i<=4;i++)
    {
        scanf("%s",sss);
        pig[x].shoupai[i]=sss[0];
    }
    pig[x].life=4;
    pig[x].cardsize=4;
    if(x!=n)
    pig[x].next=x+1;
    else
    pig[x].next=1;
    if(x!=1)
    pig[x].last=x-1;
    else
    pig[x].last=n;
    pig[x].zgln=pig[x].dead=false;
    if(x!=1)
    kn[x]='0';   //开始的身份除主猪外都不知道
}

void initcard()    //牌堆初始化
{
    for(int i=1;i<=m;i++)
    {
        scanf("%s",sss);
        paidui[m-i+1]=sss[0];
    }
}

void mp(int x)   //摸牌 
{
    if(!m) m++;  //如果牌堆里没有牌,要一直摸最后一张。
    pig[x].shoupai[++pig[x].cardsize]=paidui[m];
    m--;
}

void js(int x1,int x2)   //击杀 
{
    for(int i=1;i<=pig[x2].cardsize;i++)
    if(pig[x2].shoupai[i]=='P')   //如果有桃就吃,可以免死
    {
        pig[x2].life++;
        pig[x2].shoupai[i]='0';
        return;
    }
    pig[pig[x2].last].next=pig[x2].next;//处理好后继,关系距离问题
    pig[pig[x2].next].last=pig[x2].last;//这个其实一直没用,可以不写
    if(x2==1)  //主猪死了,游戏结束
    {
        end=true;
        return;
    }
    if(pig[x2].id=='F')
    deadfan++;
    if(fanzhu==deadfan)  //反猪死光了,游戏结束
    {
        end=true;
        return;
    }
    if(pig[x2].id=='F')  //杀死反猪摸三张牌
    {
        mp(x1);mp(x1);mp(x1);
    }
    if(pig[x2].id=='Z'&&pig[x1].id=='M')//主猪杀死忠猪弃牌
    {
        pig[x1].cardsize=0;
        pig[x1].zgln=false;//记得弃掉诸葛连弩!!!很重要!
    }
}

void useK(int x1,int x2)   //使用“杀”
{
    for(int i=1;i<=pig[x2].cardsize;i++)
    if(pig[x2].shoupai[i]=='D')
    {
        pig[x2].shoupai[i]='0';
        return;
    }
    pig[x2].life--;
    if(pig[x2].life<=0)  //死了就进入击杀环节
    js(x1,x2);
}

void kill(int x,int j,bool &okk)   //记得回合开始时把okk调成1 
{
    if(okk==0&&pig[x].zgln==false)
    return;
    if(pig[x].id=='M'&&kn[pig[x].next]!='L'&&kn[pig[x].next]!='F')
    return;
    if(pig[x].id=='Z'&&kn[pig[x].next]!='F')
    return;
    if(pig[x].id=='F'&&kn[pig[x].next]!='Z'&&kn[pig[x].next]!='M')
    return;
    pig[x].shoupai[j]='0';
    useK(x,pig[x].next);
    kn[x]=pig[x].id;
    okk=false;
}           //最后记得判断end !!!!

bool wxkj(int x1,int x2,bool x3) //无懈可击
{
    int i=x1;
    while(1)
    {
        if(x3)      //献殷勤
        {
            if(kn[x2]==pig[i].id||(kn[x2]=='M'&&pig[i].id=='Z')||(kn[x2]=='Z'&&pig[i].id=='M'))
            for(int j=1;j<=pig[i].cardsize;j++)
            if(pig[i].shoupai[j]=='J')
            {
                pig[i].shoupai[j]='0';
                kn[i]=pig[i].id;
                return !wxkj(i,x1,0);  //没有猪无懈掉此无懈就生效
            }
        }
        else   //表敌意
        {
            if((kn[x1]=='F'&&(pig[i].id=='M'||pig[i].id=='Z'))||(kn[x1]=='M'||kn[x1]=='Z')&&pig[i].id=='F')
            for(int j=1;j<=pig[i].cardsize;j++)
            if(pig[i].shoupai[j]=='J')
            {
                pig[i].shoupai[j]='0';
                kn[i]=pig[i].id;
                return !wxkj(i,x1,0);
            }
        }
        i=pig[i].next;
        if(i==x1)
        break;
    }

    return false;
}

void usen(int x1)   //南猪入侵
{
    for(int x2=pig[x1].next;x2!=x1;x2=pig[x2].next)
    {
        if(wxkj(x1,x2,1))  //判断是否被无懈
        continue;
        int i=1;
        for(i=1;i<=pig[x2].cardsize;i++)
        {
            if(pig[x2].shoupai[i]=='K')
            {
                pig[x2].shoupai[i]='0';
                break;
            }
        }
        if(i>pig[x2].cardsize)  //没杀掉血
        {
            pig[x2].life--;
            if(x2==1&&kn[x1]=='0')
            kn[x1]='L';  //悲催的类反猪命运
            if(pig[x2].life<=0)
            js(x1,x2);
            if(end)
            return;
        }
    }
}

void usew(int x1)   //万箭齐发
{   //这里直接复制上面的即可,只不过杀变闪
    for(int x2=pig[x1].next;x2!=x1;x2=pig[x2].next)
    {
        if(wxkj(x1,x2,1))  
        continue;
        int i=1;
        for(i=1;i<=pig[x2].cardsize;i++)
        {
            if(pig[x2].shoupai[i]=='D')
            {
                pig[x2].shoupai[i]='0';
                break;
            }
        }
        if(i>pig[x2].cardsize)
        {
            pig[x2].life--;
            if(x2==1&&kn[x1]=='0')
            kn[x1]='L';
            if(pig[x2].life<=0)
            js(x1,x2);
            if(end)
            return;
        }
    }
}

void fight(int x1,int x2)   //决斗
{
    kn[x2]=pig[x2].id;      //先亮身份
    if(wxkj(x1,x2,1))  //再判断无懈
    return;
    int j=1,k=1;
    while(1)   //轮流出杀
    {
        while(pig[x2].shoupai[j]!='K'&&j<=pig[x2].cardsize)
        j++;
        if(j>pig[x2].cardsize)
        {
            pig[x2].life--;
            if(!pig[x2].life)
            js(x1,x2);
            return;
        }
        else pig[x2].shoupai[j]='0';
        while(pig[x1].shoupai[k]!='K'&&k<=pig[x1].cardsize)
        k++;
        if(k>pig[x1].cardsize)
        {
            pig[x1].life--;
            if(!pig[x1].life)
            js(x2,x1);
            return;
        }
        else pig[x1].shoupai[k]='0';
    }
}

void hh()   //进入回合
{
    end=true;
    bool kok=true;
    if(fanzhu)
    end=false;
    if(end)
    return;
    int i=1;
    while(1)
    {
        kok=1;   //开始时可以杀
        mp(i);mp(i);
        for(int j=1;j<=pig[i].cardsize;j++)
        {
            switch(pig[i].shoupai[j])
            {
                case '0':
                    break;
                case 'P':
                    if(pig[i].life!=4)
                    {
                        pig[i].shoupai[j]='0';
                        pig[i].life++;
                    }
                    break;
                case 'K':
                    kill(i,j,kok);
                    if(end)
                    return;
                    break;
                case 'Z':
                    pig[i].zgln=true;
                    pig[i].shoupai[j]='0';
                    j=0;
                    break;
                case 'N':
                    pig[i].shoupai[j]='0';
                    usen(i);
                    if(end)
                    return;
                    j=0;
                    break;
                case 'W':
                    pig[i].shoupai[j]='0';
                    usew(i);
                    if(end)
                    return;
                    j=0;
                    break;
                case 'F':
                    if(pig[i].id=='F')
                    {
                        pig[i].shoupai[j]='0';
                        j=0;kn[i]=pig[i].id;
                        fight(i,1);

                    }
                    if(pig[i].id=='Z')
                    {
                        for(int x2=pig[i].next;x2!=i;x2=pig[x2].next)
                        if(kn[x2]=='F')
                        {
                            pig[i].shoupai[j]='0';
                            j=0;
                            kn[i]=pig[i].id;
                            fight(i,x2);
                            break;
                        }
                    }
                    if(pig[i].id=='M')
                    {
                        for(int x2=pig[i].next;x2!=i;x2=pig[x2].next)
                        {
                            if(kn[x2]=='F'||kn[x2]=='L')
                            {
                                if(pig[x2].id=='Z')   //主猪决斗忠猪,忠猪直接自残掉血
                                {
                                    pig[i].shoupai[j]='0';
                                    j=0;
                                    pig[x2].life--;
                                    if(pig[x2].life<=0)
                                    js(i,x2);
                                }
                                else
                                {
                                    pig[i].shoupai[j]='0';
                                    fight(i,x2);j=0;
                                }

                                break;
                            }
                        }
                    }
                    if(end)
                    return;
                    break;

            }
            if(pig[i].life<=0)
            break;
        }

        i=pig[i].next;
    }

}

int main()
{
//  freopen("P2482_6.in","r",stdin);
    scanf("%d%d",&n,&m);int a;
    for(int i=1;i<=n;i++)
    {
        initpig(i);
    }
    initcard();

    hh();
    if(pig[1].life<=0)
    printf("FP\n");
    else
    printf("MP\n");
    for(int i=1;i<=n;i++)
    {
        if(pig[i].life<=0)
        printf("DEAD\n");
        else
        {
            for(int j=1;j<=pig[i].cardsize;j++)
            if(pig[i].shoupai[j]!='0')
            printf("%c ",pig[i].shoupai[j]);
            printf("\n");
        }
    }
    return 0;
}

喜欢的话点个赞再走叭~