zoukankan      html  css  js  c++  java
  • [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("
    ");
    }
    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;
    }
    
  • 相关阅读:
    首次使用随便写点哦
    js中call、apply和bind的区别
    前端的事件流以及事件处理程序
    javascript中数组的深拷贝的方法
    我的第一篇博客
    圆盘转动按钮-react native
    鼠标拖拽删除
    js基础 -----鼠标事件(按下 拖拽)
    清除浮动的几种常用方法
    VUE常见问题解决
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7169954.html
Copyright © 2011-2022 走看看