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 + -
显示快捷键?