twopart.cpp

来自「一个扑克牌游戏集合的源码,包含了很多基本c-c++语言应用」· C++ 代码 · 共 1,255 行 · 第 1/4 页

CPP
1,255
字号
//-----------------------------------------------------------------------------/// Callback after clicking on a card in hand/// \param pos: Offset of card in hand//-----------------------------------------------------------------------------void Twopart::cardSelected (unsigned int pos) {   TRACE5 ("Twopart::cardSelected (unsigned int) - Position " << pos);   Check3 (pos < players[0].hand.size ());   Check3 (gameStatus () >= PLAYING);   CardWidget& card (*players[0].hand[pos]);   CardWidget::NUMBERS nr (card.number ());   CardWidget::COLOURS colour (card.colour ());   // Perform validity-check in part 2: Card must have the same colour and be   // bigger than the last played card or be a (bigger) trump   unsigned int start (pos);   if (gameStatus () == PLAYING2) {      start = findStartOfSerie (0, pos);      Check3 (pTrump);      if (played.size ()) {         CardWidget& top (played.getTopCard ());         if ((colour == pTrump->colour ())             ? ((top.colour () == pTrump->colour ())                && (top.number () >= nr))             : ((top.colour () != colour)                || (top.number () >= nr))) {            Gtk::MessageDialog dlg	       (ngettext ("The played card must have the same colour and must be bigger (or be a trump)!",			  "The played cards must have the same colour and must be bigger (or be trumps)!",			  pos - start + 1),		Gtk::MESSAGE_ERROR);            dlg.set_title (PACKAGE " - Twopart");            dlg.run ();            return;         }      }   }   // Inform the others about the move   if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::NONE) {      // Send played card to all clients (if any)      std::ostringstream msg;      msg << "Play=";      for (unsigned int i (start); i < pos; ++i)         msg << players[0].hand[i]->id () << ' ';      msg << players[0].hand[pos]->id () << ";Target=0";      if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::CLIENT)         ignoreNextMsg = true;      broadcastMessage (msg.str ());   }   setNextPlayer (executeMove (0, start, pos));   makeNextMoves ();}//-----------------------------------------------------------------------------/// Executes a move out of a hand/// \param player: ID of player/// \param start: Offset of first card to play/// \param end: Offset of last card to play/// \returns int: Next player or -1 at end//-----------------------------------------------------------------------------int Twopart::executeMove (unsigned int player, unsigned int start, unsigned int end) {   TRACE5 ("Twopart::executeMove (unsigned int, unsigned int) - Player: "           << player << " at position " << start << " to " << end);   Check3 (player < NUM_PLAYERS);   Check3 (start <= end);   Check3 (end < players[player].hand.size ());   if (!moveSelectedCardToPlayed (player, start, end))      return player;   // Check if every player is still in game or has already played; end round   // if so or calculate next player if not   TRACE7 ("Twopart::executeMove (unsigned int, unsigned int) - Players: "           << std::hex << bfPlayers << std::dec);   removePlayer (player);   int newPlayer (player);   if (bfPlayers)      newPlayer = findNextPlayer (player);   else {      // Show trump if not already visible      if (pTrump && !pTrump->is_visible ()) {         pTrump->showFace ();         pTrump->show ();         attach (*pTrump, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 5, 5);      }      newPlayer = endRound (player);   }   // Check if the actual part is terminated   if ((gameStatus () == PLAYING)       ? (newPlayer < 0)       : (newPlayer == findNextPlayerWithCards (newPlayer))) {      player = (gameStatus () == PLAYING) ? ~newPlayer : newPlayer;      Glib::ustring str ((gameStatus () == PLAYING)                         ? _("First part ended; Part 2 starts %1")                         : _("%1 lost"));      Check3 (actPlayers.size () > player);      Check3 (actPlayers[player]);      str.replace (str.find ("%1"), 2, actPlayers[player]->getName ());      status.pop ();      status.push (str);      if (gameStatus () == PLAYING)         startPartTwo (player);      else         setGameStatus (STOPPED);      return -1;   }   else      displayTurn (player = newPlayer);   return player;}//-----------------------------------------------------------------------------/// Makes the move for the next player./// \param player: Actual player/// \returns int: Next player or -1 if end of game//-----------------------------------------------------------------------------int Twopart::makeMove (unsigned int player) {   TRACE5 ("Twopart::makeMove () - Turn of player " << player);   Check3 (gameStatus () >= PLAYING);   if (pos2Play == -1U) {      if (findPos2Play (player, pos1Play, pos2Play) != -1) {         // Flip card(s) to play         flipCards2Play (players[player].hand, pos1Play, pos2Play);         return player;      }      else {         if ((gameStatus () == PLAYING2)             && (getConnectionMgr ().getMode () == YGP::ConnectionMgr::SERVER)) {            std::ostringstream msg;            Check3 (startPos[offPos - 1] < played.size ());            msg << "Play=" << played[startPos[offPos - 1]]->id () << ";Target=1";            broadcastMessage (msg.str ());         }         player = pickUpPlayedPile (player);      }   }   else {      player = executeMove (player, pos1Play, pos2Play);      pos1Play = pos2Play = -1U;   }   return player;}//-----------------------------------------------------------------------------/// Searches for the card(s) to play by analyzing the previously played cards/// to him if so. Else enable the players which can continue/// \param player: ID of player to analyze/// \param start: Offset of first card to play/// \param end: Offset of last card to play/// \returns int: Position to play; or -1 if player can't continue//-----------------------------------------------------------------------------int Twopart::findPos2Play (unsigned int player, unsigned int& start,                           unsigned int& end) const {   Check3 (player); Check3 (player < NUM_PLAYERS);   Check3 (gameStatus () >= PLAYING);   TRACE5 ("Twopart::findPos2Play (unsigned int) - Player " << player);   if (gameStatus () == PLAYING) {      unsigned int points (0);      unsigned int cHigh (0);      // Analyze played staple      for (unsigned int i (0); i < played.size (); ++i) {         CardWidget::NUMBERS nr (played[i]->number ());         points += nr;         if (nr >= CardWidget::TEN)            ++cHigh;      }      TRACE2 ("Twopart::findPos2Play (unsigned int) - Points: " << points              << "; Avg: " << (played.size ()                               ? (points / played.size ()) : 0)              << "; High: " << cHigh);      if (played.size ())         points /= played.size ();      int maxNr (-1);      int maxEqualNr (-1);      int posMax (-1);      int posMaxEqual (-1);      int trumps (0);      analyzeLastPlayed (*startPos, played.size () - *startPos,                         maxNr, posMax, maxEqualNr, posMaxEqual, trumps);      start = -1U;      // Try to get the cards if there are loads of high cards (a third or more)      // or if the average card played is at least a 8 or there are trumps inside      if (((played.size () / 3) < cHigh)          || (points >= CardWidget::SEVEN)          || trumps) {         end = -1U;         // Search for card whose number you own         for (start = 0;              start < players[player].hand.size (); ++start)            if ((played.exists (players[player].hand[start]->number (), *startPos))                && ((posMaxEqual == -1)                    || (played[start]->number () >= maxEqualNr))) {               TRACE2 ("Twopart::findPos2Play (unsigned int) - Having equal card at "                       << start);               // Use card if it's a trump               if (pTrump                   && (pTrump->colour () == players[player].hand[start]->colour ())) {                  return end = start;               }               if (end == -1U)                  end = start;            }         // Reset start to first found card (or 0)         Check3 (start == players[player].hand.size ());         start = (end != -1U) ? end : 0;         TRACE6 ("Twopart::findPos2Play (unsigned int) - First try (I): " << start);         // Last player plays high card if higher (even if he would have an         // equal card in case the pile is really good) or ...         if (((start != end)              || (cHigh > 1) || (points >= CardWidget::TEN))             && (posMaxEqual == -1)             && ((!(bfPlayers & ~(1 << player)))                 && trumps                 && ((end = (findBigger                             (players[player].hand,                              static_cast<CardWidget::NUMBERS> (maxNr))))                     != -1U))             // ... the staple is being fighted for and player has high cards             || (*startPos                 && ((end = players[player].hand.size () - 1),                     ((players[player].hand[end]->number ()                       == CardWidget::ACE))                     || ((playersInBitfield (bfOldPlayers) < *startPos)                         && (players[player].hand[end]->number () >= maxNr)                         && (posMaxEqual == -1))))) {            TRACE2 ("Twopart::findPos2Play (unsigned int) - Playing highest card at "                    << start);            start = end;         }         return end = start;      }      // Try to get the cards if you don't have any close to the end of part 1      // and you are the last or the pile really sucks and just one is left      // (of course only if there are no doubles).      if (!players[player].won.size ()          && (staple.size () < 13)          && (posMaxEqual == -1)          && (((!(bfPlayers & ~(1 << player)))               || (!(bfPlayers & ~((1 << player)                                   | (1 << findNextPlayer ((player + 1) & 0x3))))                   && (points < CardWidget::SIX)))              && (maxNr < players[player].hand[players[player].hand.size ()-1]->number ())))         return end = start = 2;      // We don't want the pile; so try not to get it. To do so, play      // the second (biggest) card, if the first card exists in the pile and      // the second not (though the second card must also small).      // An exception is also for the last player      TRACE5 ("Twopart::findPos2Play (unsigned int) - Avoiding pile");      start = ((players[player].hand.size () > 1)               && played.exists (players[player].hand[0]->number (), *startPos)               && !played.exists (players[player].hand[1]->number (), *startPos)               && (((!(bfPlayers & ~(1 << player)))                    && (players[player].hand[1]->number () < maxNr))                   || (players[player].hand[1]->number () <= CardWidget::SEVEN)));      TRACE5 ("Twopart::findPos2Play (unsigned int) - Avoiding returns " << start);      // Final check: If you have to pick up the pile and you're the last,      // use at least a high card (unless there are doubles)      if (!start          && (posMaxEqual == -1)          && !(bfPlayers & ~(1 << player))          && (players[player].hand.size () > 1)          && (players[player].hand[start]->number () > maxNr))         start = 1;      TRACE5 ("Twopart::findPos2Play (unsigned int) - Playing card at " << start);      return end = start;   }   else {      // Find first fitting card      start = (played.size ()               ? players[player].hand.find1EqualOrBigger (played.getTopCard (),                                                          compByColourAccTrumps)               : findSmallestCard (player));      TRACE5 ("Twopart::findPos2Play (unsigned int) - First try (II): " << start);      Check3 (pTrump);      if ((start == -1U)          || (played.size ()              && (played.getTopCard ().colour ()                  != players[player].hand[start]->colour ()))) {         TRACE5 ("Twopart::findPos2Play (unsigned int) - No card found; trying trump");         Check3 (pTrump);         if (played.getTopCard ().colour () != pTrump->colour ()) {            for (start = players[player].hand.size (); start; --start)               if (players[player].hand[start - 1]->colour () != pTrump->colour ())                  break;            if (!start)               end = findEndOfSerie (player, 0);            else {               end = players[player].hand.size () - 1;               // Take up pile if no trump was found or if only a "small amount"

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?