猪国杀题解
LitApple02 · · 个人记录
猪国杀的题解
猪国杀原题
写了三个晚上终于AC了猪国杀,放代码。
不过放代码之前先唠叨唠叨题解。
- 游戏开始时身份都是不明确的,除了主猪,因此主猪其实是整个游戏开始和结束的关键,是各个猪跳忠和跳反的开始。除此之外,南猪入侵和万箭齐发也可导致其他猪(主猪)有所反应,但这两张牌不能决定跳忠还是跳反。
- 有些牌出出去就会亮明身份,比如杀,决斗,无懈可击。尤其是决斗,只要反猪一拿到决斗,目标必是主猪,同时亮明身份。忠猪拿到决斗,只要场上有已亮明身份的反猪就会决斗,并亮明身份。
- 有一种特殊的情况,就是某只猪在自己的回合里挂掉了(比如决斗),这时要对这种情况作出判断,并及时停掉他的回合。
- 每次有猪挂掉时不仅要判断摸牌与弃牌,还要判断游戏是否已经结束了。
- 看似复杂的无懈可击其实是个补丁,但是无懈要分成无懈其他锦囊牌(即献殷勤)和无懈掉无懈(即表敌意)两种情况。
- 凡是用过的牌,不管生没生效,先弃掉。
- 题目的bug:如果牌堆里没有牌,要一直摸最后一张(我也不知道这是什么逻辑)。
- 南猪入侵和万箭齐发会不会干掉某个人与身份无关,因为是普遍攻击,但当他使用无懈即将生效时要考虑身份问题。
- 有一些牌使用后会使得前面的牌变得可用,要从头扫描牌(比如由于万箭齐发、南猪入侵、决斗亮明身份和诸葛连弩使用杀)。
其他的写在代码里吧。
/*写在前面:
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;
}
喜欢的话点个赞再走叭~