0

I'm trying to develop a card game, where user clicks a button and automatically displays 5 cards. Anyways, right now I'm doing it as a console application, where 5 characters from two-Ace are display and 5 randomly card suits are display. But I can't figure out how to prevent a repetition of a card with a same value+suit. Can anyone please help me. Here is my code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace ConsoleApplication1
{
 class Program
 {
    static void Main(string[] args)
    {

        Array values = Enum.GetValues(typeof(CardValue));
        Array symbols = Enum.GetValues(typeof(CardSuit));
        Random random = new Random();
        Random randomsymbol = new Random();
        ArrayList mySymbols = new ArrayList();
        ArrayList myAl = new ArrayList();

        for (int i = 0; i < 5; i++)
        {
            CardValue randomBar = (CardValue)values.GetValue(random.Next(values.Length));
            myAl.Add(randomBar);} 
            for (int j = 0; j < 5; j++)
            {
               CardSuit randomsign = (CardSuit)symbols.GetValue(randomsymbol.Next(symbols.Length)); 
               mySymbols.Add(randomsign);
           }
            Console.WriteLine("Values:");
            PrintValues(myAl);
            Console.WriteLine();
            PrintSigns(mySymbols);


            Console.In.ReadLine();


    }
    enum CardValue { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace };
    enum CardSuit { Hearts, Clubs, Diamonds, Spades };


    public static void PrintValues(IEnumerable mylist)
    {
        foreach (Object obj in mylist) 
            Console.Write("      {0}", obj);

    }

    public static void PrintSigns(IEnumerable mySigns)
    {
        foreach (Object obj1 in mySigns)
            Console.Write("    {0}", obj1);

    }

  }
}
Dan J
  • 16,319
  • 7
  • 50
  • 82
Edward
  • 89
  • 1
  • 1
  • 6
  • Does the Value have to be in a separate enum that the suit? – MyKuLLSKI Feb 02 '12 at 21:19
  • What have you tried so far? Clearly you must keep track of which cards you've generated somehow; the code above shows no attempt to do so. – Dan J Feb 02 '12 at 21:19
  • 1
    Also, an observation about `Random`: the pattern of pseudorandom numbers produced by an instance of that class is determined when it's instantiated (I believe). Creating two instances in rapid succession means successive calls to `random.Next()` and `randomSymbol.Next()` will produce very similar values; if the selection of value and of suit should be unassociated, just declare a single instance of `Random` and use it throughout your program. – Dan J Feb 02 '12 at 21:20
  • 3
    A natural outcome of random selection is that the same value can be randomly generated multiple times. If a value, once consumed, is no longer eligible, then you need a different approach. Consider a Fisher Yates shuffle of the cards, just like a deck is shuffled. Then you merely select from the top of the deck. – Anthony Pegram Feb 02 '12 at 21:24

6 Answers6

4

In your case draw the next random card from the set of available cards. If you draw a Queen of Hearts, remove that card from the available cards (the deck) and pick a random card from the remaining cards.

This means your current approach of randomly picking a value and a suit is not suitable. Instead you could e.g. shuffle the array once in the beginning and pick the first 5 cards (the analogy to how real people play cards is striking here). Each entry in the array would have to uniquely identify a card so it would be a valid {Value, Suit} combination.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
3
  1. Don't use two instances of Random like that. The seed is determined when you create the object, so when you create two in succession like that they will probably return the same values for each call to Next().
  2. To answer your question, you simply need to save your results. When creating a random number save it in a List or some other type of collection and check to see if it exists there. If it does not, then save it and use it. If it does, do not use it and generate yet another random number until myGeneratedNums.Contains(randomNum) returns false.

There are more sophisticated ways to handle this, but seeing as you're a beginner this should do. If you would like to investigate alternatives then I suggest following up with Anthony Pegram's suggestion in the comments.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • I been trying to save this results but I can't come up with an answer, can you give me a start. And yes I'm a beginner, so once I get this project to work then I can actually implement Anthony's suggestion. – Edward Feb 04 '12 at 00:29
3

Spontaneously Id Create a struct for your cards along the line of:

struct Card
{
    CardValue value;
    CardSuit suit;
}

Id then create a list that would represent your deck and fill this list with the cards that youd normally see in a deck. i.e.

List<Card> deck = new List<Card>();
deck.Add(new Card(){value = One, suit = Hearts})
deck.Add(new Card(){value = Two, suit = Hearts})
.....

Then randomize your results from that making sure to remove the cards from the list as they're picked. Filling the deck could def be made smoother by introducing some loop, but this should show the idea.

Henrik Sonesson
  • 79
  • 1
  • 11
1

I would suggest the following as things that will help you toward your goal and a good design in general:

  1. Define a class (or better yet, immutable struct) to represent "Card" (this will have suit and rank enums)
  2. Define a way of uniquely identifying a card object.
  3. When you generate a random card, put it into some kind of data structure and, before displaying the card to the user, check to make sure it hasn't already been shown (i.e. by querying the unique identifier that you've defined)

That should give you a running start, anyway.

Erik Dietrich
  • 6,080
  • 6
  • 26
  • 37
1

Use 1 container instead of 2. Populate it with the union of the enums (nested for loop would do it), so you have 1 value for each card (I'd store this in a Card struct/class). Then, select randomly from this list. Replace with null once a card is drawn (presumably added to another container) and if you hit a null, re-draw.

Kendrick
  • 3,747
  • 1
  • 23
  • 41
0

If you have to use an enum do it this way:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        enum Cards
        {
            TwoOFHearts,
            TwoOFClubs,
            TwoOFDiamonds,
            TwoOFSpades,

            ThreeOFHearts,
            ThreeOFClubs,
            ThreeOFDiamonds,
            ThreeOFSpades,

            FourOFHearts,
            FourOFClubs,
            FourFDiamonds,
            FourOFSpades,

            FiveOFHearts,
            FiveOFClubs,
            FiveOFDiamonds,
            FiveOFSpades,

            SixOFHearts,
            SixOFClubs,
            SixOFDiamonds,
            SixOFSpades,

            SevenOFHearts,
            SevenOFClubs,
            SevenOFDiamonds,
            SevenOFSpades,

            EightOFHearts,
            EightOFClubs,
            EightOFDiamonds,
            EightOFSpades,

            NineOFHearts,
            NineOFClubs,
            NineOFDiamonds,
            NineOFSpades,

            TenOFHearts,
            TenOFClubs,
            TenOFDiamonds,
            TenOFSpades,

            JackOFHearts,
            JackOFClubs,
            JackOFDiamonds,
            JackOFSpades,

            QueenOFHearts,
            QueenOFClubs,
            QueenOFDiamonds,
            QueenOFSpades,

            KingOFHearts,
            KingOFClubs,
            KingOFDiamonds,
            KingOFSpades,

            AceOFHearts,
            AceOFClubs,
            AceOFDiamonds,
            AceOFSpades,
    }

    Random Random = new Random();
    Cards[] CardList;
    Regex Rexex = new Regex("OF");

    static void Main(string[] args)
    {
        CardList = (Cards[])Enum.GetValues(typeof(Cards));
        ShuffleCards();
        PrintCards(5);
    }

    private static void ShuffleCards()
    {
        for (int i = CardList.Length - 1; i > 0; i--)
        {
            int n = Random.Next(i + 1);
            Cards card = CardList[i];
            CardList[i] = CardList[n];
            CardList[n] = card;
        }
    }

    private static void PrintCards(int count)
    {
        for (int i = 0; i < count; i++)
        {
            string[] card = Rexex.Split(CardList[i].ToString());
            Console.WriteLine(string.Concat("Card ", i.ToString(), " - Value:", card[0], " Suit: ", card[1]));
        }
    }
  }

}

MyKuLLSKI
  • 5,285
  • 3
  • 20
  • 39