题目: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;
}