-2

This is my first time using C#. I have to convert an old project from Java. The old project works, but when I attempted to convert it, something went wrong? The Card class sets the default card to the Ace of Spades, but it is displaying Ace of Clubs. Ace and Clubs are each the first listed of the enums so I guess it is not using the default?

Since it is displaying the same card I thought it would be something wrong with my shuffle method..but I am unsure at this point. There is a Card, Deck, and Hand class. Then Enums for Suit and Face.

UPDATE: I believe the error is in the method directly below? I need to figure out how to use the 'n' in c#. It is needed in a different class.

In Java I had it as:

public Card(int n) 
{
    face = Face.values()[n % 13];
    suit = Suit.values()[n % 4];
} //end Card (int n) method

c#:

    public Card(int n) //??
    {
      var face = (Face) 13;
      var suit = (Suit) 4;
    }

The code above is in the Card class? I know that is not too helpful, but the only other way it to post ALL of the code here. //Some of the Deck class

 public void Shuffle() 
    {
        Random ran = new Random();
        for (int nextCard = 0; nextCard < deck.Length; nextCard++)
        {
            Card hold = deck[nextCard];
            int random = ran.Next(deck.Length);
            deck[nextCard] = deck[random];
            deck[random] = hold;
        }
    }

  public Card DealACard()
    {
        if (nextCard > 51)
        {
            return null;
        }
        return deck[nextCard++];
    }

   public Hand DealAHand(int handSize)        
    {
        Hand hand = new Hand(handSize);
        for (int i = 0; i < handSize; i++)
        {
            hand.AddCard(DealACard());
        }
        return hand;
    }

//Some of the Hand Class

    public void AddCard(Card card)
    {
       hand[cardsInHand] = card;
       cardsInHand++;
    }


    public override string ToString() 
    {
        String handToString = ""; //string to hold display format
        //for loop to display each card in a hand
        for (int n = 0; n < cardsInHand; n++)
        {
            handToString += hand[n].ToString() + "\n";
        }
        return handToString;
    }

// Driver Class

        Deck deck1 = new Deck();
        int cardsToGet = 53;

        do
        {
            Console.Write("How many cards are in one hand? ");
            int handSize = Convert.ToInt32(Console.ReadLine());
           // int handSize = Console.Read();

            Console.Write("How many players are playing? ");
            int players = Convert.ToInt32(Console.ReadLine());

            cardsToGet = handSize * players;

            if (cardsToGet < 53) // if to shuffle deck and display players' hands
            {
                deck1.Shuffle();

                for (int i = 0; i < players; i++) // displays each players hand
                {
                    Console.WriteLine("\nPlayer " + (i + 1) + ":");
                    Console.WriteLine(deck1.DealAHand(handSize));
                }

            }
            else
            {
                Console.WriteLine("\nThere are not enough cards in the deck to deal " + players + " hands of " + handSize + " cards. Try again.\n");
            } 
        }
        while (cardsToGet > 52);

It is suppose to ask for a number of cards per hand and a number of players then displays a hand for each player without duplicating cards. Currently, it fills every players hand with Ace of Clubs. There are no errors showing.

T.J.
  • 3
  • 2
  • 6
    The best course would be for you to single-step through the program and debug it yourself. VS has excellent debugging support that allows views into all your data. – Bruce Sep 09 '19 at 00:51

2 Answers2

-1

Now that you've updated your question, this is answerable. The mistake is in your Card constructor, which no matter the value of n that you pass in, creates every card with the Face with value 13 and the Suit with value 4. You have the right method for turning an int into a Face or Suit enum (just cast it), so you just need to do the modulo operation like your Java version did:

public Card(int n)
{
  var face = (Face) n % 13;
  var suit = (Suit) n % 4;
}

Well, almost. The var keyword in C# just creates a local variable that's not visible outside the scope it's declared in: in this case, the constructor. What you meant to do is assign values to instance properties of your Card class. You haven't shown us what those properties are named, but I'm going to assume they're named Face and Suit (with initial uppercase as is C# naming convention); rename as appropriate:

public Card(int n)
{
  this.Face = (Face) n % 13;
  this.Suit = (Suit) n % 4;
}

And now your cards should all be different, rather than all being the ace of clubs.

rmunn
  • 34,942
  • 10
  • 74
  • 105
-1

Hello TJ and welcome to S/O, coming from other languages can be a learning curve. Same as if I switched to Java. I quickly threw this together to introduce working with lists and classes within C#. Not perfect, but does what you are looking to get at. Hope it helps. I originally wrote this with C# via a WPF application vs Console app, but the core is all the same (only thing that would be different is the "MessageBox.Show()" that shows each hand vs the Console output which I also included.

I am notorious for commenting through my code and hope this all (or most of it) makes sense as you dive into C#...

I'm starting with enums for the card faces and suits.

public enum CardFace
{
    Two = 0,
    Three = 1,
    Four = 2,
    Five = 3,
    Six = 4,
    Seven = 5,
    Eight = 6,
    Nine = 7,
    Ten = 8,
    Jack = 9,
    Queen = 10,
    King = 11,
    Ace = 12
}

public enum CardSuit
{
    Hearts = 0,
    Clubs = 1,
    Diamonds = 2,
    Spades = 3
}

Next, a class to represent a single card

public class SingleCard
{
    public CardFace Face { get; set; }
    public CardSuit Suit { get; set; }
    // place-holder for randomizing cards
    public int RndNumber { get; set; }
    // return the name of the card based on it's parts as single string
    public string NameOfCard { get { return $"{Face} of {Suit}"; } }
}

Now, the class for building the initial deck of cards, shuffling, dealing and displaying the cards (of the entire deck, or of the individual hands)

public class DeckOfCards
{
    public List<SingleCard> SingleDeck { get; private set; } = new List<SingleCard>();

    public List<SingleCard> ShuffledDeck { get; private set; }

    // create a single random generator ONCE and leave active.  This to help prevent
    // recreating every time you need to shuffle and getting the same sequences.
    // make static in case you want multiple decks, they keep using the same randomizing object
    private static Random rndGen = new Random();

    public DeckOfCards()
    {
        // build the deck of cards once...
        // Start going through each suit
        foreach (CardSuit s in typeof(CardSuit).GetEnumValues())
        {
            // now go through each card within each suit
            foreach (CardFace f in typeof(CardFace).GetEnumValues())
                // Now, add a card to the deck of the suite / face card
                SingleDeck.Add(new SingleCard { Face = f, Suit = s });
        }

        // so now you have a master list of all cards in your deck declared once...
    }

    public void ShuffleDeck()
    {
        // to shuffle a deck, assign the next random number sequentially to the deck.
        // don't just do random of 52 cards, but other to prevent duplicate numbers
        // from possibly coming in
        foreach (var oneCard in SingleDeck)
            oneCard.RndNumber = rndGen.Next(3901);  // any number could be used...

        // great, now every card has a randomized number assigned.
        // return the list sorted by that random number...
        ShuffledDeck = SingleDeck.OrderBy( o => o.RndNumber).ToList();
    }

    public void DisplayTheCards( List<SingleCard> theCards )
    {
        // show the deck of cards, or a single person's hand of cards
        var sb = new StringBuilder();
        foreach (var c in theCards)
            sb = sb.AppendLine( c.NameOfCard );

        MessageBox.Show(sb.ToString());
    }

    public void ConsoleDisplayTheCards(List<SingleCard> theCards)
    {
        // show the deck of cards, or a single person's hand of cards
        foreach (var c in theCards)
            Console.WriteLine(c.NameOfCard);
    }


    public List<List<SingleCard>> DealHands( int Players, int CardsPerHand )
    {
        // create a list of how many hands to be dealt...
        // each player hand will consist of a list of cards
        var Hands = new List<List<SingleCard>>(Players);

        // prepare every players hand before dealing cards
        for (var curPlayer = 0; curPlayer < Players; curPlayer++)
            // each player gets their own list of cards
            Hands.Add( new List<SingleCard>());


        // prepare card sequence to deal
        var nextCard = 0;
        // loop for as many cards per hand
        for (var oneCard = 0; oneCard < CardsPerHand; oneCard++)
        {
            // loop every player gets a card at a time vs one player gets all, then next player
            for (var curPlayer = 0; curPlayer < Players; curPlayer++)
                // add whatever the next card is to each individual's hand
                Hands[curPlayer].Add(ShuffledDeck[nextCard++]);
        }

        return Hands;
    }



}

I did not include the input of getting how many players, how many cards as you already had that. I also did not validate total cards to be dealt as you had that too. HTH

DRapp
  • 47,638
  • 12
  • 72
  • 142