题目:BZOJ1972、洛谷P2482、codevs1834
题目大意:叫你模拟一个叫“猪国杀”的游戏,并要你输出游戏结果。
解题思路:模拟。并没有什么高深的算法,就是模拟,不过东西很多,很容易乱,于是我调了一上午。。。所以建议在写代码时加上注释,并做好写长代码的准备。
其他注意的是,如果牌堆没牌了,就要一直摸最后那一张牌。
C++ Code:
#include<cstdio> #include<cctype> using namespace std; struct player{//玩家信息 bool f,jump,like; int hp,num; bool zhuge,used[2001]; char hd[2001]; }a[11]; int n,m,fz=0,endgame=0,now=0; char paidui[2002]; inline void reset(int p)//更新手牌信息 { int tot=0; for(int i=1;i<=a[p].num;++i) if(!a[p].used[i]) { ++tot; a[p].hd[tot]=a[p].hd[i]; a[p].used[tot]=false; } a[p].num=tot; } inline void printCard(int p){//输出猪的手牌 if(!a[p].hp){ puts("DEAD"); return; } reset(p); for(int i=1;i<=a[p].num;i++) { printf("%c",a[p].hd[i]); if(i!=a[p].num)printf(" "); } printf(" "); } inline void print(){//输出 if(endgame==1)puts("MP");else puts("FP"); for(int i=0;i<n;i++) printCard(i); } inline bool fp(int p){return a[p].f;} inline bool zp(int p){return !a[p].f&&p;} inline bool mp(int p){return !p;} inline void like(int p){if(!a[p].jump)a[p].like=true;} inline void jump(int p){a[p].jump=true;} void init(){//读入 scanf("%d%d",&n,&m); for(int i=0;i<n;++i){ char c[4]; scanf("%s",c); if(c[0]=='F')a[i].f=true,++fz; for(int j=1;j<=4;++j){ scanf(" %c",&a[i].hd[j]); } a[i].hp=a[i].num=4; } for(int i=0;i<m;++i){ char c=getchar(); while(!isalpha(c))c=getchar(); paidui[i]=c; } if(!fz)endgame=1; } inline bool useCard(int p,char card){//(被动地)使用或打出手牌 for(int i=1;i<=a[p].num;++i) if(a[p].hd[i]==card&&!a[p].used[i]){ a[p].used[i]=true; return true; } return false; } inline bool Shan(int i){return useCard(i,'D');} inline bool Tao(int i){return useCard(i,'P');} inline bool Sha(int i){return useCard(i,'K');} inline bool Wuxiekeji(int i){ if(useCard(i,'J')){ jump(i); return true; } return false; } inline void mopai(int p,int v){//摸牌 if(endgame)return; for(int i=1;i<=v;++i){ ++a[p].num; a[p].hd[a[p].num]=paidui[now]; a[p].used[a[p].num]=false; if(now<m-1)++now; } } inline void kill(int to,int from){//击杀、死亡 if(mp(to)){ endgame=2; return; } if(fp(to)){ --fz; if(!fz){ endgame=1; return; } mopai(from,3); } if(zp(to)&&mp(from)){//主猪杀了忠猪,弃光手牌 a[0].num=0; a[0].zhuge=false; } } inline void Kouxie(int to,int from){//掉血 --a[to].hp; if(!a[to].hp){ if(Tao(to))a[to].hp=1; else kill(to,from); } } bool AskWuxie(int from,bool f){//询问无懈可击 int i=from; do{ if(a[i].hp&&a[i].f==f&&Wuxiekeji(i)){ if(!AskWuxie(i,!f))return true; return false; } i=(i+1)%n; }while(i!=from); return false; } bool Wuxie(int p,int k){//无懈可击 if(!a[p].jump&&!mp(p))return false; if(AskWuxie(k,a[p].f))return true; return false; } inline int Juedou(int p,int k){//决斗的过程 if(zp(p)&&mp(k))return 1; if(Wuxie(p,k))return 2; for(;;){ if(!Sha(p))return 1; if(!Sha(k))return 0; } } inline int dis(int p,int k){//判断距离 int d=1; for(int i=(p+1)%n;i!=k;i=(i+1)%n) if(a[i].hp)d++; return d; } inline bool gongji(int p,int k){//杀和决斗的处理 if(fp(p)){//反猪打主猪 if(dis(p,0)==1&&k==1){ jump(p); if(!Shan(0))Kouxie(0,p); return true; } if(k==2){ jump(p); int t=Juedou(0,p); if(t==1)Kouxie(0,p);else if(t==0)Kouxie(p,0); return true; } } if(mp(p)){//主猪攻击 for(int i=(p+1)%n;i!=p;i=(i+1)%n) if(a[i].hp) if(fp(i)&&a[i].jump||a[i].like&&!a[i].jump){ if(dis(p,i)==1&&k==1){ if(!Shan(i))Kouxie(i,p); return true; } if(k==2){ int t=Juedou(i,p); if(t==1)Kouxie(i,p);else if(t==0)Kouxie(p,i); return true; } } }else for(int i=(p+1)%n;i!=p;i=(i+1)%n)//反猪打忠猪or忠猪打反猪 if(a[i].hp){ if((a[p].f^a[i].f)&&a[i].jump){ if(dis(p,i)==1&&k==1){ jump(p); if(!Shan(i))Kouxie(i,p); return true; } if(k==2){ jump(p); int t=Juedou(i,p); if(t==1)Kouxie(i,p);else if(t==0)Kouxie(p,i); return true; } } } return false; } inline void aoe(int p,int l){//AOE牌处理 for(int i=(p+1)%n;i!=p;i=(i+1)%n) if(a[i].hp){ if(!Wuxie(i,p)){ if(l==1){ if(!Sha(i)){ if(mp(i))like(p); Kouxie(i,p); } }else{ if(!Shan(i)){ if(mp(i))like(p); Kouxie(i,p); } } if(endgame)return; } } } inline void huihe(int p){//回合 reset(p); mopai(p,2); bool flag=false; for(int i=1;i<=a[p].num;++i){ if(endgame||!a[p].hp)return; if(a[p].used[i])continue; if(a[p].hd[i]=='P'&&a[p].hp<4)a[p].used[i]=true,++a[p].hp;else if(a[p].hd[i]=='N')a[p].used[i]=true,aoe(p,1),i=0;else if(a[p].hd[i]=='W')a[p].used[i]=true,aoe(p,2),i=0;else if(a[p].hd[i]=='K'&&(!flag||a[p].zhuge)){ if(gongji(p,1)){ flag=true; a[p].used[i]=true; i=0; } }else if(a[p].hd[i]=='F'){ if(gongji(p,2)){ a[p].used[i]=true; i=0; } }else if(a[p].hd[i]=='Z'){ a[p].used[i]=true; if(!a[p].zhuge)a[p].zhuge=true,i=0; } if(endgame)return; } } inline void BigHuihe(){//大回合,玩家依次执行回合 for(int i=0;i<n;++i) if(a[i].hp)huihe(i); } int main(){ init(); while(!endgame)BigHuihe(); print(); return 0; }