0

大家好:)我希望有人有解决方案,否则我终于找到了^^

语境

我是 C++ 的初学者,所以,对象、模板和迭代器可能我有点了解并进行了一些更改,但是当遇到困难时我无法操作它。我正在构建一个软件,使用范围来评估扑克游戏中的概率。我用图书馆的扑克炉。https://github.com/andrewprock/pokerstove。在扑克中,我们大多数时候评估一手牌对抗另一手牌获胜的概率。但是我们不知道对手的牌:所以我们操纵一个范围或一组牌。在这里,一手牌(2 张牌)是来自 pokerstove 的 CardSet 结构。所以,我必须进行像交集、差集和并集这样的集合操作。

问题

我对 union_set 有问题,但对 set_difference 没有:

std::set<CardSet> union_range;
std::set<CardSet> ensemble_main1=union_range;
std::set<CardSet> ensemble_main2=pourcent_stove(30.);//=range_action(action[0][j][1],j);
std::set<CardSet> ensemble_main=pourcent_stove(20.); //=resultat;
set_difference(ensemble_main1.begin(),ensemble_main1.end(),ensemble_main2.begin(),ensemble_main2.end(),std::inserter(ensemble_main,ensemble_main1.begin()));

作品。pourcent_stove(30.) 在无限德州扑克中给出前 30% 2 张牌的最佳牌组。

但:

std::set<CardSet> union_range;
std::set<CardSet> ensemble_main1=union_range;
std::set<CardSet> ensemble_main2=pourcent_stove(30.);//=range_action(action[0][j][1],j);
std::set<CardSet> ensemble_main=pourcent_stove(20.); //=resultat;
set_union(ensemble_main1.begin(),ensemble_main1.end(),ensemble_main2.begin(),ensemble_main2.end(),std::inserter(ensemble_main,ensemble_main1.begin()));

不起作用:我有段错误。

我想问题就在这里,因为联合可以增加元素的数量。您对我可以添加的行有什么想法吗?

尝试

我尝试做 push_back 迭代器。但没有成功。据说该对象不存在该方法。我还尝试使用向量的语法为 set 声明大小:没有成功

文件

我没有足够的声誉来放置我使用过的文档的链接。(最多 2 个链接)

卡组代码

我必须写下许可地址以尊重作者:https ://github.com/andrewprock/pokerstove/blob/master/LICENSE.txt

/**
* Copyright (c) 2012 Andrew Prock. All rights reserved.
* $Id: CardSet.h 2649 2012-06-30 04:53:24Z prock $
*/
#ifndef PEVAL_CARDSET_H_
#define PEVAL_CARDSET_H_

#include <iosfwd>
#include <vector>
#include <string>
#include <boost/cstdint.hpp>
#include "Rank.h"
#include "Suit.h"

namespace pokerstove
{
// forward declares
class Card;
class PokerEvaluation;

/**
 * The CardSet is a compact representation of an unordered set of
 * cards.  All evaluation is done at the CardSet level.
 *
 * It can be used to store set of cards such as seen cards, dead
 * cards, folded cards, door cards, and whatever generic set of cards
 * you may be interested in.
 *
 * CardSet is implemented with efficiency in mind, so when selecting
 * from representations for cards, use a CardSet if speed and size
 * efficiency is important.  Other containers may be less efficient in
 * terms of size, speed, or both.
 */
class CardSet
{
public:
    static const size_t STANDARD_DECK_SIZE = Rank::NUM_RANK* Suit::NUM_SUIT;

public:
    CardSet();                                                 //!< defaults to the         empty set
CardSet(const CardSet& cs);                                //!< copy constructor (default)
CardSet(const std::string& c);                             //!< parse cards untill fail
explicit CardSet(const Card& c);                           //!< create a set with one card
explicit CardSet(uint64_t mask) : _cardmask(mask) {}

void   clear() { _cardmask = 0; }                          //!< empty the set
void   fill()  { _cardmask = 0; _cardmask = ~_cardmask; }  //!< put all cards into the set
size_t size() const;                                       //!< return number of cards in set

uint64_t mask() const { return _cardmask; }                //!< 1 bit per card

std::vector<Card> cards() const;                           //!< break into Cards
std::vector<CardSet> cardSets() const;                     //!< break into one card/CardSet

/**
 * Card related methods.
 */
bool contains(const Card& c) const;                        //!< is a card in the set
bool contains(const CardSet& c) const;                     //!< is a card in the set
CardSet& insert(const Card& c);                            //!< add one card
CardSet& insert(const CardSet& c);                         //!< equivalent to |=
CardSet& remove(const Card& c);                            //!< remove a card
CardSet& remove(const CardSet& c);
bool disjoint(const CardSet& c) const { return (_cardmask & c._cardmask) == 0; }
bool intersects(const CardSet& c) const { return !disjoint(c); }

/**
 * Rank related methods.
 */
size_t countRanks() const;
size_t count(const Rank& r) const;
bool   contains(const Rank& r) const;
Card   find(const Rank& r) const;             //!< return some card with rank r, in suit order
int    rankMask() const;                      //!< one bit set for each rank in hand, 13 max
bool   hasStraight() const;
Rank   topRank() const;                       //!< return the highest rank in hand
Rank   bottomRank() const;                    //!< return lowest rank in hand (A plays high)
size_t countMaxRank() const;                  //!< return the number of the most common rank
bool   insertRanks(const CardSet& rset);      //!< add ranks to hand, any suit
CardSet canonizeRanks() const;                //!< create a canonical rank representation

/**
 * Suit related methods.
 */
size_t  countSuits() const;                   //!< number of different suits in hand
size_t  count(const Suit& s) const;           //!< returns the length of the specified suit
size_t  countMaxSuit() const;                 //!< returns the length of the longest suit
bool    contains(const Suit& s) const;
Rank    flushRank(const Suit& s) const;       //!< return the highest rank of specified suit
int     suitMask(const Suit& s) const;
CardSet canonize() const;                     //!< transform suits to canonical form
CardSet canonize(const CardSet& other) const; //!< canonize relative to other hand
CardSet rotateSuits(int c, int d, int h, int s) const;
void    flipSuits();                          //!< invert suit order {cdhs} -> {shdc}

/**
 * String conversions.  Note that the output produced depends on
 * Suit::setSuitStringType (Suit::display s).  Not all string types are
 * reparseable.  That is:
 *
 * CardSet (CardSet("Ac").str()) == CardSet("Ac")
 *
 * May not be true.
 *
 * It is guaranteed to be true if the Suit::display type is SUIT_ASCII
 */
std::string str() const;
std::string rankstr() const;                        //!< print sorted ranks with dupes
std::string toRankBitString() const;

/**
 * indexing utils
 */
size_t colex() const;       //!< return a unique number based on cards
size_t rankColex() const;   //!< return a unique number based on ranks

/**
 * These are the basic building blocks of evaluation, they should
 * be fairly fast, but general, note there is a chance some of
 * these may break if given degenerate sets (with no cards, or
 * more than 7 cards) Every evaluation is ordered such that
 * (better hand) > (worse hand).  This holds even for (esp for)
 * lowball.  There is also a code which represents an null hand,
 * specifcally for the case of not making a qualifying 8 low.
 *
 * There is a tradeoff putting them here, by keeping them here we
 * preserve encapsulation but clutter up the class.  It might be
 * better to separate these out into utility functions.
 * e.g. PokerEvaluation evaluateHigh(const CardSet& c);
 */
PokerEvaluation evaluateHigh() const;
PokerEvaluation evaluateHighRanks() const;
PokerEvaluation evaluateHighFlush() const;
//PokerEvaluation evaluateHighThreeCard() const;
PokerEvaluation evaluateLowA5() const;
PokerEvaluation evaluate8LowA5() const;
PokerEvaluation evaluateLow2to7() const;
PokerEvaluation evaluateRanksLow2to7() const;
PokerEvaluation evaluateSuitsLow2to7() const;
PokerEvaluation evaluate3CP() const;
PokerEvaluation evaluateBadugi() const;
PokerEvaluation evaluatePairing() const;

// sub evaluations

/** return the number of outs to complete a straight
 * returns 8 for open ended
 * returns 4 for gutshot
 * returns 1 for runner runner
 */
int evaluateStraightOuts() const;

// overloaded operators, syntactic sugar. It is no secret that
// this is a bitset, so exposing bit operations should be ok.
// one thing that should be considered is implementing the &=, etc
// operators for efficiency and generality using boost::opperators
void    operator|= (const CardSet& c) { _cardmask |= c._cardmask; }
void    operator^= (const CardSet& c) { _cardmask ^= c._cardmask; }
bool    operator== (const CardSet& c) const { return _cardmask == c._cardmask; }
bool    operator!= (const CardSet& c) const { return _cardmask != c._cardmask; }
bool    operator< (const CardSet& c) const { return _cardmask < c._cardmask; }
bool    operator> (const CardSet& c) const { return _cardmask > c._cardmask; }
CardSet operator& (const CardSet& c) const { return CardSet(_cardmask &  c._cardmask);    }
CardSet operator| (const CardSet& c) const { return CardSet(_cardmask |  c._cardmask); }
CardSet operator^(const CardSet& c) const { return CardSet(_cardmask ^  c._cardmask); }

void swap(CardSet& c)
{
    uint64_t t = c._cardmask;
    c._cardmask = _cardmask;
    _cardmask = t;
}

protected:
void fromString (const std::string& s);   //!< throws exception on parse failre
bool isPaired () const;                   //!< returns true if *any* two cards match rank
bool isTripped () const;                  //!< returns true if trips

private:
//!< bit mask of cards in "canonical" order. [2c,3c ... Ac,Ad ... Ah ... Qs,Ks,As]
uint64_t _cardmask;
};

////////////////////////////////////////////////////////////////////////////////
// Below are standalone methods related to CardSet objects.  They should
// probably be moved to a separate file as they don't directly manipulate
// CardSet data. 
////////////////////////////////////////////////////////////////////////////////


/**
* cannonize a hand relative to a board
*/
CardSet canonizeToBoard(const CardSet& board, const CardSet& hand);


std::vector<int> findSuitPermutation(const CardSet& source, const CardSet& dest);
} // namespace pokerstove


/**
* our little printer
*/
std::ostream& operator<<(std::ostream& sout, const pokerstove::CardSet& e);

#endif  // PEVAL_CARDSET_H_

感谢您的阅读:)

4

1 回答 1

1

set_union问题是和的最后一个论点set_difference。的第二个参数std::inserter需要是作为第一个参数传递的容器的迭代器。但是您从不同的容器传递了一个迭代器:

std::inserter(ensemble_main, ensemble_main1.begin())
//                           ^^^^^^^^^^^^^^^^^^^^^^
//                          doesn't point in ensemble_main

您违反了函数的先决条件,并导致未定义的行为。set_difference似乎有效的事实只是一个(不)幸运的巧合。

于 2013-12-04T21:13:13.003 回答