[SDOI2010]猪国杀

题目: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("\n");
}
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;
}

 

posted @ 2017-07-14 13:56  Mrsrz  阅读(333)  评论(0编辑  收藏  举报