Question Making a list or array that changes?

jclark94

Member
Joined
Jan 14, 2020
Messages
5
Programming Experience
Beginner
Im developing a Blackjack Card game in C#, when you play you and the dealer each get 2 cards (card1 card2). I've been trying to figure out how when I input the "hit" command it will deal another random card (card3), and keep drawing cards. Im very new to c# still
 
You need to provide a far better description of the problem, which may mean putting in more thought and work before posting. The title talks about one thing and the post talks about another that are unrelated. One of the big reasons that beginners have problems is that they don't consider breaking a problem down into parts and then tackling each part separately. That is a big part of problem solving and certainly a big part of programming. If you want to learn how to make a list change then you can learn that in isolation, without any relation to cards or random selections. If you want to learn how to make random selections then you can do that without any relation to cards or changing lists. Etc, etc. Once you understand all the parts, you can then put them together into a cohesive whole that solves your overall problem.

So, what are you actually having a problem with? What specific step in the overall process are you trying to achieve? What have you done to try to achieve it? What happened when you tried it?

Of course, to identify which step in the process you are on, you have to have identified the steps, which you should be doing before writing any code at all.
 
The one specific thing I have an issue with is displaying the list items. After the cards are drawn the console reads out what number the cards are (1-13) and what the sum of the cards are. My main issue is figuring out how to make the function scale to include all cards drawn.

When the player chooses to draw another card it would add the new card3 to the WriteLine statement. So it should be something like WriteLine(“Your cards are “ + card[0] + “” + card [1] + “” + card[2] + “” + ( card[0] + card[1] + card[2] ));

I’m thinking I’m gonna have to use some kind of statement with a ++ value and a variable that changes each time drawCard(); is called. But I’m not sure what function to use or how to lay it out
 
Last edited:
The one specific thing I have an issue with is displaying the list items.
I don’t understand how I can make it so after you have card1 and card2 read it will read card3, card4,.... depending on however many cards there are
How exactly are those the same thing? Displaying and reading are two different things. Maybe it's (past) time that you showed us some relevant code. Your description is vague and all over the place.

As general advice, you can use a List<T> to store multiple items and you can Add and Remove as required, then you can loop over the list to get each item in turn and do whatever with it, e.g. display it. I can't tell whether that is specifically applicable to your situation or not because I don't really know what your situation is.
 
Show the code for how you are adding the cards, and separately, how you are showing the cards. We can make an evaluation of what you have done and whether or not something needs changing once we see what you have done.
 
So this is the code for drawing and displaying the cards, The problem I have here (Line 31) Is that every time a new card is drawn after the first two id have to program each card[2], card[3],.... and Im trying to see If I can automate the process so the player can essentially have an infinite number of cards without me having to type out infinite lines of code. I hope that made sense

C#:
static void dealPlayer()
        {
            int[] card = new int[6];

            Console.WriteLine("Dealing...");
            //Two new random cards assigned to card1, card2
            Random random1 = new Random();
            card[0] = random1.Next(1, 13);
            Random random2 = new Random();
            card[1] = random2.Next(1, 13);

            //If card drawn is ace player has choice to use it as 1 or 11
            if (card[0] == 1)
            {
                Console.WriteLine("You got an ace. Your other card is a " + card[1]);
                Console.Write("Ace = 1 or 11? ");
                card[0] = int.Parse(Console.ReadLine());
            }else if (card[1] == 1)
            {
                Console.WriteLine("You got an ace. Your other card is a " + card[0]);
                Console.Write("Ace = 1 or 11? ");
                card[1] = int.Parse(Console.ReadLine());
            }

            //this displays the player's current hand
            Console.WriteLine("Hand: " + card[0] + ", " + card[1] + " (" + (card[0] + card[1]) + ")");

            Console.Write("\nWould you like to hit (h) or stand (s): ");
            string play = Console.ReadLine();

            if (play == "h" || play == "H")
            {
                //player chose hit, a new random card is drawn and assisgned
                Console.WriteLine("Hit");
                card[2] = cardShuffle();
                //new card is read to player
                Console.WriteLine("Hand: " + card[0] + ", " + card[1] + ", " + card[2] + " (" + (card[0] + card[1] + card[2]) + ")")
            }
            else if (play == "s" || play == "S")
            {
                Console.WriteLine("Stand");
                playerStand();
            }else
            {
                Console.WriteLine("No input selected, Redrawing...");
                dealPlayer();
            }

        }

here is the code for how a new card is chosen

C#:
static int cardShuffle()
        {
            int randomCard;

            Random random = new Random();
            randomCard = random.Next(1, 14);

            return randomCard;
        }
 
Apart from anything else, you should not be creating multiple Random objects like that. The idea is that create one and only one Random object and then call Next on that object each time you need a random number. What you're doing is like buying a new hammer each time you want to hit a nail. This:
C#:
Random random1 = new Random();
card[0] = random1.Next(1, 13);
Random random2 = new Random();
card[1] = random2.Next(1, 13);
is very wrong. That will often, if not almost always, generate two identical values. Those Random objects are created with an implicit seed based on the system clock and they will be created so quickly that they will often use the same seed and so produce the same sequence of numbers. If you only take the first number in those two sequences then they will both be the same. The idea is that you call Next twice on the same object to get the first two values in the one sequence, then keep calling Next on that same object to get subsequent values in the same sequence.
 
Apart from anything else, you should not be creating multiple Random objects like that. The idea is that create one and only one Random object and then call Next on that object each time you need a random number. What you're doing is like buying a new hammer each time you want to hit a nail. This:
C#:
Random random1 = new Random();
card[0] = random1.Next(1, 13);
Random random2 = new Random();
card[1] = random2.Next(1, 13);
is very wrong. That will often, if not almost always, generate two identical values. Those Random objects are created with an implicit seed based on the system clock and they will be created so quickly that they will often use the same seed and so produce the same sequence of numbers. If you only take the first number in those two sequences then they will both be the same. The idea is that you call Next twice on the same object to get the first two values in the one sequence, then keep calling Next on that same object to get subsequent values in the same sequence.

Okay I see that. So instead should I use the cardShuffle(); method that I created and call to it twice?
C#:
card[0] = cardShuffle();
card[1] = cardShuffle();
C#:
static int cardShuffle()
        {
            int randomCard;

            Random random = new Random();
            randomCard = random.Next(1, 14);

            return randomCard;
        }
 
That's still no better because you're creating a new Random object in that method, so calling the method twice means creating two instances in quick succession. You should do what I said and create one and only one Random object and use that every time you want a random number.

You should also keep in mind that, as it stands, your code does nothing to prevent duplicates. If you're talking about cards then an item would generally only be able to be selected once. If you want to do this like a real deck of cards then you would create a list containing all items, shuffle it once, then repeatedly select the first item and remove it from the list. The other alternative is to generate a random number based on the size of the list and remove the item at that index. That means that the max limit that you specify when calling Next will decrement each time.
 
Here is an example of the second option. You can simply copy this code into a new Console Application project and run it to see the result.
C#:
using System;
using System.Collections.Generic;


namespace ConsoleApp1
{
    class Program
    {
        static Random rng = new Random();

        static void Main(string[] args)
        {
            var deck = GetFullDeck();

            var hand1 = new List<Card>();
            var hand2 = new List<Card>();

            // Deal two hands of five cards.
            Deal(5, deck, hand1, hand2);

            Console.WriteLine("Player 1 is holding the following hand:");

            foreach (var card in hand1)
            {
                Console.WriteLine(card.ToString());
            }

            Console.WriteLine();
            Console.WriteLine("Player 2 is holding the following hand:");

            foreach (var card in hand2)
            {
                Console.WriteLine(card.ToString());
            }

            Console.ReadLine();
        }

        static List<Card> GetFullDeck()
        {
            var deck = new List<Card>();

            // Populate the deck with every possible card.
            foreach (Face face in Enum.GetValues(typeof(Face)))
            {
                foreach (Suit suit in Enum.GetValues(typeof(Suit)))
                {
                    deck.Add(new Card(face, suit));
                }
            }

            return deck;
        }

        static void Deal(int cardCount, List<Card> deck, params List<Card>[] hands)
        {
            for (int i = 0; i < cardCount; i++)
            {
                // Deal one card to each hand at a time.
                foreach (var hand in hands)
                {
                    // Select a card from the deck at random.
                    var index = rng.Next(0, deck.Count);
                    var card = deck[index];

                    // Remove the card from the deck and add it to the current hand.
                    deck.Remove(card);
                    hand.Add(card);
                }
            }
        }
    }

    enum Face
    {
        Ace = 1,
        Two,
        Three,
        Four,
        Five,
        Six,
        Seven,
        Eight,
        Nine,
        Ten,
        Jack,
        Queen,
        King
    }

    enum Suit
    {
        Hearts,
        Clubs,
        Diamonds,
        Spades
    }

    class Card
    {
        public Face Face { get; }
        public Suit Suit { get; }

        public Card(Face face, Suit suit)
        {
            this.Face = face;
            this.Suit = suit;
        }

        public override string ToString()
        {
            return $"{Face} of {Suit}";
        }
    }
}
 
Here is that code modified slightly to implement the first option. Note that the deck is shuffled when it is created and then dealing is done simply by taking the first card each time. The vast majority of the code is unchanged though.
C#:
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static Random rng = new Random();

        static void Main(string[] args)
        {
            var deck = GetFullDeck();

            var hand1 = new List<Card>();
            var hand2 = new List<Card>();

            // Deal two hands of five cards.
            Deal(5, deck, hand1, hand2);

            Console.WriteLine("Player 1 is holding the following hand:");

            foreach (var card in hand1)
            {
                Console.WriteLine(card.ToString());
            }

            Console.WriteLine();
            Console.WriteLine("Player 2 is holding the following hand:");

            foreach (var card in hand2)
            {
                Console.WriteLine(card.ToString());
            }

            Console.ReadLine();
        }

        static List<Card> GetFullDeck()
        {
            var deck = new List<Card>();

            // Populate the deck with every possible card.
            foreach (Face face in Enum.GetValues(typeof(Face)))
            {
                foreach (Suit suit in Enum.GetValues(typeof(Suit)))
                {
                    deck.Add(new Card(face, suit));
                }
            }

            // Shuffle the deck.
            deck = deck.OrderBy(c => rng.NextDouble()).ToList();

            return deck;
        }

        static void Deal(int cardCount, List<Card> deck, params List<Card>[] hands)
        {
            for (int i = 0; i < cardCount; i++)
            {
                // Deal one card to each hand at a time.
                foreach (var hand in hands)
                {
                    // Remove the first card from the deck and add it to the current hand.
                    hand.Add(deck[0]);
                    deck.RemoveAt(0);
                }
            }
        }
    }

    enum Face
    {
        Ace = 1,
        Two,
        Three,
        Four,
        Five,
        Six,
        Seven,
        Eight,
        Nine,
        Ten,
        Jack,
        Queen,
        King
    }

    enum Suit
    {
        Hearts,
        Clubs,
        Diamonds,
        Spades
    }

    class Card
    {
        public Face Face { get; }
        public Suit Suit { get; }

        public Card(Face face, Suit suit)
        {
            this.Face = face;
            this.Suit = suit;
        }

        public override string ToString()
        {
            return $"{Face} of {Suit}";
        }
    }
}
 
Back
Top Bottom