I made this very simple solitaire in C++. The deck is random shuffled, I take a card and I pronunce in sequence Ace, One, Two, …, Ten, Jack, Queen, King. If the card is exactly what I pronunced I remove the card from the deck. I iterate the process using the remained deck until I remove cards or until the deck is empty (only in this case I win). This is the code I write but I’ve an error in the line 62 when I use the function erase to remove a card. I can’t understand which is the problem.
#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;
}
Well, when I launch it, I get
Obviously that means you are trying to access something beyond the vector bounds. You are erasing an element in the cycle:
After this hits, the size of the vector will be 51 instead of 52. However, your cycles are handling 52 values, as you clearly mention in this comment:
So after the item is removed and there are 51 items left in the deck (0 to 50), the last iteration will still try to access the 51st element and crash. The actual line where it fails is this one:
when the state is the following:

As you can see, there are 51 elements in the vector, and
*(deck.at(position))will try to access the 52nd one (which index is 51 since you count from zero), and throw the exception.