C# Blackjack - Freezing?

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
TheFinalFanatic
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 14
Joined: Thu Oct 15, 2009 3:10 pm
Favorite Gaming Platforms: PC
Programming Language of Choice: C#
Location: That place. You know...Yea, that one.

C# Blackjack - Freezing?

Post by TheFinalFanatic »

So, I've been working on a basic console application game of blackjack using C#. All is going well, until I come across a strange problem. I haven't done any programming in a long time, and C# is a relatively new language to me, so the problem may be obvious. However, I fail to see it. Basically, the following code (in the main function) appears to freeze after running the first Draw method of case 1. It runs perfectly fine if I enter break mode and step through the code line by line, but when left to run freely appears to freeze.

Code: Select all

            Console.WriteLine("1 - Play Game");
            Console.WriteLine("2 - See Rules");

            int pChoice = Convert.ToInt32(Console.ReadLine());
            switch (pChoice)
            {
                case 1:
                    deck.Draw(ref player);
                    deck.Draw(ref player);
                    Debug.WriteLine("Player hand initialized.");
                    deck.Draw(ref opponent);
                    deck.Draw(ref opponent);
                    int turn = generator.Next(2);
                    switch (turn)
                    {
                        case 1:
                            if (turn == 1)
                                player.Turn(ref deck, ref player);
                            else
                                opponent.Turn(ref deck, ref player);
                            Console.ReadKey();
                            break;
                        case 2:
                            opponent.Turn(ref deck, ref player);
                            break;
                    }
                    break;
                case 2:
                    ShowRules();
                    break;
            }
This is the Draw() method in the Deck class. It generates a random value and a random suit for the card from two arrays, and checks against another array to see if the card has been used before or not, if it has, it redoes the loop, if not, it adds the card to the used array and changes the player's hand and score accordingly:

Code: Select all

        public void Draw(ref Player player)
        {
            Random generator = new Random();
            bool used = false;

            while (true)
            {
                int value = generator.Next(Names.Length);
                string name = Names[value] + Suits[generator.Next(Suits.Length)];

                for (int i = 0; i < Used.Length; i++)
                    {
                        if (name == Used[i])
                        {
                            used = true;
                            break;
                        }

                        if (Used[i + 1] == null)
                        {
                            break;
                        }
                    }

                if (used == false)
                {
                    cards--;
                    player.cards++;
                    Used[iter] = name;
                    iter++;
                    player.hand += name;
                    player.score += value;
                    Console.WriteLine("You drew a {0}!", name);
                    break;
                }
            }
        }
The opponent version of this function is simply overloaded with a small amount of modifications. Any ideas as to why this would be freezing?
User avatar
trufun202
Game Developer
Game Developer
Posts: 1105
Joined: Sun Sep 21, 2008 12:27 am
Location: Dallas, TX
Contact:

Re: C# Blackjack - Freezing?

Post by trufun202 »

TheFinalFanatic wrote:

Code: Select all

bool used = false;

            while (true)
            {
                int value = generator.Next(Names.Length);
                string name = Names[value] + Suits[generator.Next(Suits.Length)];
////////////--> used = false;
                for (int i = 0; i < Used.Length; i++)
                    {
                        if (name == Used[i])
                        {
                            used = true;
                            break;
                        }

                        if (Used[i + 1] == null)
                        {
                            break;
                        }
                    }

                if (used == false)
                {
                    cards--;
                    player.cards++;
                    Used[iter] = name;
                    iter++;
                    player.hand += name;
                    player.score += value;
                    Console.WriteLine("You drew a {0}!", name);
                    break;
                }
            }
        }
Any ideas as to why this would be freezing?
That while(true) looks mighty guilty... You need to reset the variable "used = false;" after setting a new name. (as marked above) For instance, say the first card randomly chosen IS used. (Used == true) Now, that while loop iteration is done, so we grab the next card. If that card is NOT used and falls through the for loop; however, "used" is NOT false. Welcome to the infinite loop.

By the way, rather than using a for loop to check for used cards, you could do something like this:

Code: Select all

List<string> UsedCards = new List<string>();

...

int value = generator.Next(Names.Length);
string name = Names[value] + Suits[generator.Next(Suits.Length)];

if (!UsedCards.Contains(name))
{
    UsedCards.Add(name);
   //do stuff
}
Also, I don't recommend reinstantiating a new Random with every Draw() invoke. A global can be used and it should be seeded. For instance:

Code: Select all

Random rand = new Random(DateTime.Now.Millisecond);
-Chris

YouTube | Twitter | Rad Raygun

“REAL ARTISTS SHIP” - Steve Jobs
TheFinalFanatic
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 14
Joined: Thu Oct 15, 2009 3:10 pm
Favorite Gaming Platforms: PC
Programming Language of Choice: C#
Location: That place. You know...Yea, that one.

Re: C# Blackjack - Freezing?

Post by TheFinalFanatic »

Appears to be working now, many thanks for the reply! :worship:
Using a list also seems like the better option, prevents the need to loop through the whole array on each invoke.

Still kinda confused as to why it would function correctly in it's previous state whilst in break mode though?
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: C# Blackjack - Freezing?

Post by dandymcgee »

trufun202 wrote:
Also, I don't recommend reinstantiating a new Random with every Draw() invoke. A global can be used and it should be seeded. For instance:

Code: Select all

Random rand = new Random(DateTime.Now.Millisecond);
While it's a good idea to make it global as to avoid repeated instantiation, the DateTime seed is redundant as C# uses the current time as a seed by default. The seed parameter is only there to help with debugging (by providing a constant seed).

Code: Select all

Random rand = new Random();
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
trufun202
Game Developer
Game Developer
Posts: 1105
Joined: Sun Sep 21, 2008 12:27 am
Location: Dallas, TX
Contact:

Re: C# Blackjack - Freezing?

Post by trufun202 »

dandymcgee wrote:
trufun202 wrote:
Also, I don't recommend reinstantiating a new Random with every Draw() invoke. A global can be used and it should be seeded. For instance:

Code: Select all

Random rand = new Random(DateTime.Now.Millisecond);
While it's a good idea to make it global as to avoid repeated instantiation, the DateTime seed is redundant as C# uses the current time as a seed by default. The seed parameter is only there to help with debugging (by providing a constant seed).

Code: Select all

Random rand = new Random();
touche. I've always just seeded out of habit I guess. ;)
-Chris

YouTube | Twitter | Rad Raygun

“REAL ARTISTS SHIP” - Steve Jobs
Post Reply