// Please use UTF-8 encoding so that the comments can be displayed correctly. // 标注TODO的是你需要完善的地方 #include #include #include #include #include #include #include #include #include #include using namespace std; class Card : public string { public: static const int N_CARD_VALUES; static const int N_CARD_SUITS; static const string CARD_VALUES[]; static const string CARD_SUITS[]; Card(const char* str) :string(str) {}; Card() :string() {}; Card(string str) :string(str) {}; static vector get_new_deck(); // 重载操作符,使得牌面可以比较大小 bool operator <(const Card &other) const; bool operator >(const Card &other) const; }; class DDZPlayer { protected: string name; // 玩家名 int position; // 你的位置编号,0为地主,1为地主下家,2为地主上家 vector hand; // 手牌 int prePos; //上一个出牌的人位置编号,-1表示还没有人出过牌 vector prePlay; // 上一个出牌的人出了什么牌? bool legal(vector cards); // 判断当前打出cards是否合法 void substractFromHand(vector cards); // 从当前手牌中删去cards中的牌 public: DDZPlayer(string name); // 构造函数,初始化玩家名 string getName(); virtual void draw(Card card); // 将cards中的牌加入手牌 virtual void draw(vector cards); // 将cards中的牌加入手牌 virtual void setPosition(int pos); // 初始化用,决定地主后设置 virtual void showHand(); // 打印手牌 virtual void observed(int pos, vector cards); // 观测到玩家出牌 virtual vector play(); // 轮到自己时决定出什么牌 bool leftNoCard(); // 返回是否打完了牌? int *one(int *a, int *former, int in); int *two(int *a, int *former, int in); int *three(int *a, int *former, int in); int *boom(int *a, int *former, int in); int *threeplusone(int *a, int *former, int in); int *threeplustwo(int *a, int *former, int in); int *shunzi(int *a, int *former, int in, int m); int *plane(int *a, int *former, int in, int wing, int m); int *boomplus(int *a, int *former, int in, int wing); int *liandui(int *a, int *former, int in, int m); string exchange(int num); int exchange(Card card); void mystyle(vector cards, int *a); void yourstyle(vector &cards, int a[]); }; class DDZGame { private: static int my_random(int i); // 洗牌时用到的随机函数 vector players; // 保存三个玩家的指针 void showCards(vector cards); // 输出一组牌 public: DDZGame(DDZPlayer *p1, DDZPlayer *p2, DDZPlayer *p3); // 构造函数 void run(); // 执行游戏流程 }; class DDZHumanPlayer : public DDZPlayer { public: DDZHumanPlayer(string name) : DDZPlayer(name) {}; vector play(); }; // ---------------------------------------------------------------------------- /*int main() { srand(0x5942B); DDZPlayer p1("Alice"), p2("Bob"), p3("Charlie"); DDZGame g(&p1, &p2, &p3); g.run(); system("pause"); return 0; } */ int main() { string name; cout << "Please input your name:" << endl; getline(cin, name); srand(0x5942B); DDZPlayer p1("Alice"), p2("Bob"); DDZHumanPlayer p3(name); DDZGame g(&p1, &p2, &p3); g.run(); system("pause"); return 0; } bool Card::operator <(const Card &other) const { int a = -1, b = -1; for (int i = 0; i < N_CARD_VALUES; ++i) { if (*this == CARD_VALUES[i]) a = i; if (other == CARD_VALUES[i]) b = i; } return a < b; } bool Card::operator >(const Card &other) const { return other < *this; } DDZPlayer::DDZPlayer(string name) : name(name) { // 玩家类的构造函数 prePos = -1; } string DDZPlayer::getName() { return name; } bool DDZPlayer::legal(vector cards) { // 通过上家打出的牌prePlay和手牌hand判断cards作为打出牌是否合法 // TODO:(第二题)请补全这个函数 int handcard[15] = { 0 }, giveout[15] = { 0 }, former[15] = { 0 }, num_g = 0, num_f = 0; vector newcard; mystyle(hand, handcard); mystyle(prePlay, former); mystyle(cards, giveout); for (int i = 0; i < 15; i++) num_g += giveout[i]; for (int i = 0; i < 15; i++) num_f += former[i]; //防止他瞎几把出牌 for (int i = 0; i < 15; i++) if (handcard[i] < giveout[i]) return false; //上家不出牌或者自家要不起时 if (num_g == 0 && (prePos == position || prePos == -1)) return false; if (num_g == 0) return true; if (prePos == position || prePos == -1) { if (num_g == 1) return true; if (num_g == 2) { int in = -1; if (giveout[14] == 1 && giveout[13] == 1) return true; for (int i = 0; i < 15; i++) if (giveout[i] == 2) in = i; if (in != -1) return true; } if (num_g == 3) { int in = -1; for (int i = 0; i < 15; i++) if (giveout[i] == 3) in = i; if (in != -1) return true; } if (num_g == 4) { int in = -1; for (int i = 0; i < 15; i++) if (giveout[i] >= 3) in = i; if (in >= 0) return true; } if (num_g == 5) { int in = -1, len = 0; for (int i = 0; i < 15; i++) if (giveout[i] == 3) in = i; if (in >= 0) return true; for (int k = 0; k < 12; k++) { if (giveout[k] != 0) len++; else len = 0; if (len == num_g) { in = k - 4; break; } } if (in >= 0) return true; } if (num_g >= 6) { int in = -1, wing = 0; for (int i = 0; i < 11; i++) { if (giveout[i] == 3 && giveout[i + 1] == 3) { in = i; break; } } for (int i = 0; i < 15; i++) if (giveout[i] == 2) wing += 2; for (int i = 0; i < 15; i++) if (giveout[i] == 1) wing += 1; if (in >= 0 && (wing == 2 || wing == 4)) return true; ////////////////////////////////////////// wing = 0; int i = -1; for (int i = 0; i < 13; i++) if (giveout[i] == 4) { in = i; break; } for (int i = 0; i < 15; i++) if (giveout[i] == 2) wing += 2; for (int i = 0; i < 15; i++) if (giveout[i] == 1) wing += 1; if (in >= 0 && (wing == 2 || wing == 4)) return true; //////////////////////////////////////////// wing = 0; for (int i = 0; i < 12; i++) { if (giveout[i] == 1) wing++; else wing = 0; if (wing == num_g && wing >= 5) return true; } /////////////////////////////////////////// wing = 0; for (int i = 0; i < 12; i++) { if (giveout[i] == 2) wing++; else wing = 0; if (wing == num_g / 2 && wing >= 3) return true; } } return false; } //王炸不需要约束 if (num_g == 2 && giveout[13] == 1 && giveout[14] == 1) return true; if (num_f == 2 && former[13] == 1 && former[14] == 1 && num_g != 0) return false; //普通炸弹分类讨论 if (num_g == 4 || num_f == 4) { int boom_g = -1, boom_f = -1; for (int i = 0; i < 15; i++) if (giveout[i] == 4) boom_g = i; for (int i = 0; i < 15; i++) if (former[i] == 4) boom_f = i; if (boom_f > boom_g) return false; if (boom_f < boom_g) return true; } //牌数要一样 if (num_f != num_g) return false; //单张,对子,三张裸奔 if (num_f == 1 && !(cards > prePlay)) return false; if (num_f == 2 && !(cards > prePlay)) return false; if (num_f == 3 && !(cards > prePlay)) return false; //三带一 if (num_f == 4) { int in = -1; for (int i = 0; i < 15; i++) if (former[i] == 3) in = i; if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(newcard, threeplusone(handcard, former, in)); if (newcard.size() == 0) return false; } } if (num_f == 5) { int in = -1, len = 0; for (int i = 0; i < 15; i++) if (former[i] == 3) in = i; if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(newcard, threeplustwo(handcard, former, in)); if (newcard.size() == 0) return false; } for (int k = 0; k < 12; k++) { if (former[k] != 0) len++; else len = 0; if (len == num_f) { in = k - 4; break; } } if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(newcard, shunzi(handcard, former, in, num_f)); if (newcard.size() == 0) return false; } } if (num_f >= 6) { int in = -1, wing = 0; for (int i = 0; i < 11; i++) { if (former[i] == 3 && former[i + 1] == 3) { in = i; break; } } for (int i = 0; i < 15; i++) if (former[i] == 2) wing = 2; for (int i = 0; i < 15; i++) if (former[i] == 1) wing = 1; if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(newcard, plane(handcard, former, in, wing, num_f)); if (newcard.size() == 0) return false; } ////////////////////////////////////////// wing = 0; for (int i = 0; i < 13; i++) if (former[i] == 4) { in = i; break; } for (int i = 0; i < 15; i++) if (former[i] == 2) wing = 2; if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(newcard, boomplus(handcard, former, in, wing)); if (newcard.size() == 0) return false; } //////////////////////////////////////////// wing = 0; for (int i = 0; i < 12; i++) { if (former[i] != 0) wing++; else wing = 0; if (wing == num_f) { in = i - num_f + 1; for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(newcard, shunzi(handcard, former, in, num_f)); if (newcard.size() == 0) return false; } } /////////////////////////////////////////// wing = 0; for (int i = 0; i < 12; i++) { if (former[i] == 2) wing++; else wing = 0; if (wing == num_f / 2) { in = i - num_f / 2 + 1; for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(newcard, liandui(handcard, former, in, num_f)); if (newcard.size() == 0) return false; } } } return true; } void DDZPlayer::substractFromHand(vector cards) { // 这个函数从hand中删除cards。假设cards中的牌hand可以拿得出来(否则会出错)。 sort(hand.begin(), hand.end(), greater()); sort(cards.begin(), cards.end(), greater()); vector::iterator i = hand.begin(), k = cards.begin(); for (vector::iterator j = hand.begin(); j != hand.end(); ++j) { if (k == cards.end() || *k != *j) *(i++) = *j; else if (k != cards.end()) ++k; } hand.erase(i, hand.end()); } void DDZPlayer::showHand() { // 输出玩家名和手牌。 cout << name << " holds: "; for (vector::iterator i = hand.begin(); i != hand.end(); ++i) { cout << *i << " "; } cout << endl; } void DDZPlayer::draw(Card card) { // 将card加入手牌 hand.push_back(card); sort(hand.begin(), hand.end(), greater()); } void DDZPlayer::draw(vector cards) { // 将cards中的牌加入手牌 hand.insert(hand.end(), cards.begin(), cards.end()); sort(hand.begin(), hand.end(), greater()); } void DDZPlayer::setPosition(int pos) { position = pos; } void DDZPlayer::observed(int pos, vector cards) { // 将上一个出牌的人和出了什么牌记录下来。 // 如果你想记录更多的信息供你的策略使用,可以改动这个函数。 // 例如,记录已经有哪些牌被打出(记牌器),以推测场上是否可能还存在炸弹。 if (cards.size() == 0) return; prePos = pos; prePlay = cards; } int DDZPlayer::exchange(Card card) { if (card == "3") return 0; if (card == "4") return 1; if (card == "5") return 2; if (card == "6") return 3; if (card == "7") return 4; if (card == "8") return 5; if (card == "9") return 6; if (card == "10") return 7; if (card == "J") return 8; if (card == "Q") return 9; if (card == "K") return 10; if (card == "A") return 11; if (card == "2") return 12; if (card == "joker") return 13; if (card == "JOKER") return 14; } string DDZPlayer::exchange(int num) { string str[] = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2", "joker", "JOKER" }; return str[num]; } void DDZPlayer::mystyle(vector cards,int *a) { for (int i = 0; i < cards.size(); i++) a[exchange(cards[i])]++; } void DDZPlayer::yourstyle(vector &cards, int a[]) { for (int i = 0; i < 15; i++) for (int p = 0; p < a[i]; p++) cards.push_back(exchange(i)); } vector DDZPlayer::play() { // 轮到你出牌,返回打出的牌。 // TODO:(第一题)请完善这个函数 // 如果你使用不同的数据结构进行处理,你可以现将hand变量转换为你使用的结构, // 处理过后再将打出的牌转换为vector,存入card变量。 vector cards; int handcard[15] = { 0 }, *former; former = new int[15]; for (int i = 0; i < 15; i++) former[i] = 0; mystyle(hand, handcard); /* for (int i = 0; i < hand.size(); i++) cout << hand[i] << " "; */ if (prePos == position || prePos == -1) { // 出任意牌 int flag = 0, len = 0; for (int i = 0; i < 10; i++) if (handcard[i] == 3 && handcard[i + 1] == 3 && handcard[i + 2] == 3) { int two[3] = { 0 }; former[i] = 3; former[i + 1] = 3; former[i + 2] = 3; handcard[i] -= 3; handcard[i + 1] -= 3; handcard[i + 2] -= 3; for (int k = 0; k < 15; k++) { if (handcard[k] == 2) { two[flag] = k; flag++; } if (flag == 3) { for (int i = 0; i < 3; i++) { handcard[two[i]] -= 2; former[two[i]] += 2; } yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } } flag = 0; for (int k = 0; k < 15; k++) { if (handcard[k] == 1) { two[flag] = k; flag++; } if (flag == 3) { for (int i = 0; i < 3; i++) { handcard[two[i]] -= 1; former[two[i]] += 1; } yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } } yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } len = 0; flag = 0; for (int i = 0; i < 11; i++) if (handcard[i] == 3 && handcard[i + 1] == 3) { int two[2] = { 0 }; former[i] = 3; former[i + 1] = 3; handcard[i] -= 3; handcard[i + 1] -= 3; for (int k = 0; k < 11; k++) { if (handcard[k] == 2) { two[flag] = k; flag++; } if (flag == 2) { handcard[two[0]] -= 2; handcard[two[1]] -= 2; former[two[0]] += 2; former[two[1]] += 2; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } } flag = 0; for (int k = 0; k < 15; k++) { if (handcard[k] == 1) { two[flag] = k; flag++; } if (flag == 2) { handcard[two[0]] -= 1; handcard[two[1]] -= 1; former[two[0]] += 1; former[two[1]] += 1; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } } yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } len = 0; flag = 0; for (int k = 0; k < 12; k++) { if (handcard[k] >= 2) len++; else len = 0; if (len >= 3 && handcard[k + 1] <= 2) { int out = 0; out = k - len + 1; for (int k = out; k < out + len; k++) former[k] = 2; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } } len = 0; flag = 0; for (int i = 0; i < 15; i++) if (handcard[i] == 3) { handcard[i] -= 3; former[i] = 3; for (int i = 0; i < 15; i++) if (handcard[i] == 2) { former[i] += 2; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } for (int i = 0; i < 15; i++) if (handcard[i] == 1) { former[i] += 1; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } len = 0; flag = 0; for (int k = 0; k < 12; k++) { if (handcard[k] >= 1) len++; else len = 0; if (len >= 5 && handcard[k + 1] == 0) { int out = 0; out = k - len + 1; for (int i = out; i < out + len; i++) former[i] = 1; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } } len = 0; flag = 0; for (int i = 0; i < 13; i++) if (handcard[i] == 2) { former[i] = 2; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } len = 0; flag = 0; for (int i = 0; i < 15; i++) if (handcard[i] == 1) { former[i] = 1; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } len = 0; flag = 0; for (int i = 0; i < 15; i++) if (handcard[i] == 4) { handcard[i] -= 4; for (int i = 0; i < 15; i++) former[i] = 0; former[i] = 4; yourstyle(cards, former); substractFromHand(cards); delete(former); return cards; } } else { // 位于prePos的玩家打出了prePlay的牌,你需要出什么牌? int m = 0; mystyle(prePlay, former); for (int i = 0; i < 15; i++) m += former[i]; if (m == 1) { int in = 0; for (int i = 0; i < 15; i++) if (former[i]) in = i; for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards,one(handcard, former,in)); substractFromHand(cards); return cards; } if (m == 2) { int in = 0; if (former[14] == 1 && former[13] == 1) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards, former); substractFromHand(cards); return cards; } else { for (int i = 0; i < 15; i++) if (former[i] == 2) in = i; for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards, two(handcard, former, in)); substractFromHand(cards); return cards; } } if (m == 3) { int in = 0; for (int i = 0; i < 15; i++) if (former[i] == 3) in = i; for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards,three(handcard,former, in)); substractFromHand(cards); return cards; } if (m == 4) { int in = -1; for (int i = 0; i < 15; i++) if (former[i] == 4) in = i; if (in >= 0) { yourstyle(cards, boom(handcard, former, in)); substractFromHand(cards); return cards; } else { for (int i = 0; i < 15; i++) if (former[i] == 3) in = i; if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards,threeplusone(handcard,former, in)); substractFromHand(cards); return cards; } } } if (m == 5) { int in = -1, len = 0; for (int i = 0; i < 15; i++) if (former[i] == 3) in = i; if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards, threeplustwo(handcard, former, in)); substractFromHand(cards); return cards; } for (int k = 0; k < 12; k++) { if (former[k] != 0) len++; else len = 0; if (len == m) { in = k - 4; break; } } if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards, shunzi(handcard, former, in, m)); substractFromHand(cards); return cards; } } if (m >= 6) { int in = -1, wing = 0; for (int i = 0; i < 11; i++) { if (former[i] == 3 && former[i + 1] == 3) { in = i; break; } } for (int i = 0; i < 15; i++) if (former[i] == 2) wing = 2; for (int i = 0; i < 15; i++) if (former[i] == 1) wing = 1; if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards, plane(handcard, former, in, wing, m)); substractFromHand(cards); return cards; } ////////////////////////////////////////// wing = 0; for (int i = 0; i < 13; i++) if (former[i] == 4) { in = i; break; } for (int i = 0; i < 15; i++) if (former[i] == 2) wing = 2; if (in >= 0) { for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards, boomplus(handcard, former, in, wing)); substractFromHand(cards); return cards; } //////////////////////////////////////////// wing = 0; for (int i = 0; i < 12; i++) { if (former[i] != 0) wing++; else wing = 0; if (wing == m) { in = i - m + 1; for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards,shunzi(handcard,former, in, m)); substractFromHand(cards); return cards; } } /////////////////////////////////////////// wing = 0; for (int i = 0; i < 12; i++) { if (former[i] == 2) wing++; else wing = 0; if (wing == m / 2) { in = i - m / 2 + 1; for (int i = 0; i < 15; i++) former[i] = 0; yourstyle(cards,liandui(handcard,former, in, m)); substractFromHand(cards); return cards; } } } } // 你需要保证打出的牌是合法的 // assert函数在参数为false的时候会使程序报错退出。 // 这样做的好处是,如果你有没注意到的错误导致程序在此报错退出, // 你就知道是在出牌的合法性上出了问题,而不用排查程序的其他部分。 assert(legal(cards)); substractFromHand(cards); return cards; // 将打出的牌从手牌中删去 } int* DDZPlayer::one(int *a,int *former, int in) { int out = -1; if (in < 14) for (int i = in + 1; i < 15; i++) if (a[i] != 0) { a[i] -= 1; out = i; break; } if (out > 0) { former[out] = 1; return former; } else return boom(a, former, -1); } int* DDZPlayer::two(int *a,int *former, int in) { int out = -1; for (int i = in + 1; i < 15; i++) if (a[i] == 2) { a[i] -= 2; out = i; break; } if (out > 0) { former[out] = 2; return former; } else return boom(a, former, -1); } int* DDZPlayer::three(int *a,int *former, int in) { int out = -1; for (int i = in + 1; i < 15; i++) if (a[i] == 3) { out = i; a[i] -= 3; break; } if (out > 0) { former[out] = 3; return former; } else boom(a, former, -1); } int* DDZPlayer::boom(int *a,int *former, int in) { for (int i = 0; i < 15; i++) former[i] = 0; for (int i = in + 1; i < 15; i++) if (a[i] == 4) { a[i] -= 4; former[i] = 4; return former; } if (a[13] == 1 && a[14] == 1) { a[14] = 0; a[13] = 0; for (int i = 0; i < 15; i++) former[i] = 0; former[13] = 1; former[14] = 1; return former; } return former; } int* DDZPlayer::threeplusone(int *a,int *former, int in) { int out1 = -1, out2 = -1; for (int i = in + 1; i < 15; i++) if (a[i] >= 3) { out1 = i; a[i] -= 3; break; } for (int i = 0; i < 15; i++) if (a[i] >= 1) { out2 = i; a[i] -= 1; break; } if (out1 > 0 && out2 > 0) { former[out1] = 3; former[out2] = 1; return former; } else return boom(a, former, -1); } int* DDZPlayer::threeplustwo(int *a,int *former, int in) { int out1 = -1, out2 = -1; for (int i = in + 1; i < 15; i++) if (a[i] >= 3) { out1 = i; a[i] -= 3; break; } for (int i = 0; i < 15; i++) if (a[i] >= 2) { out2 = i; a[i] -= 2; break; } if (out1 >= 0 && out2 >= 0) { former[out1] = 3; former[out2] = 2; return former; } else return boom(a, former, -1); } int* DDZPlayer::shunzi(int *a,int *former, int in, int m) { int out = -1, len = 0; for (int k = in + 1; k < 12; k++) { if (a[k] != 0) len++; else len = 0; if (len == m) { out = k - m + 1; break; } } if (out >= 0) { for (int i = out; i < out + m; i++) { a[i] -= 1; former[i] = 1; } return former; } else return boom(a, former, -1); } int* DDZPlayer::plane(int *a, int *former,int in, int wing, int m) { int out1 = -1, out21 = -1, out22 = -1, out23 = -1; if (wing > 0) { if (m == 10) { for (int i = in + 1; i < 11; i++) { if (a[i] >= 3 && a[i + 1] >= 3) { out1 = i; a[i] -= 3; a[i + 1] -= 3; break; } } for (int i = 0; i < 15; i++) { if (a[i] >= 2 && out21 == -1) { out21 = i; a[i] -= 2; } if (a[i] >= 2 && out21 > -1) { out22 = i; a[i] -= 2; break; } } if (out1 > -1 && out21 > -1 && out22 > -1) { former[out1] = 3; former[out1 + 1] = 3; former[out21] = 2; former[out22] = 2; return former; } } if (m == 15) { for (int i = in + 1; i < 10; i++) { if (a[i] == 3 && a[i + 1] == 3 && a[i + 2] == 3) { out1 = i; a[i] -= 3; a[i + 1] -= 3; a[i + 2] -= 3; break; } } for (int i = 0; i < 15; i++) { if (a[i] >= 2 && out21 == -1) { out21 = i; a[i] -= 2; } if (a[i] >= 2 && out21 > -1 && out22 == -1) { out22 = i; a[i] -= 2; } if (a[i] >= 2 && out22 > -1) { out23 = i; a[i] -= 2; break; } } if (out1 > -1 && out21 > -1 && out22 > -1 && out23 > -1) { former[out1] = 3; former[out1 + 1] = 3; former[out1 + 2] = 3; former[out21] = 2; former[out22] = 2; former[out23] = 2; return former; } } } if (wing == 1) { if (m == 8) { for (int i = in + 1; i < 11; i++) { if (a[i] >= 3 && a[i + 1] >= 3) { out1 = i; a[i] -= 3; a[i + 1] -= 3; break; } } for (int i = 0; i < 15; i++) { if (a[i] >= 1 && out21 == -1) { out21 = i; a[i] -= 1; } if (a[i] >= 1 && out21 > -1) { out22 = i; a[i] -= 1; break; } } if (out1 > -1 && out21 > -1 && out22 > -1) { former[out1] = 3; former[out1 + 1] = 3; former[out21] = 1; former[out22] = 1; return former; } } if (m == 12) { for (int i = in + 1; i < 10; i++) { if (a[i] >= 3 && a[i + 1] >= 3 && a[i + 2] >= 3) { out1 = i; a[i] -= 3; a[i + 1] -= 3; a[i + 2] -= 3; break; } } for (int i = 0; i < 15; i++) { if (a[i] >= 1 && out21 == -1) { out21 = i; a[i] -= 1; } if (a[i] >= 1 && out21 > -1 && out22 == -1) { out22 = i; a[i] -= 1; } if (a[i] >= 1 && out22 > -1) { out23 = i; a[i] -= 1; break; } } if (out1 > -1 && out21 > -1 && out22 > -1 && out23 > -1) { former[out1] = 3; former[out1 + 1] = 3; former[out1 + 2] = 3; former[out21] = 1; former[out22] = 1; former[out23] = 1; return former; } } } if (wing == 0) { if (m == 6) { for (int i = in + 1; i < 11; i++) { if (a[i] >= 3 && a[i + 1] >= 3) { out1 = i; a[i] -= 3; a[i + 1] -= 3; break; } } if (out1 > -1) { former[out1] = 3; former[out1 + 1] = 3; return former; } } if (m == 9) { for (int i = in + 1; i < 10; i++) { if (a[i] >= 3 && a[i + 1] >= 3 && a[i + 2] >= 3) { out1 = i; a[i] -= 3; a[i + 1] -= 3; a[i + 2] -= 3; break; } } if (out1 > -1) { former[out1] = 3; former[out1 + 1] = 3; former[out1 + 2] = 3; return former; } } if (m == 12) { for (int i = in + 1; i < 10; i++) { if (a[i] >= 3 && a[i + 1] >= 3 && a[i + 2] >= 3 && a[i + 3] >= 3) { out1 = i; a[i] -= 3; a[i + 1] -= 3; a[i + 2] -= 3; a[i + 3] -= 3; break; } } if (out1 > -1) { former[out1] = 3; former[out1 + 1] = 3; former[out1 + 2] = 3; former[out1 + 3] = 3; return former; } } } return boom(a, former, -1); } int* DDZPlayer::boomplus(int *a,int *former, int in, int wing) { int out1 = -1, out21 = -1, out22 = -1; if (wing == 2) { for (int i = in + 1; i < 15; i++) if (a[i] == 4) { out1 = i; a[i] -= 4; break; } for (int i = 0; i < 15; i++) { if (a[i] == 2 && out21 == -1) { out21 = i; a[i] -= 2; } if (a[i] == 2 && out21 != -1) { out22 = i; a[i] -= 2; break; } } if (out1 != -1 && out21 != -1 && out22 != -1) { former[out1] = 4; former[out21] = 2; former[out22] = 2; return former; } } if (wing == 0) { for (int i = in + 1; i < 15; i++) if (a[i] == 4) { out1 = i; a[i] -= 4; break; } for (int i = 0; i < 15; i++) { if (a[i] >= 1 && out21 == -1) { out21 = i; a[i] -= 1; } if (a[i] >= 1 && out21 != -1) { out22 = i; a[i] -= 1; break; } } if (out1 != -1 && out21 != -1 && out22 != -1) { former[out1] = 4; former[out21] = 1; former[out22] = 1; return former; } } return boom(a, former, -1); } int* DDZPlayer::liandui(int *a, int *former, int in, int m) { int out = -1, len = 0; for (int k = in + 1; k < 12; k++) { if (a[k] >= 2) len++; else len = 0; if (len == m / 2) { out = k - m / 2 + 1; break; } } if (out >= 0) { for (int i = out; i < out + m / 2 && i<15; i++) { a[i] -= 2; former[i] = 2; } return former; } else return boom(a, former, -1); } bool DDZPlayer::leftNoCard() { // 返回当前手牌为空 return hand.empty(); } const int Card::N_CARD_VALUES = 15; const int Card::N_CARD_SUITS = 4; const string Card::CARD_VALUES[] = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2", "joker", "JOKER" }; const string Card::CARD_SUITS[] = { "Spades", "Hearts", "Diamonds", "Clubs" }; vector Card::get_new_deck() { // 生成一副新牌 vector deck; for (int i = 0; i < N_CARD_VALUES - 2; ++i) { for (int j = 0; j < N_CARD_SUITS; ++j) { Card card(CARD_VALUES[i]); deck.push_back(card); } } deck.push_back(Card(CARD_VALUES[13])); deck.push_back(Card(CARD_VALUES[14])); return deck; } int DDZGame::my_random(int i) { return std::rand() % i; } DDZGame::DDZGame(DDZPlayer *p1, DDZPlayer *p2, DDZPlayer *p3) { // 牌局类的构造函数,需要接受三个玩家作为参数 players.push_back(p1); players.push_back(p2); players.push_back(p3); } void DDZGame::showCards(vector cards) { sort(cards.begin(), cards.end(), greater()); for (vector::iterator i = cards.begin(); i != cards.end(); ++i) { cout << *i << " "; } if (cards.size() == 0) cout << "YAO BU QI"; cout << endl << endl; } void DDZGame::run() { // 斗地主游戏的主要流程 // 取一副新牌并洗牌 vector deck = Card::get_new_deck(); random_shuffle(deck.begin(), deck.end(), my_random); // 每个玩家抽17张牌,留下三张底牌 for (int i = 0; i < 54 - 3; ++i) players[i % 3]->draw(deck[i]); // 随机选取地主,发给地主最后三张牌 // * 你可以实现自己的叫地主流程, // * 你需要在DDZPlayer类里面加入相应的变量(存储其他玩家叫地主的情况) // * 和函数bool DDZPlayer::bid()(返回自己是否要叫地主)。 // * 请参阅play()函数和叫地主的规则设计这个流程。 int landlordPos = my_random(3); for (int i = 54 - 3; i < 54; ++i) players[landlordPos]->draw(deck[i]); for (int i = 0; i < 3; ++i) players[i]->setPosition((i + 3 - landlordPos) % 3); // 计算与地主的相对位置 cout << players[landlordPos]->getName() << " is the landlord." << endl; int currentPlayer = landlordPos; while (true) { // 当前玩家打牌 vector currentCards = players[currentPlayer]->play(); cout << players[currentPlayer]->getName() << " plays:"; showCards(currentCards); // 其他玩家看到了打出的牌。(并不是只有下家看到,上家也能看到) for (int i = 0; i < 3; ++i) { // 玩家看到的位置编号都是从地主为0开始的 int relativePos = (currentPlayer + 3 - landlordPos) % 3; players[i]->observed(relativePos, currentCards); } // 如果刚出完牌的玩家没有牌了游戏结束 if (players[currentPlayer]->leftNoCard()) { bool landlordwins = (currentPlayer == landlordPos); cout << (landlordwins ? "Landlord wins!" : "Farmers win!") << endl; break; } // 计算下一个玩家的下标 currentPlayer = (currentPlayer + 1) % 3; } } vector DDZHumanPlayer::play() { vector cards; string s, c; while (true) { showHand(); cout << "Please input the cards you want to play." << endl; getline(cin, s); istringstream iss(s); while (iss >> c) { cards.push_back(Card(c)); } // 现在cards是一个vector,存储了用户输入的牌 // 你需要检测输入的牌是持有的牌,并且合法。请完成legal函数。 if (legal(cards)) { break; } else { cout << "Illegal cards. Input again." << endl; cards.clear(); } } substractFromHand(cards); return cards; }