Unhandled Exception Error

Started by
2 comments, last by Zahlman 18 years, 7 months ago
Well, I'm pretty new here... Anyways, I have this error that I just can't fix (I've been looking at it for a week), so do you think you can help me? The problem is that when I run the program(A Poker game I'm working on) it pops up with a "Unhandled Exception Error" when I try to print out a card class (You'll see in the code). What I want to do is to circumvent the Unhandled Exception in such a way that it will still work. I think the error is caused by a pointer but I have no idea how... The code is a bit long and without many comments... Thanks in advance. BTW: It's loosely based on the BlackJack game in the Beginning C++ Game Programming book.
//Poker
//INCLUDES
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>

using namespace std;
//GLOBALS
const int SMALLBLIND = 50;
const int BIGBLIND = 100;
const int ANTI = 20;
enum rank{ACE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING};
enum suit{CLUBS, HEARTS, DIAMONDS, SPADES};

//CLASSES
class card
{
public: 
	friend ostream& operator<<(ostream &os, const card& aCard);
	card(rank r, suit s):cRank(r), cSuit(s){};
	rank getRank();
	suit getSuit();
protected:
	rank cRank;
	suit cSuit;
};

rank card::getRank()
{
	return cRank;
}

suit card::getSuit()
{
	return cSuit;
}

class field
{
public:
	field();
	virtual ~field();
	void addCard(card* aCard);
	void clear();
	int getCall();
	void addToPot(int x);
	void setLastBetter(int x);
	card* getBack(int x);
protected:
	int call;
	int pot;
	int lastBetter;
	vector <card*> cards;
};

field::field()
{
	cards.reserve(5);
	call=BIGBLIND;
	pot=0;
}

field::~field()
{
	clear();
}

void field::addCard(card* aCard)
{
	cards.push_back(aCard);
}

void field::clear()
{
	vector<card*>::iterator iter = cards.begin();
	for(iter = cards.begin(); iter != cards.end(); iter++)
	{
		delete *iter;
		*iter=0;
	}
	cards.clear();
	pot=0;
	call=BIGBLIND;
}

card* field::getBack(int x)
{
	return cards.back() - x;
}

int field::getCall()
{
	return call;
}

void field::addToPot(int x)
{
	pot += x;
}

void field::setLastBetter(int x)
{
	lastBetter = x;
}

class hand : public field
{
public:
	hand();
	void rateHand(field& aField);
protected:
	int handRank;
	int rankRank;
	int kicker;
};



hand::hand()
{
}

void hand::rateHand(field& aField)
{
	bool isPair = false;
	bool isTriple = false;
	bool isTwoPair = false;
	bool isFlush = false;
	bool isStraight = false;
	bool isStraightFlush = false;
	bool isQuad = false;
	bool isRoyaleFlush = false;

	int flushSuit;

	for(int i = 0; i < 5; i++)
		addCard(aField.getBack(i));

	sort(cards.begin(), cards.end());
	

	vector<int> pairs;
	//Finds a pair
	vector<card*>::const_iterator iter1 = cards.begin();
	vector<card*>::const_iterator iter2 = cards.begin();
	for(iter1 = cards.begin(); iter1 != cards.end(); iter1++)
		for(iter2 = cards.begin(); iter2 != cards.end(); iter2++)
			if(iter1 != iter2)
				if((*iter1)->getRank() == (*iter2)->getRank())
					pairs.push_back((*iter1)->getRank());
					isPair = true;
					
	vector<int> cardsRanking;

	for(iter1 = cards.begin(); iter1 != cards.end(); iter1++)
		cardsRanking.push_back((*iter1)->getRank());

	sort(cardsRanking.begin(), cardsRanking.end());
	kicker = (cards.back())->getRank();

	vector<card*> spades;
	vector<card*> clubs;
	vector<card*> hearts;
	vector<card*> diamonds;
	
	//Sorts the cards into their respected suits and checks for a flush
	for(iter1 = cards.begin(); iter1 != cards.end(); iter1++)
		switch((*iter1)->getSuit())
		{
		case SPADES:
			spades.push_back(*iter1);
			break;
		case CLUBS:
			clubs.push_back(*iter1);
			break;
		case HEARTS:
			hearts.push_back(*iter1);
			break;
		case DIAMONDS:
			diamonds.push_back(*iter1);
			break;
		}

	vector<int> flush;

	if(spades.size() >= 5)
		isFlush = true;
		flushSuit = SPADES;
		for(iter1 = spades.begin(); iter1 != spades.end(); iter1++)
			flush.push_back((*iter1)->getRank());
	if(clubs.size() >= 5)
		isFlush = true;
		flushSuit = CLUBS;
		for(iter1 = clubs.begin(); iter1 != clubs.end(); iter1++)
			flush.push_back((*iter1)->getRank());
	if(hearts.size() >= 5)
		isFlush = true;
		flushSuit = HEARTS;
		for(iter1 = hearts.begin(); iter1 != hearts.end(); iter1++)
			flush.push_back((*iter1)->getRank());
	if(diamonds.size() >= 5)
		isFlush = true;
		flushSuit = DIAMONDS;
		for(iter1 = diamonds.begin(); iter1 != diamonds.end(); iter1++)
			flush.push_back((*iter1)->getRank());
	
	//Sorts the card rankings in order
	sort(cardsRanking.begin(), cardsRanking.end());
	int z = 0;
	vector<int> straight;
	vector<int>::const_iterator iter3;
	vector<int>::const_iterator iter4;
		
	/*
	A bit of explaining here will do nicely. The first loop starts off with the 
	lowest card since it was sorted previously, and if the first card is an ace
	the variable z will hold the number one, I'll show you the purpose of that 
	later. The second loop will start out with that first if statement. Should 
	iter4 be less than or equal to iter3, it will start the loop over again with 
	the next iteration, this is to prevent any more computing than it has to. The
	second if statement sees if iter4 is one above iter3, and should it be that 
	way then it will add iter3 into the vector straight and then it will break.
	If it isn't that way then it will see if there is already a straight already,
	if not then it will clear away straight. The last else if clause is for the 
	king, since ace is the lowest card, but can also be higher than the king.
	*/
	for(iter3 = cardsRanking.begin(); iter3 != cardsRanking.end(); iter1++)
	{
		if((*iter3) == 1)
		{
			z = 1;
		}
		for(iter4 = cardsRanking.begin(); iter4 != cardsRanking.end(); iter2++)
		{
			if(iter4 <= iter3 && *iter3 != 13)
				continue;
			if(*iter4 == (*iter3) + 1 || (*iter4) + 24 == (*iter3) + 12)
			{
				straight.push_back(*iter3);
				break;
			}
			else if(*iter3 != cardsRanking.back() && *iter3 != 13)
			{
				straight.push_back(*iter4);
				if(straight.size() < 5)
					straight.clear();				
			}
			else if((*iter3) == 13 )
			{
				if(z == 1)
				{
					straight.push_back(*iter3);
					break;
				}
			}
		}
	}
	
	//Sees if there is a straight
	if(straight.size() >= 5)
		isStraight = true;

	vector<int> straightFlush;

	//Sees if there is a straigh within the flush
	sort(flush.begin(), flush.end());
	if(isFlush && isStraight)
		for(iter3 = flush.begin(); iter3 != flush.end(); iter1++)
		{
			if((*iter3) == 1)
			{
				z = 1;
			}
			for(iter4 = flush.begin(); iter4 != flush.end(); iter2++)
			{
				if(iter4 <= iter3 && *iter3 != 13)
					continue;
				if(*iter4 == (*iter3) + 1 || (*iter4) + 24 == (*iter3) + 12)
				{
					straightFlush.push_back(*iter3);
					break;
				}
				else if(*iter3 != flush.back() && *iter3 != 13)
				{
					straightFlush.push_back(*iter4);
					if(straightFlush.size() < 5)
						straightFlush.clear();				
				}
				else if((*iter3) == 13 )
				{
					if(z == 1)
					{
						straightFlush.push_back(*iter3);
						break;
					}
				}
			}
		}
		
	if(straightFlush.size() >= 5)
		isStraightFlush = true;	

	if(isStraightFlush)
	{
		if(straightFlush.back() == ACE)
		{
			handRank = 10;
			rankRank = 14;
		}
		else
		{
			handRank = 8;
			rankRank = straightFlush.back();
		}
	}
	else if(isPair)
	{
		if(pairs.size() == 6)
		{
			handRank = 9;
			rankRank = pairs.back();
		}
		else if(pairs.size() == 4)
		{
			handRank = 7;
			int t, u;
			for(iter3 = pairs.begin(); iter3 != pairs.end(); iter3++)
			{
				if(iter3 == pairs.begin())
					t = *iter3;
				if(iter3 != pairs.begin())
					u = *iter3;
				rankRank = u + t;
			}
		}
		else if(pairs.size() == 3)
		{
			handRank = 4;
			rankRank = pairs.back();
		}
		else if(pairs.size() == 2)
		{
			handRank = 3;
			int t, u;
			for(iter3 = pairs.begin(); iter3 != pairs.end(); iter3++)
			{
				if(iter3 == pairs.begin())
					t = *iter3;
				if(iter3 != pairs.begin())
					u = *iter3;
				rankRank = u + t;
			}
		}
		else if(pairs.size() == 1)
		{
			handRank = 2;
			rankRank = pairs.back();
		}
	}
	if(!isStraightFlush)
	{
		if(isStraight)
		{
			handRank = 6;
			rankRank = straight.back();
		}
		else if(isFlush)
		{
			handRank = 5;
			rankRank = flush.back();
		}
	}
}



class genericPlayer : public hand
{
public:
	friend ostream& operator<<(ostream& os, const genericPlayer& aPlayer);
	enum blind{NOBLIND, SMBLIND, BGBLIND, DEALER};
	genericPlayer(string n, int x):name(n), id(x), money(5000){cards.reserve(7);};
	genericPlayer() {};
	bool isBankrupt();
	virtual bool isBetting(field& aField, int max) = 0;
	void setBlind(blind b);
	int getMoney();
	int getId();
	string getName();
protected:
	string name;
	int money;
	bool bet;
	blind whatBlind; 
	int round;
	int status;
	int id;
};

string genericPlayer::getName()
{
	return name;
}

int genericPlayer::getId()
{
	return id;
}

bool genericPlayer::isBankrupt()
{
	if(!money)
		return true;
	else
		return false;
}

int genericPlayer::getMoney()
{
	return money;
}

class player : public genericPlayer
{
public:
	player();
	bool isBetting(field& aField, int max);
	void borrow();
protected:
	int borrowAmount;
};

player::player()
{
	id = 1;
	money = 5000;
}

bool player::isBetting(field& aField, int max)
{
	int x;
	int y;
	if(round == 1)
	{
		cout <<"What would you like to do?\n";
		cout << "1. Raise \n";
		if(whatBlind == BGBLIND && aField.getCall() == BIGBLIND)
            cout<< "2. Check \n";
		else
			cout<< "3. Call \n";
		cout << "4. Fold \n";
		cin >> x;
		switch(x)
		{
		case 1:
			cout << "How much do you want to raise? \n";
			cin >> y;
			if(money < aField.getCall() + y || aField.getCall() + y > max)
				cout << "You can't raise that much \n";
			else
				aField.addToPot(aField.getCall() + y);
				money -= aField.getCall() + y;
				aField.setLastBetter(id);
				cout << "You raise to " << aField.getCall() + y << " \n";
				break;
		case 2:
			if(whatBlind == BGBLIND && aField.getCall() == BIGBLIND)
				cout << "You check. \n";
				break;
		case 3:
			if(whatBlind == SMBLIND)
				aField.addToPot(aField.getCall() - SMALLBLIND);
				money -= (aField.getCall() - SMALLBLIND);
			if(whatBlind == BGBLIND)
				aField.addToPot(aField.getCall() - BIGBLIND);
				money -= (aField.getCall() - BIGBLIND);
			cout << "You call " << aField.getCall() << " \n";
			break;
		case 4:
			status = 0;
			cout << "You folded \n";
			break;

		}
	}
	else
	{
		cout <<"What would you like to do?\n";
		if(!aField.getCall())
			cout << "1. Bet \n";
		else
			cout << "2. Raise \n";
		if(!aField.getCall())
            cout<< "3. Check \n";
		else
			cout<< "4. Call \n";
		cout << "5. Fold \n";
		cin >> x;
		switch(x)
		{
		case 1:
			if(!aField.getCall())
				cout << "How much do you want to bet? \n";
				cin >> y;
				if(money < y || y > max)
					cout << "You can't bet that much. \n";
				else
					aField.addToPot(aField.getCall() + y);
					money -= y;
					aField.setLastBetter(id);
					cout << "You bet << y << \n";
					break;
		case 2:
			if(aField.getCall())
				cout << "How much do you want to raise? \n";
				cin >> y;
				if(money < aField.getCall() + y  || aField.getCall() + y > max)
					cout << "You can't bet that much. \n";
				else
					aField.addToPot(aField.getCall() + y);
					money -= aField.getCall() + y;
					aField.setLastBetter(id);
					cout << "You raise to " << aField.getCall() + y << " \n";
					break;
		case 3:
			if(!aField.getCall())
				cout << "You check. \n";
				break;
		case 4:
			if(aField.getCall())
				aField.addToPot(aField.getCall());
				money -= aField.getCall();
				cout << "You call " << aField.getCall() << " \n";
				break;
		case 5:
			status = 0;
			cout << "You folded \n";
			break;
		}
	}
	return true;
}

void player::borrow()
{
}

class cPlayer : public genericPlayer
{
public:
	cPlayer(string n, int x); 
	bool isBetting(field& aField, int max);
	void setStats();
private:
	int aggresive;
	int intelligent;
};

cPlayer::cPlayer(string n, int x)
{
	genericPlayer(n, x);
	money = 5000;
}

bool cPlayer::isBetting(field& aField, int max)
{
	if(!aField.getCall())
		cout << name << " checks. \n";
	else if(aField.getCall())
		aField.addToPot(aField.getCall());
		money -= aField.getCall();
		cout << name << " calls " << aField.getCall() <<" \n";
	system("PAUSE");
	return true;
}

class deck : public field
{
public:
	deck();
	virtual ~deck();
	void populate();
	void shuffle();
	void deal(genericPlayer& aPlayer);
	void flop(field& aField);
	void turn(field& aField);
};

deck::deck()
{
	cards.reserve(52);
	populate();
}

deck::~deck()
{}

void deck::populate()
{
	clear();
	for(int s = CLUBS; s <= SPADES; s++)
	{
		for(int r = ACE; r <= KING; r++)
		{
			addCard(new card(static_cast<rank>(r), static_cast<suit>(s)));
		}
	}
}

void deck::shuffle()
{
	random_shuffle(cards.begin(), cards.end());
}

void deck::deal(genericPlayer& aPlayer)
{
	if(!cards.empty())
	{
		aPlayer.addCard(cards.back());
		cards.pop_back();
	}
	else
	{
		cout<<"No More Cards\n";
	}
}

void deck::flop(field& aField)
{
	if(!cards.empty())
	{
		cards.pop_back();
		for(int i = 0; i < 3; i++)
		{
			aField.addCard(cards.back());
			cards.pop_back();
		}
	}
	else
	{
		cout<<"No More Cards\n";
	}
}


void deck::turn(field& aField)
{
	if(!cards.empty())
	{
		cards.pop_back();
		aField.addCard(cards.back());
		cards.pop_back();
	}
	else
	{
		cout<<"No More Cards\n";
	}
}

class game
{
public:
	game(vector<string> &n);
	void play();
	void updateScore();
protected:
	player human;
	vector<cPlayer> computers;
	field pokerField;
	deck standardDeck;
	vector<int> score;
	int shortStack;
	vector<string> mNames;
};

game::game(vector<string> &n)
{
	mNames = n;
	vector<string>::iterator iter;
	int x = 2;
	for(iter = mNames.begin(); iter != mNames.end(); iter++)
	{
		computers.push_back(cPlayer(*iter , x));
	}
	srand(time(0));
	standardDeck.populate();
	standardDeck.shuffle();
}

void game::play()
{
	int numNotBankrupt = 0;
	vector<cPlayer>::iterator iter;
	for(iter = computers.begin(); iter != computers.end(); iter++)
	{
		if(!(iter->isBankrupt()))
			numNotBankrupt++;
	}
	if(!(human.isBankrupt()))
		numNotBankrupt++;

	cout << numNotBankrupt << "\n";
	while(numNotBankrupt > 2)
	{
		for(int index = 0; index < 2; index++)
		{
			for(iter = computers.begin(); iter != computers.end(); iter++)
			{
				standardDeck.deal(*iter);
			}
			standardDeck.deal(human);
			cout << human << "\n";
		}
		human.isBetting(pokerField, shortStack);
		updateScore();
		for(iter = computers.begin(); iter != computers.end(); iter++)
		{
			iter->isBetting(pokerField, shortStack);
			updateScore();
		}
		
		
		standardDeck.flop(pokerField);
		human.isBetting(pokerField, shortStack);
		updateScore();
		for(iter = computers.begin(); iter != computers.end(); iter++)
		{
			iter->isBetting(pokerField, shortStack);
			updateScore();
		}
		

		standardDeck.turn(pokerField);
		human.isBetting(pokerField, shortStack);
		updateScore();
		for(iter = computers.begin(); iter != computers.end(); iter++)
		{
			iter->isBetting(pokerField, shortStack);
			updateScore();
		}
		

		standardDeck.turn(pokerField);
		human.isBetting(pokerField, shortStack);
		for(iter = computers.begin(); iter != computers.end(); iter++)
		{
			iter->isBetting(pokerField, shortStack);
			updateScore();
		}
		for(iter = computers.begin(); iter != computers.end(); iter++)
		{
			if(!(iter->isBankrupt()))
				numNotBankrupt++;
		}
		if(!(human.isBankrupt()))
			numNotBankrupt++;
		pokerField.clear();
        standardDeck.populate();
		standardDeck.shuffle();
	}
}

void game::updateScore()
{
	vector<cPlayer>::iterator iter;
	for(iter = computers.begin(); iter != computers.end(); iter++)	{
		score.push_back(iter->getMoney());
	}
	score.push_back(human.getMoney());
	sort(score.begin(), score.end());
	shortStack = score.front();
}

//PROTOTYPES
ostream& operator<<(ostream& os, const card& aCard);
ostream& operator<<(ostream& os, const genericPlayer& aPlayer);

//MAIN
int main()
{
	int x;
	for(;;)
	{
		cout << "How many computer players do you want? (1-7)\n";
		cin >> x;
		if(x < 1 || x > 7)
		{
			cout << "Pick a number between 1 and 7. \n";
		}
		else
		{
			break;
		}
	}
	
	vector<string> names;
	string y;
	for(int i = 0; i < x; i++)
	{
		cout << "What would you like to name computer number " << i + 1 << "? \n"; 
		cin >> y;
		names.push_back(y);
	}
	game aGame(names);
	aGame.play();
	system("PAUSE");
	return 0;
}


ostream& operator<<(ostream& os, const card& aCard)
{
	string suits[]={"Clubs", "Hearts", "Diamonds", "Spades"};
	string ranks[]={0, "Ace", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};
	
	os << ranks[aCard.cRank] << " Of " << suits[aCard.cSuit];
	return os;
}
ostream& operator<<(ostream& os, const genericPlayer& aPlayer)
{
	if(aPlayer.id == 1)
	{
		os << "Your ";
	}
	else
	{
		os << aPlayer.name << "'s ";
	}
	cout << "cards: \n";
	vector<card*>::const_iterator iter;
	
	for(iter = aPlayer.cards.begin(); iter != aPlayer.cards.end(); iter++)
	{
		os << *(*iter) << "\n";
	}
	return os;
}
Advertisement
Try changing your card class ostream to this:

ostream& operator<<(ostream& os, const card& aCard){	string suits[]={"Clubs", "Hearts", "Diamonds", "Spades"};	string ranks[]={"", "Ace", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};		os << ranks[aCard.cRank] << " Of " << suits[aCard.cSuit];	return os;}


The problem was that you were trying to assign a null value to a stack variable (non-pointer).

so this:

string ranks[]={0, "Ace", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};

needs to be this:

string ranks[]={"", "Ace", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};

Hope this helps! Good luck!
Thank You!
It worked! The only thing is why did it work? I want to be able to fix it again if it ever happens.
//EDIT
Whoops! Didn't see your explanation...
To be a bit more accurate: When you initialize the string array, the generated code makes an array of std::string objects, and attempts to initialize each using the char* that's provided to it. (string literals in double quotes are char*'s, not std::strings). The way this works is that the std::string constructor looks for data starting at the indicated pointer, and tries to copy it into its buffer. Given a null pointer - boom.

This topic is closed to new replies.

Advertisement