为什么没输出,题解看了,主猪清空牌的问题也改了:
#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();
}