📄 hearts.cpp
字号:
playedSQ = false; setGameStatus (PLAYING); // Search for startplayer unsigned int nextPlayer (0); for (unsigned int i (1); i < NUM_PLAYERS; ++i) if (((*players[i].hand)[0]->number () == CardWidget::TWO) && ((*players[i].hand)[0]->colour () == CardWidget::CLUBS)) { TRACE7 ("Hearts::startPlaying () - Start with player " << i); nextPlayer = i; break; } Check3 (nextPlayer < NUM_PLAYERS); setNextPlayer (nextPlayer); YGP::ConnectionMgr& cmgr (getConnectionMgr ()); if (((cmgr.getMode () == YGP::ConnectionMgr::NONE) && nextPlayer) || ((cmgr.getMode () == YGP::ConnectionMgr::SERVER) && (nextPlayer > getConnectionMgr ().getClients ().size ()))) flipCards2Play (*players[nextPlayer].hand, pos1Play = 0, pos2Play = 0); player2Exchange = (player2Exchange - 1) & 0x3; displayTurn (currentPlayer ()); makeNextMoves ();}//-----------------------------------------------------------------------------/// Checks who has played the highest card and would therefore win the played/// pile/// \returns \c ID of player with the highest card//-----------------------------------------------------------------------------unsigned int Hearts::check4Winner () { CardWidget::COLOURS colour (played[0]->colour ()); CardWidget::NUMBERS highest (CardWidget::TWO); unsigned int pos (0); for (unsigned int i (0); i < played.size (); ++i) if ((played[i]->colour () == colour) && (played[i]->number () > highest)) { pos = i; highest = played[i]->number (); TRACE9 ("Hearts::check4Winner (unsinged int, unsinged int) - " "New high card at " << i); } return pos;}//-----------------------------------------------------------------------------/// Checks if the round is at end and gives the cards to winner if so/// \param player: ID of player who did the last turn/// \returns \c Next player//-----------------------------------------------------------------------------unsigned int Hearts::calcNextPlayer (unsigned int player) { if (played.size () == NUM_PLAYERS) { // Everyone played its card: Search for winner of played pile; // clear it and continue with winner player = (player - NUM_PLAYERS + check4Winner () + 1) & 0x3; movePile (*players[player].won, played); } else player = ((player + 1) & 0x3); if (!players[player].hand->size ()) { player = -1U; setGameStatus (STOPPED); if (!pScoreDlg) { // Resort player for score dialogue std::vector<Player*> player; for (unsigned int i (0); i < NUM_PLAYERS; ++i) player.push_back (actPlayers[i]); pScoreDlg = ScoreDlg::create (player); pScoreDlg->get_window ()->set_transient_for (get_window ()); } int aScore[NUM_PLAYERS]; for (unsigned int i (0); i < NUM_PLAYERS; ++i) { aScore[i] = pointsOfPile (*players[i].won); if (aScore[i] == 26) { aScore[0] = aScore[1] = aScore[2] = aScore[3] = 26; aScore[i] = 0; break; } } pScoreDlg->addPoints (aScore); pScoreDlg->show (); Glib::ustring stat (_("Round ended")); unsigned int player; int points; pScoreDlg->getMaxPoints (points, player); if ((unsigned int)points >= ENDPOINTS) { stat = _("Game ended; %1 won"); pScoreDlg->getMinPoints (points, player); Check3 (actPlayers.size () > player); Check3 (actPlayers[player]); stat.replace (stat.find ("%1"), 2, actPlayers[player]->getName ()); } status.pop (); status.push (stat); } else displayTurn (player); if (!player) enableWonCards (*players[0].won); TRACE4 ("Hearts::calcNextPlayer (unsinged int) - Continuing with player " << player); return player;}//-----------------------------------------------------------------------------/// Moves the selected card to the played pile/// \param player: ID of player/// \param card: Offset of card to play/// \returns \c Status of moving; true: Card could be moved; false else//-----------------------------------------------------------------------------bool Hearts::moveSelectedCardToPlayed (unsigned int player, unsigned int card) { TRACE5 ("Hearts::moveSelectedCardToPlayed (unsigned int, unsigned int) - Player " << player << "; Pos. " << card); Check1 (player < NUM_PLAYERS); Check1 (card < players[player].hand->size ()); Check1 ((gameStatus () == PLAYING) || (gameStatus () == EXCHANGE)); if (gameStatus () == PLAYING) { CardWidget& actCard (*(*players[player].hand)[card]); CardWidget::COLOURS playColour (actCard.colour ()); unsigned int cardsPlayed (0); for (unsigned int i (0); i < NUM_PLAYERS; ++i) cardsPlayed += players[i].won->size (); if (played.size ()) { // The same colour must be played again (if available) CardWidget::COLOURS colour (played[0]->colour ()); if ((playColour != colour) && players[player].hand->exists (colour)) { Gtk::MessageDialog dlg (_("Play first cards with an equal colour as " "the first played one!"), Gtk::MESSAGE_ERROR); dlg.set_title (PACKAGE " - Hearts"); dlg.run (); return false; } } else { // The game must be started with the two of clubs if (!cardsPlayed) { if ((actCard.colour () != CardWidget::CLUBS) || (actCard.number () != CardWidget::TWO)) { Gtk::MessageDialog dlg (_("The game must be started with the two of clubs!"), Gtk::MESSAGE_ERROR); dlg.set_title (PACKAGE " - Hearts"); dlg.run (); return false; } } // One can start with a heart only if there has been one played before if (((playColour == CardWidget::HEARTS) && !aPlayed[CardWidget::HEARTS]) && ((*players[player].hand)[0]->colour () != CardWidget::HEARTS)) { Gtk::MessageDialog dlg (_("You can't start with a heart, if they have" " not been played before!"), Gtk::MESSAGE_ERROR); dlg.set_title (PACKAGE " - Hearts"); dlg.run (); return false; } } // The queen of spades can't be played in the first round if (!cardsPlayed) { if ((actCard.colour () == CardWidget::SPADES) && (actCard.number () == CardWidget::QUEEN)) { Gtk::MessageDialog dlg (_("The queen of spades can't be played in the first" " round!"), Gtk::MESSAGE_ERROR); dlg.set_title (PACKAGE " - Hearts"); dlg.run (); return false; } if (((playColour == CardWidget::HEARTS) && !aPlayed[CardWidget::HEARTS]) && ((*players[player].hand)[0]->colour () != CardWidget::HEARTS)) { Gtk::MessageDialog dlg (_("Hearts can't be played in the first round!"), Gtk::MESSAGE_ERROR); dlg.set_title (PACKAGE " - Hearts"); dlg.run (); return false; } } Check3 ((unsigned int)playColour < (sizeof (aPlayed) / sizeof (aPlayed[0]))); aPlayed[playColour]++; } movePile (played, *players[player].hand, card, card); return true;}//-----------------------------------------------------------------------------/// Exchanges the cards of the computer players. Get rid of cards according the/// following algorithm:/// - If nr. of clubs or diamonds are < 3 -> Use them/// - If nr. of spades < 5 get rid of high spades (especially the queen)/// - Get rid of high hearts/// - Get rid of high cards//-----------------------------------------------------------------------------void Hearts::exchangeCards () { TRACE8 ("Hearts::exchangeCards () - with " << player2Exchange); Check3 (played.size () == 3); movePile (aExchange[0], played); Check9 (aExchange[0].size () == 3); if (getConnectionMgr ().getMode () != YGP::ConnectionMgr::CLIENT) { for (unsigned int i (getConnectionMgr ().getClients ().size () + 1); i < NUM_PLAYERS; ++i) { TRACE8 ("Hearts::exchangeCards () - Player " << i); int posColours[4]; ICardPile& source (*players[i].hand); getPositionOfColours (source, posColours); unsigned int moved (0); unsigned int cCards (numberOfCards (posColours, CardWidget::CLUBS)); // If nr. of clubs or diamonds are < 3 -> Use them if (cCards && (cCards < 3)) { TRACE3 ("Hearts::exchangeCards () - Getting rid of all clubs: 0 - " << cCards - 1 << "; " << cCards << " cards"); movePile (aExchange[i], source, 0, posColours[CardWidget::CLUBS]); moved = cCards; } cCards = numberOfCards (posColours, CardWidget::DIAMONDS); if (cCards && (cCards) < (3 - moved)) { TRACE3 ("Hearts::exchangeCards () - Getting rid of all diamonds: " << posColours[CardWidget::DIAMONDS] - moved - cCards + 1 << " - " << posColours[CardWidget::DIAMONDS] - moved << "; " << cCards << " cards"); movePile (aExchange[i], source, posColours[CardWidget::DIAMONDS] - moved - cCards + 1, posColours[CardWidget::DIAMONDS] - moved); moved += cCards; } // If nr. of spades < 5 get rid of high spades (especially the queen) cCards = numberOfCards (posColours, CardWidget::SPADES); if (cCards && (cCards < 5)) { // Search for the queen of spades and get rid of cards equal or // bigger unsigned int start (posColours[CardWidget::SPADES] - moved - cCards + 1); while (start <= (posColours[CardWidget::SPADES] - moved - 1) && (source[start]->number () < CardWidget::QUEEN)) { TRACE9 ("Hearts::exchangeCards () - Checking spades at " << start); Check3 (source[start]->colour () == CardWidget::SPADES); ++start; } if (source[start]->number () == CardWidget::QUEEN) { TRACE3 ("Hearts::exchangeCards () - Getting rid of queen of spades at " << start); movePile (aExchange[i], source, start, start); moved++; } if ((moved < 3) && (start < (posColours[CardWidget::SPADES] - moved))) { start = posColours[CardWidget::SPADES] - moved; cCards = 2 - moved; TRACE3 ("Hearts::exchangeCards () - Getting rid of all high spades: " << start - cCards << " - " << start << "; " << (cCards + 1) << " cards"); movePile (aExchange[i], source, start - cCards, start); moved += cCards + 1; } } // Get rid of high cards int cardPos; for (unsigned int nr (CardWidget::ACE); moved < 3; --nr) { Check3 (nr > CardWidget::TWO); TRACE8 ("Hearts::exchangeCards () - Getting rid of high cards"); if ((cardPos = source.find (CardWidget::NUMBERS (nr))) != -1) { TRACE3 ("Hearts::exchangeCards () - Getting rid of high card at " << cardPos); movePile (aExchange[i], source, cardPos, cardPos); moved++; } } if (getConnectionMgr ().getMode () == YGP::ConnectionMgr::SERVER) { std::ostringstream msg; msg << "Exchange=" << aExchange[i][0]->id () << ' ' << aExchange[i][1]->id () << ' ' << aExchange[i][2]->id () << ";Player=" << i << ';'; broadcastMessage (msg.str ()); } } } for (unsigned int i (0); i < NUM_PLAYERS; ++i) { TRACE9 ("Hearts::exchangeCards () - " << i << " gives to " << ((i + player2Exchange) & 0x3)); Check3 (aExchange[i].size () == 3); ICardPile& target (*players[(i + player2Exchange) & 0x3].hand); movePile (target, aExchange[i]); target.sortByColour (); Check3 (target.size () == (cards.size () / NUM_PLAYERS)); Check3 (aExchange[i].empty ()); }}//-----------------------------------------------------------------------------/// Retrieve the last position of each colour in the pile/// \param pile: Pile to inspect/// \param result: Array of position of last cards of earch colour//-----------------------------------------------------------------------------void Hearts::getPositionOfColours (ICardPile& pile, int result[4]) { memset (result, (char)-1, sizeof (int[4])); for (unsigned int i (0); i < (pile.size () - 1); ++i) if (pile[i]->colour () != pile[i + 1]->colour ()) result[pile[i]->colour ()] = i; result[pile[pile.size () - 1]->colour ()] = pile.size () - 1; TRACE9 ("Hearts::getPositionOfColours (ICardPile&, unsigned int) - Pos. of " "cards: " << result[0] << ", " << result[1] << ", " << result[2] << ", " << result[3]);}//-----------------------------------------------------------------------------/// Calculate the number of cards out of the positions/// \param aPositions: Array of positions/// \param colour: Colour whose number should be calculated/// \returns \c int: Number of cards for colour//-----------------------------------------------------------------------------unsigned int Hearts::numberOfCards (const int aPositions[4], CardWidget::COLOURS colour) { Check1 (colour <= CardWidget::HEARTS); unsigned int nr (0), col ((unsigned int)colour); if (aPositions[colour] != -1) { nr = aPositions[colour] + 1; while (col) if (aPositions[--col] != -1) { nr -= aPositions[col] + 1; break; } } TRACE9 ("Hearts::size (int, CardWidget::COLOURS) - Cards: " << nr); return nr;}//-----------------------------------------------------------------------------/// Searches for the card to play/// \param player: Player to inspect//-----------------------------------------------------------------------------unsigned int Hearts::findPos2Play (unsigned int player) { Check1 (player < NUM_PLAYERS); TRACE8 ("Hearts::findPos2Play (unsigned int)"); ICardPile& pile (*players[player].hand); int aPos[4]; getPositionOfColours (pile, aPos);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -