Question on scope

This is a discussion on Question on scope within the C++ Programming forums, part of the General Programming Boards category; I'm assuming my problem was due to scope due to how I fixed it. Since the code is long and ...

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    4

    Question on scope

    I'm assuming my problem was due to scope due to how I fixed it.

    Since the code is long and i think it's a simple problem I'm just going to explain it.

    The assignment was to make a BlackJack program. For my own enjoyment I was going to expand it to be a general card game program. So for the time being I have several global variables that I was going to assign to a parent CardGame class from wich BlackJack, Poker, etc would be derived. I say that because previously I have been told to avoid global variables.

    Anyway I have a global variable "int bet" Within the BlackJack class it hits the lines

    Code:
    while (getbet==false)
    	{
    		cout<<"How much would you like to bet?"<<endl<<" You have $"<<money<<"."<<endl;
    		cin>>bet;
    		if (bet>10)
    		{goodbet=true;}
    	if (bet<money&&goodbet==true)
    		{
    		money=money-bet;
    		pool=pool+bet;
    		getbet=true;
    		}
    	}
    When I ran? (start debugging) the program it became an infinite loop there.

    ~edit
    I should say it was an infinite loop repeating the message
    "How much would you like to bet?" " You have $"<<money<<"."
    ~edit

    However if I declare bet=0 immediately before the while statement the loop occurs as I intended it to.

    I assumed that it had to do with bet not having a value before the cin line, however the global variable is set as 'int bet=0;' so I'm not sure how adding the line I did changed anything.

    I know I should go through the code with the debugger a line at a time watching values,, however I am new to using it and only know how to start it from the beginning of Main() so it takes me about 30 minutes to get to the location. I guess as a second question if someone knows a source I could read about the debugger or say how to allow the program to run to a location and then let me go line by line from there. I only figured out what I know through trial and error.
    Last edited by Kiklion; 04-06-2009 at 02:48 PM.

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You could get into an infinite loop if cin failed (what was read was not a number). I guess one way that could happen is if some earlier input statement has left garbage in the input stream. For example, you ask for a players name and read it with operator>> while trying to enter more than one name (operator>> only reads up to the next whitespace character).

    So the problem may well be earlier.

    [edit]
    And how do you initialize goodbet?

    It could be a scope problem in a different way: why is goodbet not declared and initialized within the loop (close to where it is used) - and why do you need this variable in the first place?
    [/edit]
    Last edited by anon; 04-06-2009 at 03:17 PM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Registered User
    Join Date
    Mar 2009
    Posts
    4
    Thanks for responding. That may be a case with left over garbage in the input stream. The previous question is "Do you want to play another hand?" with cin>>yesno, where yesno is a char. I then checked yesno against 'y' and 'Y' in order to avoid problems where they input just a Y instead of Yes.

    The entire code upto Main() is as follows, incase what was previously posted wouldn't of left garbage. Still doesn't answer to me how inputting bet=0 immediately before the while statement would fix garbage in the stream.

    "goodbet" is a bool, it is a global variable. It is (or will be used often) whenever checking to make sure the bet/insurance etc is valid. In this scenario it makes sure the person bet's more then $10, which is the mininum as per professors instructions. In other parts it is to make sure people don't bet negatively and then lose on purpose... though in hindsight if I made it an unsigned int that could prevent people from betting negative money, however I am not too sure what an unsigned int is. Just that a signed int uses the first bit(?) to show pos/neg and an unsigned int does not have that so it can't be negative. What would happen if someone tried putting a negative number into an unsigned int?

    As I previously said all or almost all global variables will become part of a CardGame class which each game will derive from. I keep them global for now until I fulfill the assignment requirements so that they are all in one place before I go ahead with what I want to do.

    ~edit is there a way to make the code scrollable or is that done auto at a certain length?

    Code:
    #include <conio.h>
    #include <iostream>
    #include <list>
    #include <cstdlib>
    #include <ctime>
    #include <string.h>
    
    using namespace std;
    int money=0,pool=0,bet=0;
    bool ante;
    char yesno;
    bool getbet,goodbet;
    
    
    struct Card
    	{
    	int rank;
    	char suit;
    	int value;
    	}C;//end of Card
    
    struct Hand
    {
    	list<Card> main;
    	list<Card> side;
    	list<Card>::iterator hi;
    }Dealer,Player;//end of hand
    
    class Deck
    	{
    public:
    	void TakeCard(Card);
    	Card GetCard();
    	Deck Shuffle(Deck,Deck);
    	Deck();
    	Deck(int);	
    private:
    	list<Card> D1;
    	list<Card>::iterator di;
    	}MainD,TempD(0);//End of Deck Class
    
    
    Deck::Deck()
    	{
    	int suitcounter=0,rankcounter=2;
    	while (suitcounter!=4)
    		{
    		while (rankcounter!=15)
    			{
    			C.suit=suitcounter;
    			C.rank=rankcounter;
    			if (rankcounter>10&&rankcounter<14)
    			{C.value=10;}
    			else 
    			{C.value=rankcounter;}
    			D1.push_front(C);
    			++rankcounter;
    			}
    		rankcounter=2;
    		++suitcounter;
    		}
    	}//end of Deck::Deck
    Deck::Deck(int x)
    {}
    void Deck::TakeCard(Card C)
    	{
    	D1.push_front(C);
    	}//end of TakeCard
    
    Card Deck::GetCard()
    	{
    	Card tempCard;
    	list<Card> temp;
    	list<Card>::iterator ti;
    	srand((unsigned)time(0)); 
        int random,x;
    	x=D1.size();
    	random=(rand()%x); 
    	while (random!=0)
    		{
    		di=D1.begin();
    		C=*di;
    		//if (di!=D1.end())
    			//{
    			//++di;
    			//}
    		D1.pop_front();
    		temp.push_front(C);
    		--random;
    		}
    		di=D1.begin();
    		tempCard=*di;
    		D1.pop_front();
    
    	while (temp.size()!=0)
    		{
    		ti=temp.begin();
    		C=*ti;
    		//if (ti!=temp.end())
    			//{
    			//++ti;
    			//}
    		temp.pop_front();
    		D1.push_front(C);
    		}
    		
    	return(tempCard);
    	}// end of GetCard
    
    Deck Deck::Shuffle(Deck temp,Deck main)
    	{
    	int x;
    	x=(int) temp.D1.size();
    	while (x!=0)
    		{
    		C=temp.GetCard();
    		main.TakeCard(C);
    		--x;
    		}
    	return main;
    	}//end of shuffle
    
    class BlackJack
    	{
    	private:
    		int insurance;
    		int deals;
    		int sbet;
    		int value;
    		bool again;
    		bool duble;
    		bool split;
    	public:
    		BlackJack(int);
    		Card Hit();
    		void Fold();
    		void Split();
    		void Double();
    		void Surrender();
    		void NewHand();
    		void Insurance();
    	};//end of BlackJack declarations
    
    
    
    BlackJack::BlackJack(int cash)
    {	
    	ante=true;
    	again=true;
    	money=cash;
    
    	cout<<"Hello and welcome to BlackJack. You start with $"<<money<<". Good luck."<<endl;
    	_getche();
    	while (again==true)
    	{ 
    		if (money<10)
    			{
    			ante=false;
    			}	
    		cout<<"Play a hand?(Yes/No)"<<endl;
    		cin>>yesno;
    		if (yesno=='n'||yesno=='N')
    			{
    			again=false;
    			}
    		if (again==true&&ante==false)
    			{
    			cout<<"Sorry you don't have enough funds for the mininum bet(10)";
    			again=false;
    			}
    		if (again==true&&ante==true)
    			{
    				deals=deals+1;
    				if (deals==6)
    					{
    					MainD.Shuffle(TempD,MainD);
    					deals=1;
    					}
    				BlackJack::NewHand();
    			}
    	}
    	MainD.Shuffle(TempD,MainD);
    }//end of constructor
    
    void BlackJack::NewHand()
    {
    	string choice;
    	Card Compare;
    	getbet=false;
    	goodbet=false;
    	bet=0;
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
    	while (getbet==false)
    	{
    		cout<<"How much would you like to bet?"<<endl<<" You have $"<<money<<"."<<endl;
    		cin>>bet;
    		if (bet>10)
    		{goodbet=true;}
    	if (bet<money&&goodbet==true)
    		{
    		money=money-bet;
    		pool=pool+bet;
    		getbet=true;
    		}
    	}
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
    	getbet=false;
    	goodbet=false;
    	C=MainD.GetCard();
    	Player.main.push_front(C);
    	C=MainD.GetCard();
    	Dealer.main.push_front(C);
    	C=MainD.GetCard();
    	Player.main.push_front(C);
    	C=MainD.GetCard();
    	Dealer.main.push_front(C);
    	
    	Player.hi=Dealer.main.begin();
    	C=*Player.hi;
    	if (C.rank==12)
    	{
    		cout<<"The dealer has an ace, would you like insurance?(Yes/No)";
    		cin>>yesno;
    		if (yesno=='y'||yesno=='Y')
    		{
    			Insurance();
    			/*while (getbet=false)
    			{
    			cout<<"You currently have $"<<money<<", you may insure upto $"<<bet/2<<".";
    			cin>>insurance;
    			if(insurance>=0)
    			{goodbet=true;}
    			if (insurance<money&&insurance<(bet/2)&&goodbet==true)
    			{
    				money=money-insurance;
    				Dealer.hi=Dealer.main.end();
    				C=*Dealer.hi;
    				if (C.value==10)
    				{
    					cout<<"The dealer has BlackJack, you win the insurance";
    					money=money+2*(insurance);
    				}
    				insurance=0;
    			}
    			else
    			{cout<<"Your insurance bet did not meet the requirements, bet again";}
    			}*/
    		}
    	}
    
    	
    	Player.hi=Player.main.begin();
    	C=*Player.hi;
    	Player.hi=Player.main.end();
    	Compare=*Player.hi;
    	cout<<"Your cards are a "<<C.rank<<" of "<<C.suit<<" and a "<<Compare.rank<<" of "<<Compare.suit<<".";
    	if (C.rank==Compare.rank)
    	{split=true;}
    
    	if (split==true)
    		{
    		cout<<"Would you like you Split?";
    		cin>>yesno;
    		if (yesno=='y'||yesno=='Y')
    			{
    			if (money>=bet)
    				{
    				Split();
    				}
    			else
    				{
    				cout<<"Not enough cash to split.";
    				}
    			}
    		}
    
    }

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Here's a simplified example of your problem:

    Code:
    #include <iostream>
    #include <cctype>
    
    int main()
    {
        char yesno;
        int bet = 0;
    
        std::cout << "Yes on no? ";
        std::cin >> yesno;
    
        if (tolower(yesno) == 'y') {
            do {
                std::cout << "Enter a number larger than 10: ";
                std::cin >> bet;
            } while (bet <= 10);
        }
    }
    There are two ways to get an infinite loop here.

    When you type "Yes" at the first prompt, only one character is read and "es" is left over in the stream. Next time "es" is read, but since an integer is expected, the input fails causing all following inputs to fail as long as the programmer doesn't do anything about the input problem.

    The other way is to type a non-number at the second prompt yourself, leading to the same situation.

    You should deal with input errors, namely clearing the stream's error bits (indicating that an error happened and the stream isn't in a usable state) and removing the unnecessary unread characters that caused or can cause the input to fail.

    So a code that is more resistant to input errors:

    Code:
    #include <iostream>
    #include <cctype>
    #include <limits>
    
    void clear_stream(std::istream& is)
    {
        //clear error bits
        is.clear();
        //remove unread characters
        is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    
    int main()
    {
        char yesno;
        int bet = 0;
    
        std::cout << "Yes on no? ";
        std::cin >> yesno;
    
        if (tolower(yesno) == 'y') {
            clear_stream(std::cin);
            do {
                std::cout << "Enter a number larger than 10: ";
                while (!(std::cin >> bet)) {
                    std::cout << "A number please: ";
                    clear_stream(std::cin);
                }
            } while (bet <= 10);
        }
    }
    "goodbet" is a bool, it is a global variable. It is (or will be used often) whenever checking to make sure the bet/insurance etc is valid.
    This is not a very good reason to make it a global (and other globals you have there) because you can always declare a local by the same name. Thankfully it seems that you are using most of your globals as local variables (setting their value at the beginning of the functions) but as soon as you start making functions rely on such globally set flags, the code goes into terrible spaghetti. Still, making them global simply means that if you forget to assign them a value somewhere, you could start getting weird errors that depend mystically on what the user has been doing etc.

    IMO, the logic of this loop is rather overcomplicated with the use of these boolean variables.
    Last edited by anon; 04-07-2009 at 04:24 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Scope Related question
    By csonx_p in forum C++ Programming
    Replies: 13
    Last Post: 08-24-2008, 12:02 PM
  2. Question regarding Memory Leak
    By clegs in forum C++ Programming
    Replies: 29
    Last Post: 12-07-2007, 01:57 AM
  3. Design layer question
    By mdoland in forum C# Programming
    Replies: 0
    Last Post: 10-19-2007, 05:22 AM
  4. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 10:47 PM
  5. opengl DC question
    By SAMSAM in forum Game Programming
    Replies: 6
    Last Post: 02-26-2003, 09:22 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21