0

私はこの非常にシンプルなソリティアをC++で作成しました。デッキはランダムにシャッフルされ、カードを取り、エース、ワン、ツー、...、テン、ジャック、クイーン、キングの順に発音します。カードが私が発音したものとまったく同じである場合、私はそのカードをデッキから取り除きます。カードを取り除くか、デッキが空になるまで(この場合のみ勝ちます)、残っているデッキを使用してプロセスを繰り返します。これは私が書いたコードですが、関数eraseを使用してカードを削除すると、62行目にエラーが発生します。どちらが問題なのかわかりません。

#include <iostream>
#include <vector>
using namespace std;

enum SUIT { HEART, CLUB, DIAMOND, SPADE };
string suit_string[] = {"HEART", "CLUB", "DIAMOND", "SPADE"};

enum VALUE { ACE, TWO, THREE, FOUR, FIVE, SIX,
    SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING};
string value_string[] = {"ACE", "TWO", "THREE", "FOUR", "FIVE",
    "SIX", "SEVEN", "EIGHT","NINE", "TEN", "JACK", "QUEEN", "KING"};

class Card {
 public:
    Card(SUIT s, VALUE v);
    SUIT suit;
    VALUE value;
    string toString();
};

Card::Card(SUIT s, VALUE v){
    suit=s;
    value=v;
}

string Card::toString(){
    return value_string[(int)this->value]+" of "+suit_string[(int)this->suit];
}



int main() {
        vector<Card*> deck;
        for (int i=0; i<4; i++) {
            for (int j=0; j<13; j++) {
                deck.push_back(new Card((SUIT)i,(VALUE)j));
            }               
        }

        int removed_count, runs = 0;

        do{
            random_shuffle(deck.begin(),deck.end());
            removed_count=0;

            cout<<"--- Run number: "<<++runs<<"\n";
            cout<<"--- still "<<deck.size()<<" cards in the deck\n";

            for (int i=0; i<4; i++) {
                for (int j=0; j<13; j++) {
                    //cout<<i*13+j<<"\n";

                    int position=i*13+j; //from 0 to 51

                    cout<<"'"+value_string[j]+"'"<<" <-> ";

                    Card card=*(deck.at(position));
                    cout<<card.toString()<<" ";

                        if(card.value == j){
                            removed_count++;
                            deck.erase(deck.begin()+position); //problems here!
                            cout<<"removed\n";
                        }else{
                            cout<<"not removed\n";
                        }

                    }               
            }
            if(deck.empty()) break;
        }while(removed_count>0);

        if(deck.empty()){
            cout<<"You win!\n";
        }else{
            cout<<"You lose!\n";
        }

        return 0;
}
4

1 に答える 1

4

さて、起動すると

'KING' <-> terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check

明らかに、それはあなたがベクトルの境界を超えて何かにアクセスしようとしていることを意味します。サイクル内の要素を消去しています:

deck.erase(deck.begin()+position);

このヒットの後、ベクトルのサイズは52ではなく51になります。ただし、このコメントで明確に述べているように、サイクルは52の値を処理しています。

int position=i*13+j; //from 0 to 51

したがって、アイテムが削除され、デッキに51個のアイテム(0〜50)が残っている場合でも、最後の反復では51番目の要素にアクセスしてクラッシュします。失敗する実際の行は次のとおりです。

Card card=*(deck.at(position));

状態が次の場合: ここに画像の説明を入力してください

ご覧のとおり、ベクトルには51個の要素があり*(deck.at(position))、52番目の要素(ゼロから数えるのでインデックスは51)にアクセスしようとし、例外をスローします。

于 2012-09-28T12:11:37.013 に答える