0

カード ゲームを扱う C++ コードがいくつかありますが、セグメンテーション違反が発生しており、その理由がわかりません。より明確なエラーを取得するために MSVS 2012 で実行しようとしたところ、「Vector is not dereferencable」がスローされました。私はいくつかの調査を試みましたが、エラーがどこから来ているのかわかりません。ほとんどの場合、問題の行が機能するため、バグは push_back ではなく別の場所にあると思います。エラーは Table::hit() で発生します。コードを調べた後、バグは Hand::split() にある可能性があると思いますが、よくわかりませんし、修正方法もよくわかりません。ありがとう!

class Hand
{    
public:
std::vector<Card> hand;
bool active, doubled, isBlackjack, busted;

Hand() : active(true), doubled(false), isBlackjack(false), busted(false) { }
Hand(const Hand& _hand);

void removeCard(Card card) { hand.erase( hand.begin() ); }
Card split();
void clear();
int cards() const { return hand.size(); }
int getHandValue() const;
Card at(int pos) { return hand[pos]; }

friend std::ostream& operator<< (std::ostream& out, const Hand& hand);
friend std::ostream& operator<< (std::ostream& out, const std::vector<Hand>& hands);
};

Hand::Hand(const Hand& _hand)
: hand(_hand.hand), active(_hand.active), doubled(_hand.doubled), isBlackjack(_hand.isBlackjack), busted(_hand.busted)
{ }

Card Hand::split()
{ //COULD THE BELOW CODE BE CAUSING ISSUES?
Card card = hand[0];

hand.erase( hand.begin() );

return card;    
}

void Hand::clear()
{
active = true;
hand.clear();
}

int Hand::getHandValue() const
{
int value(0), aces(0);

for(std::vector<Card>::const_iterator it = hand.cbegin(); it != hand.cend(); ++it)
{
    value += getCardValue(it->getRank());
    if(it->getRank() == ACE)
        ++aces;
}

while(aces > 0 && value > 21)
{
    value -= 10;
    --aces;
}

return value;
}

std::ostream& operator<< (std::ostream& out, const Hand& hand)
{
for(std::vector<Card>::const_iterator it = hand.hand.begin(); it != hand.hand.end(); ++it)
{
    out << *it << " ";
}

out << hand.getHandValue();

return out;
}

std::ostream& operator<< (std::ostream& out, const std::vector<Hand>& hands)
{
for(std::vector<Hand>::const_iterator it = hands.begin(); it != hands.end(); ++it)
{
    out << *it << " ";
}

return out;
}

class Table
{
protected:
Shoe shoe;
Strategy strat;
Hand dealer;
std::vector< Hand > player;

double balance, blackjackPayoff;
bool hitSoft17;

void deal();

void hit(int split=0);

void split(int split=0);

double stand();

Action getUserAction();

bool isCurrentGame();

public:
Table(int decks, int _balance);

double bet;

void play();

void print();

void simulate(std::string fileName, int hands);
};

 Table::Table(int decks, int _balance)
: shoe(decks), balance(_balance), blackjackPayoff(1.5), hitSoft17(true), bet(10)
{}

bool Table::isCurrentGame()
{
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
    if(it->active)
        return true;
}

return false;
}

void Table::deal()
{
dealer.clear();
player.clear();

dealer.addCard( shoe.pullCard(true) );
dealer.addCard( shoe.pullCard() );

player.push_back(Hand());

player[0].addCard( shoe.pullCard() );
player[0].addCard( shoe.pullCard() );

if(player[0].getHandValue() == 21 && dealer.getHandValue() == 21)
{
    player[0].active = false;
}
else if(player[0].getHandValue() == 21)
{
    player[0].active = false;
}
else if(dealer.getHandValue() == 21)
{
    player[0].active = false;
}

}

void Table::hit(int split)
{
player[split].hand.push_back( shoe.pullCard() ); //SEGFAULT HERE

if(player[split].getHandValue() > 21)
{
    player[split].active = false;
}
}

void Table::split(int split)
{ 
player.push_back(Hand());
player[player.size() - 1].hand.push_back( player[split].split() );
player[split].hand.push_back( shoe.pullCard() );
player[player.size() - 1].hand.push_back( shoe.pullCard() );

if(player[split].getHandValue() == 21)
{
    player[split].active = false;
}
else if(player[player.size() - 1].getHandValue() == 21)
{
    player[player.size() - 1].active = false;
}

}

double Table::stand()
{
double winnings(0.0);
bool allNats(true);
//dealer.push_back( shoe.pullCard() );
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
    if(it->cards() == 2 && it->getHandValue() == 21)
    {
        winnings += bet * blackjackPayoff;
        it->isBlackjack = true;
    }
    else
    {
        allNats = false;
        if(it->getHandValue() > 21)
            it->busted = true;
    }
}

if(!allNats)
{
    while(dealer.getHandValue() <= 17)
    {
        if(dealer.getHandValue() == 17)
        {
            //dealer has 17 and doesnt hit soft 17s so hes not going to draw anymore cards
            if( !hitSoft17 || dealer.cards() != 2 || !(dealer.hand.at(0) == ACE || dealer.hand.at(1) == ACE) )
                break;
        }

        dealer.addCard( shoe.pullCard() );
    }
}

for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
    if(!it->isBlackjack)
    {
        if(it->busted)
        {
            if(it->doubled)
                winnings -= 2.0 * bet;
            else
                winnings -= bet;
        }
        else if(dealer.getHandValue() > 21 || dealer.getHandValue() < it->getHandValue())
        {
            if(it->doubled)
                winnings += 2.0 * bet;
            else
                winnings += bet;
        }
        else if(dealer.getHandValue() > it->getHandValue())
        {
            if(it->doubled)
                winnings -= 2.0 * bet;
            else
                winnings -= bet;
        }
    }
}
//only other scenario is a push which we dont do anythign for

return winnings;
}

void Table::simulate(std::string fileName, int hands)
{
int i(0), countHL;
double trueCountHL;
std::ofstream ofs(fileName);

Action action;

while(i < hands)
{
    deal();
    VisibleCards vc(player[0].at(0), player[0].at(1), dealer.at(0));
    while(isCurrentGame())
    {
        int j(0), q(1);
        countHL = shoe.getCountHL();
        trueCountHL = shoe.getTrueCountHL();

        for(int l = 0; l < q; ++l)
        {
            while(player[l].active)
            {

                if(player[l].cards() == 2)
                    action = getBasicStrategy(player[l].getHandValue(), dealer.at(0).getCardValue(),
                                player[l].at(0).getCardValue(), player[l].at(1).getCardValue());
                else
                    action = getBasicStrategy(player[l].getHandValue(), dealer.at(0).getCardValue());

                switch(action)
                {
                case HIT:
                    hit(j);
                    break;
                case DOUBLE:
                    hit(j);
                    if(player[l].cards() == 3)
                    {
                        player[l].doubled = true;
                        player[l].active = false;
                    }
                    break;
                case SPLIT:
                    if(player.size() <= 4)
                    {
                        split(j);
                        ++q;
                    }
                    else
                        hit(j);

                    break;
                case STAND:
                    player[l].active = false;
                    break;
                }

                ++j;
            }
        }
    }

    double winnings = stand();
    balance += winnings;

    ofs << std::endl << std::fixed << vc << "," << winnings << "," << std::setprecision(2) << trueCountHL
        << "," << balance << "," << std::setprecision(0) << countHL << "," << shoe.getRemainingDecks();
    ofs << std::endl << 1;
    //BlackjackData bjd(winnings, balance, shoe.getTrueCountHL(), shoe.getCountHL(), HIT);      
    //strat.addData(vc, bjd);
    ++i;
}

strat.print(fileName);
}
4

2 に答える 2

2

hand最初のカードがあることを最初にチェックして、最初のカードをチェックhand[0]hand.erase(hand.begin())ずに最初のカードを取得しようとしているようです。が空の場合hand(コンストラクターから新しく作成された場合のようにHand)、未定義の動作が発生し、後でクラッシュとして現れる可能性があります。

于 2013-09-09T20:46:50.290 に答える
0

私はこれを1日じっと見つめていましたが、それを理解できませんでした。外に出て、「hit」関数を呼び出していたときに「l」の代わりにベクトルにアクセスするために使用していた古い変数「j」があることに気付きました。 ... 助けてくれてありがとう。

于 2013-09-10T03:10:08.547 に答える