当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - ToArray() within a different method

问题描述:

I have an array named mainDeck which holds the values for a deck of playing cards. What I have to do next is distribute the cards within that array to two separate arrays named playerDeck and computerDeck and each deck must contain a unique card.

The problem I have is distributing the cards with a unique value - 26 cards per deck. I have tried a few different approaches and the coding at the bottom in comments is the last remnant of what I was trying to do before I had to leave for class which isn't finished.

To note: My programming skills are limited to please explain your answer rather then just give a solution as that doesn't further my understanding.

static void Main(string[] args)

{

// 1 = Ace , 13 = King : 0 = Hearts, 1 = Diamonds, 2 = Clubs, 3 = Spades

int[] mainDeck = new int[52];

FillDeck(mainDeck);

int[] playerDeck = new int[26];

int[] computerDeck = new int[26];

// Check mainDeck elements

foreach (int number in mainDeck)

{

Console.WriteLine(number);

}

}

public static void FillDeck(int [] mainDeck)

{

int cardType = 1;

List<int> deck = new List<int>();

// Add cards to a list

for (int x = 0; x < 13; x++)

for(int y = 0; y < 4; y++)

{

deck.Add(cardType);

if (y == 3)

++cardType;

}

// Insert deck list into a new Array

int[] cards = deck.GetRange(0, 52).ToArray();

// Add cards array to mainDeck

for (int x = 0; x < 52; ++x)

{

mainDeck[x] = cards[x];

}

}

//public static void Distribute()

//{

// RandomNumber number = new RandomNumber();

// int value = number.RandomNum;

// List<int> playerCards = new List<int>();

// for (int x = 0; x < 2; ++x)

// {

// Console.WriteLine(number.RandomNum);

// }

//}

}

//class RandomNumber

//{

// private int randomNum;

// Random ranNumberGenerator;

// public RandomNumber()

// {

// ranNumberGenerator = new Random();

// }

// public int RandomNum

// {

// get

// {

// randomNum = ranNumberGenerator.Next(1, 26);

// return randomNum;

// }

// }

//}

网友答案:

If you're trying to distribute the cards randomly like you would in a typical card game here is an article on shuffling an array. - http://www.dotnetperls.com/shuffle - It should do what you want.

After you shuffle the mainDeck array you just loop through it alternately assigning cards to player and computer decks in the same manner you would deal cards in real life.

网友答案:

The common solution for a card game deck

  1. Create the deck with all available cards
  2. Shuffle the deck
  3. Get cards from the top

so the code :)

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

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

public class Card
{
  public Card(CardValue value, CardColor color)
  {
    Value = value;
    Color = color;
  }

  public readonly CardValue Value;
  public readonly CardColor Color;
}

public class Deck
{
  private Queue<Card> deckInternal;

  public Deck()
  {
    var deck = new List<Card>();
    for(int index = 0; index < 52; index++)
    {
      var cardValue = (CardValue)(index % 4) + 1;
      var cardColor = (CardColor)index / 4;
      dec.Add(new Card(cardValue, cardColor));
    }

    var rand = new Random();
    dec = dec
      .OrderBy(c => rand.Next(52))
      .ToList();

    deckInternal = new Queue<Card>(deck);
  }

  public Card GetCard()
  {
    return deckInternal.Dequeue();
  }
}

to get deck and split it you can do next

var deck = new Deck();

var player = new List<Card>();
var computer = new List<Card>();

for(int index = 0; index < 52; index++)
{
  if(index % 2 == 0)
  {
    player.Add(deck.GetCard());
  }
  else
  {
    computer.Add(deck.GetCard());
  }
}
网友答案:

You have two options for keeping the values unique within the deck here. You can either create a new class representing a card, which has properties for the Rank and Suit, or if you want to keep it simple (from a compiler standpoint, anyway) you can use the value to indicate both rank and suit, whereas you're using 1 through 13 to indicate rank only.

For the latter solution, you would want to use the numbers 0 through 12 to indicate Ace through King of Hearts, 13 through 25 to indicate Ace through King of Diamonds, and so on. To get the rank of any card you'd use card % 13 and to get the suit of the card you'd use card / 4.

I would prefer the former solution, though, and would create a class like this (you could also replace the int properties with Enums for even more readability):

public class Card
{
    public int Rank { get; set; }
    public int Suit { get; set; }
}

after that you could create a loop that runs until the main deck is empty and picks a random card from the main deck to put into the other two decks. In pseudo-code it might look like:

while (mainDeck has any elements)
    num = random number between 0 and elements in mainDeck - 1, inclusive
    deckToAddTo = alternate between playerDeck and computerDeck
    remove card num from mainDeck and insert into deckToAddTo
网友答案:

Give player the first 26 cards.

playerDeck = mainDeck.Take(26).ToArray();

Skip player's cards and get the next 26 cards.

computerDeck = mainDeck.Skip(26).Take(26).ToArray();
网友答案:
Random  rnd = new Random();
// you can Shuffle Array and Take random 26 items using Linq as below
int[] playerDeck = mainDeck.OrderBy(x => rnd.Next()).Take(26).ToArray();
// get rest of the items using Except linq method 
int[] computerDeck = mainDeck.Except(playerDeck).ToArray();
网友答案:

.......

There are quite a few ways to do this.....

It uses only single bytes for the values although you can operate on it with a int as per other implementations...

I wrote it just for you in 20 minutes... (With a few additions later on)

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

namespace CodeProjectHelpProject
{
    public class Deck
    {
        #region Nested Types

        //Exceptions
        public class DeckException : Exception { public DeckException(string message) : base(message) { } public DeckException(string message, Exception inner) : base(message, inner) { } }

        #region CardSuit

        //Enumeration of Suits a Card can Obtain, Allows the Developer to change the Card Order.
        public struct CardSuit
        {
            //Exceptions
            public class CardSuitException : DeckException { public CardSuitException(string message) : base(message) { } }

            #region Statics

            internal static byte Spade = 0;
            internal static byte Club = 1;
            internal static byte Heart = 2;
            internal static byte Diamond = 3;

            public static CardSuit Spades = new CardSuit(Spade);
            public static CardSuit Clubs = new CardSuit(Club);
            public static CardSuit Hearts = new CardSuit(Heart);
            public static CardSuit Diamonds = new CardSuit(Diamond);

            #endregion

            #region Properties

            public char Symbol
            {
                get
                {
                    switch (m_Suit)
                    {
                        case 0: return '♠';
                        case 1: return '♣';
                        case 2: return '♥';
                        case 3: return '♦';
                        default: return 'D';
                    }
                }
            }

            #endregion

            #region Fields

            internal byte m_Suit;

            #endregion

            #region Constructor

            public CardSuit(byte suit)
            {
                if (suit < Spade || suit > Diamond) throw new CardSuitException("Invalid Suit");
                m_Suit = suit;
            }

            #endregion

            #region CardSuit Overrides

            public override string ToString()
            {
                switch (m_Suit)
                {
                    case 0: return "Spades";
                    case 1: return "Clubs";
                    case 2: return "Hearts";
                    case 3: return "Diamonds";
                    default: return "Unknown";
                }
            }

            #endregion

            #region Operators

            public static bool operator >(CardSuit a, CardSuit b){ return a.m_Suit < b.m_Suit;}
            public static bool operator <(CardSuit a, CardSuit b){ return a.m_Suit > b.m_Suit;}

            public static bool operator >(CardSuit a, int b) { return a.m_Suit > b; }
            public static bool operator <(CardSuit a, int b) { return a.m_Suit < b; }

            public static implicit operator int(CardSuit a) { return a.m_Suit; }
            public static implicit operator CardSuit(int a) { return new CardSuit((byte)a); }

            #endregion
        }

        #endregion

        #region Card Structure
        public struct Card
        {
            //Exceptions
            public class CardException : DeckException { public CardException(string message) : base(message) { } }

            #region Constants

            const char CharJoker = default(char);

            const char AceValue = unchecked((char)1);

            const char JackValue = unchecked((char)11);

            const char QueenValue = unchecked((char)12);

            const char KingValue = unchecked((char)13);

            #endregion

            #region Properties

            public char Value { get; internal set; }

            public Deck.CardSuit Suit { get; internal set; }

            public byte Number { get { return (byte)Value; } }

            public char Symbol { get { return Name[0]; } }

            public string Name { get { return (Value <= 0 ? "Joker" : Value == AceValue ? "Ace" : Value == JackValue ? "Jack" : Value == QueenValue ? "Queen" : Value == KingValue ? "King" : Number.ToString()); } }

            #endregion

            #region Constructor

            public Card(char value, CardSuit suit)
                : this()
            {                
                Value = value;
                Suit = suit;
            }


            public Card(int value) : this(unchecked((char)Convert.ToInt32(value / 4)), (Deck.CardSuit)(value % 4)) { }

            public Card(int value, CardSuit suite) : this(unchecked((char)value), suite) { }

            public Card(byte value, CardSuit suite) : this((char)value, suite) { }

            #endregion

            #region Card Overrides

            public override string ToString()
            {
                return "Card, " + Name + " Of " + Suit + '(' + Suit.Symbol + ')' + " (" + Symbol + " - " + Number + ')' ;
            }

            public override bool Equals(object obj)
            {
                if (obj is Card)
                {
                    Card c = (Card)obj;
                    return c.Suit == Suit && c.Value == Value;
                }
                return base.Equals(obj);
            }

            public override int GetHashCode() { return Value.GetHashCode() ^ Suit.GetHashCode(); }

            #endregion

            #region Card Operators

            public static implicit operator Card(int c) { return new Card(c); }
            public static implicit operator int(Card c) { return c.GetHashCode(); }

            public static bool operator ==(Card a, Card b) { return a.GetHashCode() == b.GetHashCode(); }
            public static bool operator !=(Card a, Card b) { return !(a == b); }

            public static bool operator >(Card a, Card b) { return a.Value >= b.Value && a.Suit > b.Suit; }
            public static bool operator <(Card a, Card b) { return a.Value <= b.Value && a.Suit < b.Suit; }

            #endregion

        }

#endregion Card

        #endregion

        #region Deck Statics

        // Override the default order of suits here for other games, see below
        public static readonly Deck.CardSuit[] DefaultSuitOrder = new CardSuit[] { CardSuit.Spades, CardSuit.Clubs, CardSuit.Hearts, CardSuit.Diamonds };

        public static readonly Card[] Jokers = new Card[] { new Card(0), new Card(1), new Card(2), new Card(3) };

        public static bool HasAllCards(Deck d) { foreach (var c in Enumerable.Range(d.HasJokers ?  0 : 4, d.HasJokers ?  56 : 52)) if (!d.Cards.Contains(c)) return false; return true; }

        #endregion

        #region Deck Properties

        public readonly string Manufactuer = "v//";

        public List<Card> Cards { get; internal set; }

        public bool HasJokers { get; private set; }

        public bool Shuffled { get; private set; }

        public Card this[int index] { get { return Cards[index]; } private set { Cards[index] = value; } }

        public bool this[Card c] { get { return ContainsCard(c); } }

        public virtual bool IsLegalDeck { get { return HasJokers ? Cards.Count() == 56 : Cards.Count() == 52 && HasAllCards(); } }

        public CardSuit[] SuitOrder { get; private set; }

        public int MinValue { get; private set; }

        public int MaxValue { get; private set; }

        #endregion

        #region Constructor

        public Deck(bool usesJokers = false, bool shuffle = false, CardSuit[] suitOrder = null, int minValue = 1, int maxValue = 13)
        {
            try
            {
                MinValue = minValue;
                MaxValue = maxValue;
                if (null == suitOrder) SuitOrder = DefaultSuitOrder;
                else SuitOrder = suitOrder;
                Cards = new List<Card>();
                HasJokers = usesJokers;
                if (HasJokers) foreach (var c in Enumerable.Range(minValue - 1, MaxValue * SuitOrder.Count() + SuitOrder.Count())) { Card C = c; VerifyCard(C); Cards.Add(C); }
                else foreach (Deck.CardSuit s in SuitOrder) { foreach (char c in Enumerable.Range(MinValue, MaxValue)) { Card C = new Card(c, s); VerifyCard(C); Cards.Add(C); } }
                if (shuffle) Shuffle(Extensions.Random.Next(Cards.Count % 4), true);
                return;


            }
            catch(Exception e) { throw new DeckException(e.Message, e); }
        }        

        #endregion

        #region Deck Methods

        internal void VerifyCard(Card C)
        {
            if (!SuitOrder.Contains(C.Suit)) goto InvalidSuit; if (C.Value < MinValue || C.Value > MaxValue) goto InvalidValue;
            return;
        InvalidSuit:
            throw new CardSuit.CardSuitException("Invalid Suit");
        InvalidValue: //Not Yet Implemented
            throw new CardSuit.CardSuitException("Invalid Suit");
        }

        public void Shuffle(int times = 0, bool knuthAlgorithm = false)
        {
            if (knuthAlgorithm) this.Cards.ShuffleKnuth();
            else Extensions.Shuffle(this, times);
            Shuffled = true;
        }

        public List<Card> Take(int amount = 0, bool random = false)
        {
            var cards = (random ? (Cards.Skip(Extensions.Random.Next(0, Cards.Count() - amount))) : (Cards.Skip(Extensions.Random.Next(0, Cards.Count() - amount))).Take(amount).ToList());
            foreach (var c in cards) Cards.Remove(c);
            return cards.ToList();
        }

        public List<Card> TakeRandom(int amount = 0) { return Take(amount, true); }

        public virtual bool RemoveCard(Card c) { return Cards.Remove(c); }

        public virtual void RemoveCards(bool stopIfNotContained = false, params Card[] s) { foreach (Card c in s) if (!stopIfNotContained && !RemoveCard(c)) break; return; }

        public virtual bool ContainsCard(Card c) { return Cards.Contains(c); }        

        public virtual bool HasAllCards() { return Deck.HasAllCards(this); }

        #endregion

        #region Deck Overrides

        public override string ToString() { return "Deck, " + Cards.Count + " Remaining Cards"; }

        public override int GetHashCode() { return Cards.GetHashCode(); }

        public override bool Equals(object obj)
        {
            if (obj is Deck)
            {
                return ((Deck)obj).GetHashCode() == obj.GetHashCode();
            }
            return base.Equals(obj);
        }

        #endregion

        #region Deck Operators

        public static implicit operator int(Deck d) { return d.GetHashCode(); }

        public static bool operator ==(Deck a, Deck b) { return a.GetHashCode() == b.GetHashCode(); }
        public static bool operator !=(Deck a, Deck b) { return !(a == b); }

        public static Deck operator <<(Deck a, int b) { a.Shuffle(b); return a; }
        public static Deck operator >>(Deck a, int b) { a.Shuffle(b, true); return a; }

        public static List<Card> operator -(Deck d, int amount) { d.Take(amount, true); return d.Cards; }
        public static List<Card> operator +(Deck d, IEnumerable<int> cards) { foreach (int c in cards) d.Cards.Add(c); return d.Cards; }
        public static List<Card> operator +(Deck d, int card) { d.Cards.Add(card); return d.Cards; }
        public static List<Card> operator +(Deck d, IEnumerable<Card> cards) { d.Cards.AddRange(cards); return d.Cards; }

        public static Deck operator -(Deck a, Deck b) { a.Cards.ForEach(c => b.Cards.Remove(c)); return a; }
        public static Deck operator +(Deck a, Deck b) { a.Cards.AddRange(b.Cards); return a; }

        #endregion
    }
    public static class Extensions
    {
        //Cause random leaks
        public static readonly Random Random = new Random();

        /// <summary>
        /// Shuffles a List according to Knuth's Algorithm
        /// </summary>
        /// <param name="List">The List to shuffle</param>
        public static void ShuffleKnuth(this List<CodeProjectHelpProject.Deck.Card> List)
        {
            for (int i = 1, e = List.Count(); i < e; ++i)
            {
                int pos = Random.Next(i + 1);
                var x = List[i];
                List[i] = List[pos];
                List[pos] = x;
            }
        }        

        public static void Shuffle(this Deck d, int times = 0)
        {
            do
            {
                foreach (CodeProjectHelpProject.Deck.CardSuit s in d.SuitOrder)
                {
                    var cards = d.Cards.Where(c => c.Suit != s).ToList();
                    cards.ForEach(c =>
                    {
                        d.Cards.Remove(c);                                                
                        d.Cards.Insert(c.Value % 4, c);
                    });
                }
            } while (--times >= 0);
        }
    }
}

Each value can be overridden in a derived class such as BlackJackDeck or each class such as BlackJackCard... no more complicated than the others and just as if not more elegant and useful...

Cards and Decks have unique hash codes..

The only thing missing is to have a card tell you if it is part of a deck originally :P

You can even give other values you just have to be creative when you extend such as in situations like UnoDeck and UnoCard... you would pass Jokers[(0-3)] to the Card constructor and the overridden values would only apply in your Game...

It even allows you to change the Deck's SuitOrder so your came can have Suit Priority such as in Bridge vs Preferans.

Use it like so

        var d = new Deck();

        Deck.Card c = 0; //Joker Of Spades(0)
        c = 1; //Joker Of Clubs (0)
        c = 4; //Ace Of Spades (1)
        c = 52; //King Of Spades (13)

        d.Shuffle();
        d.Take(1);
        d.TakeRandom(1);
        d.Cards.Skip(10).Take(5);
分享给朋友:
您可能感兴趣的文章:
随机阅读: