rt
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define debug 1
struct cardType;
struct player;
cardType getCard(string name);
void show(int playerId);
void binsijiesuanqian(int playerId);
int getDistance(int player1Id, int player2Id);
void clear() {
system("cls");
}
int clear(player *from, player *to) {
system("cls");
cout<<"三国杀 0.1 版 by liuzhiyu1 (luoguUID 683780)\n\n";
}
// --卡牌--
enum type { // 牌型
jiben, // 基本牌
zhuangbei, // 装备牌
fangju, // 防具牌
jingongma, // 进攻马
fangyuma, // 防御马
pandin, // 判定牌
jinnang, // 锦囊牌
other
};
enum huase { // 花色
meihua,
hongtao,
heitao,
fangkuai
};
enum shenfen { // 身份
zhongchen, // 忠臣
neijian, // 内奸
zhugong, // 主公
fanzei // 反贼
};
enum jineng {
paoxiao, // 【咆哮】你使用【杀】无次数限制
};
enum country {
wei, // 魏
shu, // 蜀
wu, // 吴
qun, // 群
xi, // 西
tang, // 唐
};
enum to {
others, // 对其它所有人使用
self, // 对自己使用
any, // 对任意角色使用
all, // 对所有人使用
noone, // 不能直接使用
};
int cardCount = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct cardType {
int id, num;
string name;
string engName;
type typeName;
int quantity;
int jingong = 0; // only for jingongma
int fangyu = 0; // only for fangyuma
to mubiao = self;
int (*useCard)(player *from, player *to) = clear;
int use(player *from, player *to);
bool operator==(cardType x) {
return id == x.id;
srand((int)time(0));
}
bool operator==(int x) {
return typeName == x;
}
bool operator==(string x) {
return name == x || engName == x;
}
bool operator==(type x) {
return typeName == x;
}
bool operator!=(cardType x) {
return id != x.id;
}
bool operator!=(int x) {
return typeName != x;
}
bool operator!=(string x) {
return name != x && engName != x;
}
cardType(string en, string n, type t, int q, int (*p)(player *from, player *to), to m) :
engName(en), name(n), typeName(t), quantity(q), useCard(p), mubiao(m) {
id = cardCount++;
if (t == jingongma || t == fangyuma) {
cout << "错误:装备牌需要有进攻/防御值(" << n << ")" << endl;
}
}
cardType(string en, string n, type t, int q) :
engName(en), name(n), typeName(t), quantity(q) {
id = cardCount++;
if (t == jingongma || t == fangyuma || t == zhuangbei) {
cout << "错误:装备牌需要有进攻/防御值(" << n << ")" << endl;
}
}
// (英文名,中文名,类型,数量,使用函数)
cardType(string en, string n, type t, int j, int q) :
engName(en), name(n), typeName(t), jingong(j), fangyu(j), quantity(q) {
id = cardCount++;
if (t != fangyuma && t != jingongma && t != zhuangbei) {
cout << "错误:非装备牌不能有进攻/防御值(" << n << ")" << endl;
}
srand((int)time(0));
}
// (英文名,中文名,类型(装备牌),进攻/防御值,数量,使用函数)
cardType() {
}
cardType(string en) :
engName(en) {
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct wujiang {
int id;
string name;
int xueliang;
string engName;
country shili;
vector<jineng> jinengs;
wujiang(string en, string n, int x, country c, vector<jineng> j) :
engName(en), name(n), xueliang(x), shili(c), jinengs(j) {
id = cardCount++;
}
wujiang() {
}
};
wujiang wujiangs[] = {
{"zhangfei", "张飞", 4, shu, {
paoxiao,
}},
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct card {
huase col;
int num;
cardType type;
void show() {
if (type.typeName == jingongma && type.jingong != 1) {
cout << type.name << "(-" << type.jingong - 1 << ")";
} else if (type.typeName == fangyuma && type.fangyu) {
cout << type.name << "(+" << type.fangyu << ")";
} else if (type.name == string("")) {
cout << "无";
} else {
cout << type.name;
}
}
card() {
}
card(cardType t) :
type(t) {
}
card(huase c, int n, cardType t) :
col(c), num(n), type(t) {
}
bool operator==(cardType x) {
return type.id == x.id;
srand((int)time(0));
}
bool operator==(int x) {
return type.id == x;
}
bool operator==(string x) {
return type.name == x || type.engName == x;
}
bool operator!=(cardType x) {
return type.id != x.id;
}
bool operator!=(int x) {
return type.id != x;
srand((int)time(0));
}
bool operator!=(string x) {
return type.name != x && type.engName != x;
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
int playerCount = 0;
struct player {
string name;
vector<card> cards;
int id;
card soupai, // 手牌
zhuangbeiqu,
fangjuqu,
jingongmaqu,
fangyumaqu,
pandinqu;
wujiang jiang;
int shenfen = 0;
int xueliang = 4;
int maxxueliang = 4;
int shanghai(int n, string from) {
if (fangjuqu == (string("tengjia"))) {
if (from != "sha" && from != "nanmanruqin" && from != "wanjianqifa") {
xueliang -= n;
} else if (from == "huosa") {
xueliang -= n + 1;
}
} else {
xueliang -= n;
}
if (xueliang <= 0) {
binsijiesuanqian(id);
if (xueliang < 0) {
cout << name << "死了\n";
}
}
return 0;
}
int huifu(int n, string from) {
xueliang += n;
return 0;
}
bool ask(cardType t, string ss) {
clear();
show(id);
cout << "[" << name << "]:" << ss << "?(请输入编号,输入 -1 取消)";
int choice;
cin >> choice;
if (cards[choice].type == t) {
cards.erase(cards.begin() + choice);
clear();
return true;
} else if (choice == -1) {
clear();
return 0;
} else {
cout << "错误:选择的不是" << t.name << "!" << endl;
clear();
return ask(t, ss);
}
}
int useCard(int n, player *to) {
card tmp;
if (cards[n].type == jingongma) {
tmp = jingongmaqu;
jingongmaqu = cards[n];
cards[n] = tmp;
if (cards[n].type == "") {
cards.erase(cards.begin() + n);
}
return 0;
} else if (cards[n].type == fangyuma) {
tmp = fangyumaqu;
fangyumaqu = cards[n];
cards[n] = tmp;
if(cards[n].type==""){
cards.erase(cards.begin() + n);
}
return 0;
} else if (cards[n].type == pandin) {
tmp = pandinqu;
pandinqu = cards[n];
cards[n] = tmp;
if (cards[n].type == "") {
cards.erase(cards.begin() + n);
}
return 0;
} else if (cards[n].type == fangju) {
tmp = fangjuqu;
fangjuqu = cards[n];
cards[n] = tmp;
if (cards[n].type == "") {
cards.erase(cards.begin() + n);
}
return 0;
} else if (cards[n].type == zhuangbei) {
tmp = zhuangbeiqu;
zhuangbeiqu = cards[n];
cards[n] = tmp;
if (cards[n].type == "") {
cards.erase(cards.begin() + n);
}
return 0;
} else if (cards[n].type.use(this, to) == 0) {
cards.erase(cards.begin() + n);
return 0;
}
return 1;
}
void showCards(bool soupai, bool tab) {
if (!soupai) {
for (int i = 0; i < cards.size(); i++) {
cout << "[" << i << "]";
cards[i].show();
cout << '\t';
}
cout << endl;
} else {
cout << '\t';
}
if (tab) {
cout << '\t';
}
cout << "判定区:";
pandinqu.show();
cout << "\t进攻马:";
jingongmaqu.show();
cout << "\t防御马:";
fangyumaqu.show();
cout << "\t防具:";
fangjuqu.show();
cout << "\t装备:";
zhuangbeiqu.show();
cout << "\n";
}
bool hasJineng(jineng j) {
for (int i = 0; i < jiang.jinengs.size(); i++) {
if (jiang.jinengs[i] == j) {
return true;
}
}
return false;
}
player(string n, int x) :
name(n), xueliang(x), id(playerCount++), maxxueliang(x) {
}
player() :
id(playerCount++) {
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct cardStack {
vector<card> stack;
card getCard() { // 获取一张牌
if (stack.empty()) {
cout << "错误:牌堆为空" << endl;
return card();
}
card c = stack.back();
stack.pop_back();
return c;
}
void putCards();
void xipai() { // 洗牌
random_shuffle(stack.begin(), stack.end());
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
cardStack deck; // 牌堆
vector<player> players = {
// 玩家
{"玩家1", 4},
{"玩家2", 4},
{"玩家3", 4},
{"玩家4", 4},
{"玩家5", 4},
};
int playerNum = 5; // 玩家数量
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
int sha(player *from, player *to) { // 杀
if (getDistance(from->id, to->id) - from->jingongmaqu.type.jingong - from->zhuangbeiqu.type.jingong <= 1) {
if ((*to).ask(getCard("shan"), from->name + "对你使用杀,是否使用闪")) {
clear();
cout << (*to).name << "使用闪挡住了你的杀" << endl;
} else {
(*to).shanghai(1, "sha");
}
return 0;
} else {
cout << "你与" << to->name << "距离过远" << endl;
return 1;
}
}
int leisha(player *from, player *to) { // 雷杀
if ((*to).ask(getCard("shan"), from->name + "对你使用雷杀,是否使用闪")) {
clear();
cout << (*to).name << "使用闪挡住了你的雷杀" << endl;
} else {
(*to).shanghai(1, "leisha");
}
return 0;
}
int huosha(player *from, player *to) { // 火杀
if ((*to).ask(getCard("shan"), from->name + "对你使用火杀,是否使用闪")) {
clear();
cout << (*to).name << "使用闪挡住了你的火杀" << endl;
} else {
(*to).shanghai(1, "huosha");
}
return 0;
}
int shan(player *from, player *to) { // 闪
cout << "不能直接使用闪!" << endl;
return 1;
}
int jiu(player *from, player *to) { // 酒
if ((*to).xueliang < 1) {
(*to).huifu(1, "jiu");
}
return 0;
}
int ZANWEIFU(player *from, player *to) { // 占位符
if (debug)
cout << "错误:卡牌行为未定义\n";
else
cout << "错误" << endl;
return 1;
}
int tao(player *from, player *to) { // 桃
(*to).huifu(1, "tao");
return 0;
}
int none(player *from, player *to) { // 空牌
if (debug) {
cout << "使用了一张空牌" << endl;
}
return 1;
}
int wuzhongshengyou(player *from, player *to) { // 无中生有
for (int i = 0; i < 2; i++) {
(*to).cards.push_back(deck.getCard());
}
return 0;
}
int unuseable(player *from, player *to) { // 不能直接使用的牌
cout << "不能直接使用该牌!" << endl;
return 1;
}
// (英文名,中文名,类型,数量,使用函数)
// (英文名,中文名,类型(装备牌),进攻/防御值,数量,使用函数)
cardType cardTypes[10000] = {
{"sha", "杀", jiben, 30, sha, others},
{"leisha", "雷杀", jiben, 9, leisha, others},
{"huosha", "火杀", jiben, 5, huosha, others},
{"tao", "桃", jiben, 12, any},
{"shan", "闪", jiben, 24, shan, noone},
{"jiu", "酒", jiben, 5, jiu, self},
{"wuxiekeji", "无懈可击", jinnang, 7},
{"wuzhongshengyou", "无中生有", jinnang, 4, wuzhongshengyou, self},
{"sandian", "闪电", pandin, 2, ZANWEIFU, others},
{"zugeliannu", "诸葛连弩", zhuangbei, 1, 2},
{"tengjia", "藤甲", fangju, 2},
{"dilu", "的卢", fangyuma, 1, 1},
{"jueyin", "绝影", fangyuma, 1, 1},
{"dawan", "大宛", jingongma, 1, 1},
{"chitu", "赤兔", jingongma, 1, 1},
{"__end", "__保持此项在最后", other, 0}};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
void cardStack::putCards() { // 生成牌堆
cardType temp;
int i = 0;
while (temp != "__end") {
temp = cardTypes[i];
for (int j = 0; j < temp.quantity; j++) {
stack.push_back(card(cardTypes[i]));
}
i++;
}
}
cardType getCard(string name) {
cardType temp;
int i = 0;
while (temp != "__end") {
temp = cardTypes[i++];
if (temp == name) {
return temp;
}
}
if (debug) {
cout << "错误:未找到卡牌类型" << name << endl;
}
return cardType();
}
// --定义--
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// --游戏流程--
int cardType::use(player *from, player *to) {
if (typeName == jinnang) {
for (int i = to->id; i < playerNum; i++) {
if (players[i].ask(getCard("wuxiekeji"), from->name + "对" + to->name + "使用" + name + ",是否使用无懈可击")) {
clear();
cout << players[i].name << "使用无懈可击挡住了你的" << name << endl;
return 0;
}
}
for (int i = 0; i < to->id; i++) {
if (players[i].ask(getCard("wuxiekeji"), from->name + "对" + to->name + "使用" + name + ",是否使用无懈可击")) {
clear();
cout << players[i].name << "使用无懈可击挡住了你的" << name << endl;
return 0;
}
}
}
return useCard(from, to);
}
int getDistance(int player1Id, int player2Id) { // 计算两个玩家之间的距离,玩家编号从0开始,返回值为正数,玩家首尾相接
return min(abs(player1Id - player2Id), playerNum - abs(player1Id - player2Id)) + players[player1Id].fangyumaqu.type.fangyu;
}
void show(int playerId) {
cout << "你(" << players[playerId].name << "):\n";
cout << "\t血量:" << players[playerId].xueliang << "\t手牌数:" << players[playerId].cards.size() << "\n\t";
players[playerId].showCards(0, 1);
cout << "\n其他玩家:\n";
for (int j = 0; j < playerNum; j++) {
if (j != playerId) {
cout << '\t' << players[j].name << "\t血量:" << players[j].xueliang;
cout << "\t手牌数:" << players[j].cards.size() << "\n\t";
players[j].showCards(1, 0);
}
}
}
void init() {
srand((int)time(NULL));
}
void showPlayers(int playerId) {
cout << '\n';
for (int j = 0; j < playerNum; j++) {
cout << "\t[" << j << "] " << players[j].name << "\t血量:" << players[j].xueliang;
cout << "\t手牌数:" << players[j].cards.size();
cout << "\t与你的距离:" << getDistance(playerId, j) << "\n\t";
players[j].showCards(1, 0);
}
}
void start() {
deck.putCards();
deck.xipai();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < playerNum; j++) {
players[j].cards.push_back(deck.getCard());
}
}
}
void startPandin() {
}
void binsijiesuanqian(int playerId) {
for (int i = playerId; i < playerNum; i++) {
clear();
show(i);
players[i].ask(getCard("tao"), players[playerId].name + "处于濒死状态,是否对其使用桃");
}
for (int i = 0; i < playerId; i++) {
clear();
show(i);
cout << players[playerId].name << "处于濒死状态";
players[i].ask(getCard("tao"), players[playerId].name + "处于濒死状态,是否对其使用桃");
}
}
void chupai(int i) {
int shaCount = 0;
while (1) {
show(i);
cout << "\n"
<< players[i].name << (debug ? "请出牌(-1 跳过,-2 直接获取):" : "请出牌(-1 跳过):");
int choice;
cin >> choice;
clear();
if (choice == -1) {
break;
} else if (choice == -2 && debug) {
string choice;
clear();
cout << "[测试模式] 请输入你想获取的牌名:";
cin >> choice;
players[i].cards.push_back(card(getCard(choice)));
} else if (choice < 0 || choice >= players[i].cards.size()) {
cout << "错误:卡牌编号超出范围\n"
<< endl;
} else {
if (players[i].cards[choice].type == "sha" || players[i].cards[choice].type == "leisha" || players[i].cards[choice].type == "huosha") {
if (shaCount >= 1 && !players[i].hasJineng(paoxiao) && players[i].zhuangbeiqu.type != "zugeliannu" && players[i].zhuangbeiqu.type != "liannu") {
clear();
cout << "你已达到使用杀的上限\n";
continue;
} else if (shaCount >= 4 && !players[i].hasJineng(paoxiao) && players[i].zhuangbeiqu.type != "zugeliannu" && players[i].zhuangbeiqu.type != "liannu") {
clear();
cout << "你已达到使用杀的上限\n";
continue;
}
}
clear();
if (players[i].cards[choice].type.mubiao == any || players[i].cards[choice].type.mubiao == others) {
cout << "请选择使用目标";
showPlayers(i);
int targetPlayer;
cin >> targetPlayer;
if (targetPlayer < 0 || targetPlayer >= playerNum) {
cout << "错误:编号超出范围\n"
<< endl;
} else {
clear();
if (players[i].cards[choice].type == "sha") {
int a = players[i].useCard(choice, &players[targetPlayer]);
if (a == 0) {
shaCount++;
}
} else {
players[i].useCard(choice, &players[targetPlayer]);
}
}
} else if (players[i].cards[choice].type.mubiao == self) {
clear();
players[i].useCard(choice, &players[i]);
} else if (players[i].cards[choice].type.mubiao == all) {
if (debug) {
clear();
cout << "未完成";
}
} else if (players[i].cards[choice].type.mubiao == noone) {
clear();
cout << "不能直接使用" << players[i].cards[choice].type.name << endl;
}
}
}
}
void qipai(int playerId) {
clear();
show(playerId);
int a = players[playerId].cards.size(), b = players[playerId].maxxueliang;
if (a > b) {
cout << "你的手牌数大于血量上限,请输入弃牌数量(最大 " << a << " 张,最小 " << a - b << " 张):";
int choice;
cin >> choice;
if (choice < a - b || choice > a) {
cout << "错误:弃牌数量超出范围\n"
<< endl;
qipai(playerId);
return;
}
cout << "请弃牌(输入手牌编号,用空格分隔):";
for (int i = 0; i < choice; i++) {
int choice;
cin >> choice;
if (choice < 0 || choice >= players[playerId].cards.size()) {
cout << "错误:卡牌编号超出范围\n"
<< endl;
} else {
players[playerId].cards.erase(players[playerId].cards.begin() + choice);
}
}
}
}
void fapai(int playerId) {
for (int i = 0; i < 2; i++) {
players[playerId].cards.push_back(deck.getCard());
}
}
void newterm() {
clear();
startPandin();
for (int i = 0; i < playerNum; i++) {
fapai(i);
clear();
chupai(i);
qipai(i);
clear();
}
}
// --主函数--
int main() {
init();
start();
while (1) {
newterm();
}
}