Help me!
查看原帖
Help me!
1128414
ptb15楼主2024/1/20 10:42

为什么没输出,题解看了,主猪清空牌的问题也改了:

#include <bits/stdc++.h>
using namespace std;

struct Pig {
	int prev, next; //以链表的思想存储该猪之前的猪和下一只猪
	int id;//猪的身份0为主猪(MP),1为忠猪(ZP),2为反猪(FP)
	int HP;//当前生命值
	int uc;//该猪累计摸到的牌数(不是当前手中牌数)
	int outid;//对外展示的身份0为未暴露身份,1为已经暴露身份,2为类反猪
	bool zg;//是否装备猪哥连弩
	bool alive;//是否存活
	char card[2005];//该猪摸过的所有牌
	bool whyu[2005];//对应位置的牌是否使用过
	bool why;//是否过出杀
} p[11];

int n, m;
int pai[2001];
int pos = -1, alive_fp;//pos记的是主猪是否存活alive_fp存活反猪数
bool ok;//是否输出信息
bool clear_mark;

void newgame() {//初始化信息
	for (int i = 1; i <= n; i++) {
		p[i].HP = 4;
		p[i].alive = true;
		if (i == 1)
			p[i].prev = n;
		else
			p[i].prev = i - 1;
		if (i == n)
			p[i].next = n;
		else
			p[i].next = i + 1;
	}
}

void inputid() {//读入信息
	for (int i = 1; i <= n; i++) {
		string s;
		cin >> s;
		//判断身份
		if (s == "MP")
			p[i].id = 0,
			    p[i].outid = 1;//主猪肯定会暴露身份
		else if (s == "ZP")
			p[i].id = 1;
		else
			p[i].id = 2;
		for (int j = 1; j <= 4; j++) {//读入手牌
			cin >> s;
			p[i].uc++;
			p[i].card[i] = s[0];
		}
	}
}

void inputcard() {//读入牌堆
	for (int i = 1; i <= m; i++) {
		char s[5];
		scanf("%s", s);
		pai[i] = s[0];
	}
}

int curc;

void givecard(int x) {//编号为x的猪摸一张牌
	p[x].card[++p[x].uc] = pai[curc];
	if (curc != m)
		curc++;//牌堆用完的时候,要一直摸最后一张牌
}

bool peach(int x) {//吃个桃
	if (p[x].HP < 4) {
		p[x].HP++;
		return true;
	}
	return false;
}

void dodge(int x) {//闪
	bool ok = false;
	for (int i = 1; i <= p[x].uc; i++)
		if (p[x].card[i] == 'D' && p[x].whyu[i] == false) {
			p[x].whyu[i] = true;
			ok = true;
			break;
		}
	if (!ok)
		p[x].HP--;
}

void kill_settlement(int cur, int killer) {
	for (int i = 1; i <= p[cur].uc; i++)
		if (p[cur].card[i] == 'P' && p[cur].whyu[i] == false) {
			p[cur].HP++;
			p[cur].whyu[i] = true;
			if (p[cur].HP > 0)return; //该猪摆脱了濒死状态
		}
	p[cur].alive = false; //将该猪标记为死亡
	p[p[cur].prev].next = p[cur].next; //改变出牌顺序
	p[p[cur].next].prev = p[cur].prev;
	if (p[cur].id == 0) { //主猪死亡,反猪胜利
		pos = 1;
		return;
	}
	if (p[cur].id == 2) {
		alive_fp--;
		if (alive_fp == 0) { //先判断游戏胜利条件是否达成,如果达成,就不再摸牌了
			pos = 0;
			return;
		}
		givecard(killer);
		givecard(killer);
		givecard(killer); //杀死反猪的猪摸3张牌
	} else if (p[cur].id == 1 && killer == 1) { //主猪杀死忠猪,弃置所有手牌和装备
		p[1].uc = 0; //清空牌堆
		memset(p[1].card, 0, sizeof(p[1].card));
		memset(p[1].whyu, false, sizeof(p[1].whyu));
		p[1].zg = false; //卸掉装备
		clear_mark = true; //防止牌打出状态被意外改变
	}
}

bool kill(int x) {//杀
	if (p[x].id == 2) {
		if (p[p[x].next].outid == 1 && (p[p[x].next].id == 0 || p[p[x].next].id == 1)) {//反猪会杀忠猪或主猪
			p[x].outid = 1;//打杀会爆身份
			dodge(p[x].next);
			if (p[p[x].next].HP <= 0)
				kill_settlement(p[x].next, x);
			return true;
		}
	} else {
		if (p[x].id == 1) {
			if (p[p[x].next].outid == 1 && p[p[x].next].id == 2) {//忠猪只杀反猪
				p[x].outid = 1;
				dodge(p[x].next);
				if (p[p[x].next].HP <= 0)
					kill_settlement(p[x].next, x);
				return true;
			}
		} else {
			if (p[p[x].next].outid != 0 && (p[p[x].next].id == 2 || p[p[x].next].outid == 2)) {//主猪会对反猪、类反猪出杀;
				p[x].outid = 1;
				dodge(p[x].next);
				if (p[p[x].next].HP <= 0)
					kill_settlement(p[x].next, x);
				return true;
			}
		}
	}
	return false;
}

bool wxkj(int x, int y) {//轮到编号x的猪出无懈可击,锦囊牌的目标为y一方(1代表主猪一方,2代表反猪一方)
	int curp = x;
	do {
		if (p[curp].id != 2 && y == 1) {
			for (int i = 1; i <= p[curp].uc; i++)
				if (p[curp].card[i] == 'J' && p[curp].whyu[i] == false) {
					p[curp].whyu[i] = true;
					if (p[curp].outid != 1)
						p[curp].outid = 1;
					return !wxkj(curp, 2); //轮到相反一方出无懈可击
				}
		}
		if (p[curp].id == 2 && y == 2) {
			for (int i = 1; i <= p[curp].uc; i++)
				if (p[curp].card[i] == 'J' && p[curp].whyu[i] == false) {
					p[curp].whyu[i] = true;
					if (p[curp].outid != 1)
						p[curp].outid = 1;
					return !wxkj(curp, 1);
				}
		}
		curp = p[curp].next;
	} while (curp != x);
	return false;
}

bool nzrq(int x) {
	for (int i = p[x].next; i != x; i = p[i].next) {
		bool used_kill = false;
		if (p[i].outid == 1) //只有暴露身份的猪才有其他猪对它使用无懈可击
			if (wxkj(x, p[i].id == 0 ? 1 : p[i].id))
				continue;
		//需要注意,无懈可击只会免除对一个目标的锦囊效果,并不会使整个锦囊失效
		for (int j = 1; j <= p[i].uc; j++)
			if (p[i].card[j] == 'K' && p[i].whyu[j] == false) {
				p[i].whyu[j] = true;
				used_kill = true;
				break;
			}
		if (!used_kill) {
			p[i].HP--;
			if (p[i].HP <= 0)
				kill_settlement(x, i);
			if (i == 1 && p[x].outid == 0)
				p[x].outid = 2;//没暴露身份,且对主猪造成伤害的猪会被判断为类反猪
			if (pos != -1)
				return true;//一旦游戏结束条件达成,立刻终止锦囊结算过程
		}
	}
	return true;
}

bool wjqf(int x) {
	for (int i = p[x].next; i != x; i = p[i].next) {
		bool used_kill = false;
		if (p[i].outid == 1) //只有暴露身份的猪才有其他猪对它使用无懈可击
			if (wxkj(x, p[i].id == 0 ? 1 : p[i].id))
				continue;
		//无懈可击只会免除对一个目标的锦囊效果,并不会使整个锦囊失效
		for (int j = 1; j <= p[i].uc; j++)
			if (p[i].card[j] == 'D' && p[i].whyu[j] == false) {
				p[i].whyu[j] = true;
				used_kill = true;
				break;
			}
		if (!used_kill) {
			p[i].HP--;
			if (p[i].HP <= 0)
				kill_settlement(i, x);
			if (i == 1 && p[x].outid == 0)
				p[x].outid = 2;//没暴露身份,且对主猪造成伤害的猪会被判断为类反猪
			if (pos != -1)
				return true; //一旦游戏结束条件达成,立刻终止锦囊结算过程
		}
	}
	return true;
}

void battle(int attacker, int defender) {//执行决斗过程
	if (attacker == 1 && p[defender].id == 1) { //忠猪在与主猪决斗时,必定掉血
		p[defender].HP--;
		if (p[defender].HP <= 0)
			kill_settlement(defender, attacker);
		return;
	}
	int curp = defender;
	while (1) {
		bool flag = false;
		for (int i = 1; i <= p[curp].uc; i++)
			if (p[curp].card[i] == 'K' && p[curp].whyu[i] == false) {
				p[curp].whyu[i] = true;
				flag = true;
				break;
			}
		if (flag)curp = (curp == defender ? attacker : defender); //轮到对方弃置杀
		else {
			p[curp].HP--;
			if (p[curp].HP <= 0)
				kill_settlement(curp, attacker == curp ? defender : attacker); //没有受到伤害的一方为伤害来源
			return;
		}
	}
}

bool fight(int cur) {//编号为cur的猪打出一张决斗
	if (p[cur].id == 2) { //反猪决斗时总是找主猪
		p[cur].outid = 1;
		bool flag = wxkj(cur, 1);
		if (!flag)
			battle(cur, 1); //执行决斗过程
		return true;//无论该锦囊是否被无懈,该锦囊都已经被打出
	} else if (p[cur].id == 1) {
		for (int i = p[cur].next; i != cur; i = p[i].next)
			if (p[i].outid == 1 && p[i].id == 2) { //忠猪找跳反的猪决斗
				p[cur].outid = 1;
				bool flag = false;
				if (p[i].outid == 1)
					flag = wxkj(cur, 2);
				if (!flag)
					battle(cur, i);
				return true;
			}
	} else {
		for (int i = p[cur].next; i != cur; i = p[i].next)
			if ((p[i].outid == 1 && p[i].id == 2) || p[i].outid == 2) { //主猪找跳反的猪和类反猪
				bool flag = false;
				if (p[i].outid == 1)
					flag = wxkj(cur, 2);
				if (!flag)
					battle(1, i);
				return true;
			}
	}
	return false;//没有目标可以进行决斗
}

void Game_framework() {
	while (pos == -1)
		for (int i = 1; i <= n; i = p[i].next) {
			givecard(i), givecard(i); //摸牌阶段,摸两张牌
			int kill_num = 0; //没有装备诸葛连弩的猪一回合只能使用一张杀
			for (int j = 1; j <= p[i].uc; j++)
				if (!p[i].whyu[j]) { //没有使用该手牌就使用它
					bool used = false;
					if (p[i].card[j] == 'P')
						used = peach(i); //吃桃
					else if (p[i].card[j] == 'K') { //打出杀
						if (kill_num == 0 || p[i].zg)
							used = kill(i);
						if (used)
							kill_num++;
					} else if (p[i].card[j] == 'F')
						used = fight(i); //打出决斗
					else if (p[i].card[j] == 'Z') {
						used = true; //装备猪哥连弩
						p[i].zg = true;
					} else if (p[i].card[j] == 'N')
						used = nzrq(i); //打出南猪入侵
					else if (p[i].card[j] == 'W')
						used = wjqf(i); //打出万箭齐发
					if (used) {
						if (i == 1 && clear_mark)
							clear_mark = false; //这句话是为了避免一个小bug
						else
							p[i].whyu[j] = true;
						j = 0; //使用一张手牌可能会导致前面的手牌变为可用,因此要从头开始判断每一张牌
					}
					if (!p[i].alive)
						break;//结束它的阶段 
					if (pos != -1)
						break; //一旦达成胜利条件,游戏立刻终止
				}
			if (pos != -1)
				break; //一旦达成胜利条件,游戏立刻终止
		}
	//输出结果阶段开始
	if (pos == 0)
		puts("MP");
	else
		puts("FP");
	for (int i = 1; i <= n; i++) {
		if (!p[i].alive) {
			puts("DEAD");
			continue;
		}
		for (int j = 1; j <= p[i].uc; j++)
			if (!p[i].whyu[j])
				printf("%c ", p[i].card[j]);
		puts("");
	}//输出结果阶段结束
	return;
}

int main() {
	scanf("%d%d", &n, &m);
	newgame();
	inputid();
	inputcard();
	Game_framework();
}
2024/1/20 10:42
加载中...