📄 cardpile.cpp
字号:
for (const_iterator p (begin ()); (p = getFittingCard (card, p, cmp)) != end (); ++p) { if (*p == &card) // Skip card if its the passed one continue; int diff (cmp (**p, card)); if (diff) { diff = (diff < 0) ? (diff + 2) : (diff + 1); Check3 (diff < 4); TRACE1 ("ICardPile::pileHasFittingPair (const " "CardWidget*, " "CMPFUNC2, bool) - " << **p << " diff: " << diff); if ((((unsigned int)diff) < 4) && !(bCols & (1 << diff))) { // The card is valid, if either a card bordering the one the // inspect and this one has been found. Note that for aces the // bordering card must be in the same direction as the card to // to inspect (e.g. K-A-2 is not valid; only Q-K-A!) if ((card.number () == CardWidget::ACE) ? (bCols & (0x1 << (diff ^ 0x1))) : (bCols & (diff ? (0x5 << (diff - 1)) : 0x1))) return true; bCols |= (1 << diff); } } else { // Filter out doubles (if specififed) if (!doubles) { std::vector<unsigned int>::const_iterator i (foundCards.begin ()); do { TRACE1 ("ICardPile::pileHasFittingPar (const CardWidget*, CMPFUNC2, bool)) - " << *i << '-' << (*p)->id ()); if (*i == (*p)->id ()) break; } while (++i != foundCards.end ()); if (i != foundCards.end ()) continue; foundCards.push_back ((*p)->id ()); TRACE1 ("ICardPile::pileHasFittingPair (const " "CardWidget*, " "CMPFUNC2, bool) - Adding non-double " << **p); } if (++nrs == 2) return true; } } TRACE7 ("CardPile::pileHasFittingPair (const CardWidget*, CMPFUNC2, bool) - " << card << " matches " << nrs << '/' << std::hex << bCols << std::dec); return false;}//-----------------------------------------------------------------------------/// Returns a card fitting to the passed on/// \param card: Card where to find a fitting one to/// \param start: Position where to start the search/// \param cmp: Method to compare two cards. This method gets the two cards to/// compare as input as must return an integer describing their/// difference (0: Equal). A pair can have a difference of at most/// [-2 - 2]/// \returns \c Position of matching card or pile.end ()/// \pre start must be a valid iterator in pile//-----------------------------------------------------------------------------ICardPile::iterator ICardPile::getFittingCard (const CardWidget& card, const_iterator start, CMPFUNC2 cmp) const { TRACE9 ("ICardPile::getFittingCard (const CardWidget*, const_iterator, " "CMPFUNC2) - " << card); while (start != end ()) { if ((static_cast<unsigned int> (cmp (card, **start) + 2)) < 5) break; ++start; }#if TRACELEVEL > 8 if (start == end ()) { TRACE ("ICardPile::getFittingCard (const CardWidget*, const_iterator, " "CMPFUNC2) - End"); } else { TRACE ("ICardPile::getFittingCard (const CardWidget*, const_iterator, " "CMPFUNC2) - Found " << **start); }#endif return (const_cast<ICardPile*> (this)->begin () + (start - (const_iterator)begin ()));}//----------------------------------------------------------------------------/// Sorts a series of matching cards to the end of the pile/// \param aPos: Map holding the positions of the cards in the pile/// \param aOrder: Sorted order of the cards/// \returns unsigned int: Position of start of sorted serie//----------------------------------------------------------------------------unsigned int ICardPile::sortColourSerie (std::map<unsigned int, unsigned int>& aPos, std::vector<unsigned int>& aOrder) { unsigned int pos (1); for (std::vector<unsigned int>::reverse_iterator p (aOrder.rbegin ()); p != aOrder.rend (); ++p) { std::map<unsigned int, unsigned int>::const_iterator v (aPos.find (*p)); Check3 (v != aPos.end ()); TRACE9 ("ICardPile::sortColourSeries (...) - Moving " << v->second << " to end " << ((*p < 2) ? *p : 0)); Check3 ((p - aOrder.rbegin ()) >= 0); // Move the card to the end of the staple; If it belongs before the // first card move it before the other cards. move (size () - pos, v->second); unsigned int oldOrder (*p); if (((p + 1) != aOrder.rend ()) && (*(p + 1) < oldOrder)) ++pos; } TRACE9 ("ICardPile::sortColourSeries (...) - Moved " << size () - aPos.size () << " cards"); return size () - aPos.size ();}//-----------------------------------------------------------------------------/// Helper-function to correct the found matching cards/// \param elem: Element to remove from the found ones/// \param aPos: Map holding the positions of the cards in the pile/// \param aOrder: Sorted order of the cards//-----------------------------------------------------------------------------void ICardPile::deleteElement (unsigned int elem, std::map<unsigned int, unsigned int>& aPos, std::vector<unsigned int>& aOrder) { Check3 (aPos.find (elem) != aPos.end ()); Check3 (std::find (aOrder.begin (), aOrder.end (), elem) != aOrder.end ()); aOrder.erase (std::find (aOrder.begin (), aOrder.end (), elem)); aPos.erase (aPos.find (elem));}//----------------------------------------------------------------------------/// Gets a series of matching cards/// \param card: Card to compare/// \param aPos: Map holding the positions of the cards in the pile/// \param aOrder: Sorted order of the cards/// \param cmp: Method to compare two cards. This method gets the two cards to/// compare as input as must return an integer describing their/// difference (0: Equal). A pair can have a difference of at most/// [-2 - 2]/// \returns unsigned int: The number of matching cards in a row//----------------------------------------------------------------------------unsigned int ICardPile::getSeries (CardWidget& card, std::map<unsigned int, unsigned int>& aPos, std::vector<unsigned int>& aOrder, CMPFUNC2 cmp, bool doubles) { TRACE1 ("ICardPile::getSeries (...) for " << card); unsigned int nrs (0); unsigned int bCols (0x4); std::vector<unsigned int> foundCards (4); unsigned int cDoubles (0); if (!doubles) foundCards.push_back (card.id ()); for (const_iterator p (begin ()); ((p = getFittingCard (card, p, cmp)) != end ()); ++p) { if (*p == &card) { aPos[2] = p - begin (); aOrder.push_back (2); ++nrs; } else { int diff (cmp (**p, card)); TRACE1 ("ICardPile::getSeries (...) - " << **p << " differs " << diff); Check3 (static_cast<unsigned int> (diff + 2) < 5); if (diff) { diff += 2; Check3 (diff <= 4); if (!(bCols & (1 << diff))) { Check3 (aPos.find (diff) == aPos.end ()); bCols |= (1 << diff); aPos[diff] = p - begin (); aOrder.push_back (diff); if (aPos.size () == 7) break; } } else { // Filter out doubles (if specififed) if (!doubles) { std::vector<unsigned int>::const_iterator i (foundCards.begin ()); do { TRACE1 ("ICardPile::getSeries (...) - " << *i << '-' << (*p)->id ()); if (*i == (*p)->id ()) break; } while (++i != foundCards.end ()); if (i != foundCards.end ()) { ++cDoubles; continue; } foundCards.push_back ((*p)->id ()); TRACE1 ("ICardPile::getSeries (...) - Adding non-double " << **p); if (cDoubles) move (p - begin () - cDoubles, p - begin ()); } ++nrs; } } } // Check if the series of colors is a valid one TRACE1 ("ICardPile::getSeries (...) - Serie: " << std::hex << bCols << std::dec); Check3 (bCols & 0x4); // Delete cards having no direct access to the analyzed one if ((bCols & 0x3) == 0x1) { Check3 (aPos.find (1) == aPos.end ()); deleteElement (0, aPos, aOrder); bCols &= ~0x1; } if ((bCols & 0x18) == 0x10) { Check3 (aPos.find (3) == aPos.end ()); deleteElement (4, aPos, aOrder); bCols &= ~0x10; } // Special handling of series of colours for an ace, to avoid the problem // with 3-K-A of one colour. if (card.number () == CardWidget::ACE) { if ((bCols & 0xa) == 0xa) { if ((bCols & 0x18) == 0x18) { if (aPos.find (0) != aPos.end ()) deleteElement (0, aPos, aOrder); if (aPos.find (1) != aPos.end ()) deleteElement (1, aPos, aOrder); } else { if (aPos.find (3) != aPos.end ()) deleteElement (3, aPos, aOrder); if (aPos.find (4) != aPos.end ()) deleteElement (4, aPos, aOrder); } } } return nrs;}//----------------------------------------------------------------------------/// Find the worst (lowest) card in the pile/// \return unsigned int: Position of the lowest card in the pile//----------------------------------------------------------------------------unsigned int ICardPile::findLowestCard () const { TRACE9 ("ICardPile::findLowestCard () const - Analyzing " << size () << " cards"); Check3 (size ()); unsigned int pos (0); for (ICardPile::const_iterator i (begin () + 1); i != end (); ++i) if ((*i)->number () < operator[] (pos)->number ()) pos = i - begin (); TRACE8 ("ICardPile::findLowestCard () const - Lowest card: " << *operator[] (pos) << " at " << pos); return pos;}//----------------------------------------------------------------------------/// Find the worst (lowest) card in the pile/// \param excludeColour: Special colour, which is not included in the search/// \return unsigned int: Position of the lowest card in the pile//----------------------------------------------------------------------------unsigned int ICardPile::findLowestCard (CardWidget::COLOURS excludeColour) const { TRACE9 ("ICardPile::findLowestCard (CardWidget::COLOURS) const - Analyzing " << size () << " cards") Check3 (size ()); unsigned int pos (0); for (ICardPile::const_iterator i (begin () + 1); i != end (); ++i) if (((*i)->colour () != excludeColour) && ((*i)->number () < operator[] (pos)->number ())) pos = i - begin (); TRACE8 ("ICardPile::findLowestCard (CardWidget::COLOURS) const - Lowest card: " << *operator[] (pos) << " at " << pos); return pos;}//----------------------------------------------------------------------------/// Finds the last card with the passed colour in the pile./// \param col: Colour to search for/// \return int: Position of found card; -1 if there's no bigger card/// \pre The pile must be sorted by colour//----------------------------------------------------------------------------int ICardPile::findLastEqualOrBiggerColour (CardWidget::COLOURS col) const { TRACE9 ("ICardPile::findLastEqualOrBiggerColour (CardWidget::COLOURS)"); int pos (findFirstEqualOrBiggerColour (col)); return ((pos == -1) ? - 1 : ((operator[] (pos)->colour () == col) ? findLastEqualColour (pos) : -1));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -