使用C#

时间:2018-10-01 16:04:44

标签: c# sorting playing-cards array-algorithms

我正在尝试创建一个控制台程序来模拟一副纸牌,用户应该能够;

  • 随机选择一些卡
  • 随机播放甲板
  • 将卡座恢复到原始状态

我正在努力寻找一种方法,可以将牌组恢复到起点

当我尝试再次使用初始化数组时; string [] Deck = {x,x,x}似乎也不喜欢

任何指针将不胜感激!下面的代码;

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

namespace CardArranger
{  
    class Program
    {

        static void Main(string[] args)
        {

            string[] Deck =
            {
                "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "DJ", "DQ", "DK",
                "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9", "H10", "HJ", "HQ", "HK",
                "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "CJ", "CQ", "CK",
                "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "SJ", "SQ", "SK",
            };

            Random r1 = new Random();       

            while (true)
            {
                //display number of random cards
                Console.WriteLine("write shuffle to shuffle or 'sort' to organise the deck again");
                string Uinput = Console.ReadLine();

                bool isCount = int.TryParse(Uinput, out int noCards);

                if (isCount)
                {
                    for (int i = 0; i < noCards; i++)
                    {
                        Console.WriteLine(Deck[r1.Next(0, 52)]);
                    }
                }
                else
                {
                    if (Uinput.Equals("shuffle"))
                    {
                        Shuffle(ref Deck, r1);
                        Console.WriteLine("Shuffled Deck");
                        for (int i = 0; i < Deck.Length; i++)
                        {
                            Console.WriteLine(Deck[i] + " , ");                        
                        }
                        Console.WriteLine();
                        Console.WriteLine("---");
                    }
                    else if (Uinput.Equals("sort"))
                    {
                        //Implement your sort method here
                        Console.WriteLine("Sorted Deck");
                        for (int i = 0; i < Deck.Length; i++)
                        {
                            Console.WriteLine(Deck[i] + " , ");
                        }
                        Console.WriteLine();
                        Console.WriteLine("---");
                    }
                    else
                    {                    
                        Console.WriteLine("Unrecognised Command");
                    }

                }
                Console.WriteLine("Press Any Key to Repeat");
                Console.ReadKey();
            }

        }

        //Fisher-Yates Shuffle
        static void Shuffle(ref string[] OriginalArray, Random Rnd)
        {            
            for (int i = 0; i < OriginalArray.Length; i++)
            {
                string tmp = OriginalArray[i];
                int r = Rnd.Next(0, OriginalArray.Length);
                OriginalArray[i] = OriginalArray[r];
                OriginalArray[r] = tmp;
            }
        }



        static void Sort(ref string[] ShuffledArray)
        {
           // sort the deck back in order
        }
    }
}

4 个答案:

答案 0 :(得分:1)

仅将数组分配给原始副本可能是处理此问题的最简单方法。话虽如此,使用Array.sort()和自定义比较器功能对它进行排序很有用,因为您将来可能希望保持卡的状态(见下文):

static void Sort(ref string[] ShuffledArray)
{
    Array.Sort(ShuffledArray, CardComparator);
}

public static int CardComparator(string a, string b)
{
    Dictionary<string, int> rank = new Dictionary<string, int>()
    {
        {"A", 0}, {"1", 1}, {"2", 2}, {"3", 3}, {"4", 4}, 
        {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {"9", 9}, 
        {"10", 10}, {"J", 11}, {"Q", 12}, {"K", 13}, 
    };
    int cmp = "HCS".IndexOf(a[0]) - "HCS".IndexOf(b[0]);

    if (cmp == 0) {
        return rank[a.Substring(1)] - rank[b.Substring(1)];
    }

    return cmp;
}

Try it!

这应该说明您的程序可能遇到的一些设计问题。问题是排序需要解析字符串以确定每个卡的等级和适合度。这对于编写游戏逻辑是有问题的。您将花费大量精力进行解析。

要解决此问题,我建议编写一个结构或类来封装卡。成员属性可以是RankSuit以及相应的getter和setter(如适用)。从长远来看,此重构将获得回报(!)。 Deck类也很合适,它包含Card s的成员数组以及SortShuffle函数。

此外,您的洗牌代码似乎有偏差;检查pseudocode on Wikipedia并尝试重新实现它,直到获得在大型数据集上运行它的无偏排序。这是在数据集上运行排序数十万次并保留元素结束位置的计数的示例分布(无偏排序将提供均匀分布):

111258
104215
99394
96347
95288
95949
98992
104344
111426

答案 1 :(得分:0)

Deck函数中像这样初始化Sort

static void Sort( ref string[] ShuffledArray ) {
    // sort the deck back in order
    string[] Deck =
    {
        "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "DJ", "DQ", "DK",
        "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9", "H10", "HJ", "HQ", "HK",
        "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "CJ", "CQ", "CK",
        "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "SJ", "SQ", "SK",
    };


    ShuffledArray = (string[])Deck.Clone();

}

在您的Main中:

string[] Deck = new string[ 52 ];

Sort( ref Deck );

Random r1 = new Random();

.....
.....

答案 2 :(得分:0)

尝试在拖曳时跟踪掉期头寸,通过向后迭代来撤消;像这样:

public sealed class ShuffleBag<T> : IEnumerable<T>, IEnumerator<T>
{
    private readonly Random m_randomNumberGenerator;
    private readonly int[] m_swaps;
    private readonly T[] m_values;

    private int m_currentIndex;
    private T m_currentValue;

    object IEnumerator.Current => Current;
    public T Current => m_currentValue;

    public ShuffleBag(Random randomNumberGenerator, T[] values) {
        if (randomNumberGenerator == null) {
            throw new ArgumentNullException(message: "random number generator cannot be null", paramName: nameof(randomNumberGenerator));
        }

        if (values == null) {
            throw new ArgumentNullException(message: "array of values cannot be null", paramName: nameof(values));
        }

        m_currentIndex = 0;
        m_currentValue = default(T);
        m_randomNumberGenerator = randomNumberGenerator;
        m_swaps = new int[values.Length];
        m_values = values;
    }

    public void Dispose() { }
    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }
    public IEnumerator<T> GetEnumerator() {
        while (MoveNext()) {
            yield return Current;
        }
    }
    public bool MoveNext() {
        if (m_currentIndex < m_values.Length) {
            var randomIndex = m_randomNumberGenerator.Next(m_currentIndex, m_values.Length);

            m_currentValue = m_values[randomIndex];
            m_swaps[m_currentIndex] = randomIndex;
            m_values[randomIndex] = m_values[m_currentIndex];
            m_values[m_currentIndex] = m_currentValue;

            m_currentIndex++;

            return true;
        }
        else {
            return false;
        }
    }
    public void Reset(bool unshuffle) {
        if (unshuffle) {
            var count = m_values.Length;

            while (0 < count--) {
                var tempValue = m_values[m_swaps[count]];

                m_values[m_swaps[count]] = m_values[count];
                m_values[count] = tempValue;
            }
        }
        else {
            var count = m_swaps.Length;

            while (0 < count--) {
                m_swaps[count] = 0;
            }
        }

        m_currentIndex = 0;
        m_currentValue = default(T);
    }
    public void Reset() {
        Reset(unshuffle: true);
    }
}

用法:

var shuffleBag = new ShuffleBag<string>(new Random(42), new[] { "a", "b", "c", "d", "e" });

foreach (var item in shuffleBag) {
    Console.WriteLine(item);
}

shuffleBag.Reset();

答案 3 :(得分:0)

如果您坚持要对洗过的甲板进行改组,那么这是最简单的方法:

string[] deck =
{
    "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "DJ", "DQ", "DK",
    "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9", "H10", "HJ", "HQ", "HK",
    "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "CJ", "CQ", "CK",
    "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "SJ", "SQ", "SK",
};

var r = new Random();

string[] shuffled = deck.OrderBy(x => r.Next()).ToArray();

string[] unshuffled = shuffled.OrderBy(x => Array.IndexOf(deck, x)).ToArray();