使用Lookup或Dictionary来表示C#中的一手牌

时间:2013-09-10 21:38:44

标签: c# dictionary lookup

  

如果已经有类似的问题,我道歉。那里   有几个关于得分手的问题,但我不需要。

     

我正在进行的项目需要10张卡,需要报告   找到最好的5张牌("直#34;,"高牌","冲洗"   等等。)。幸运的是,卡片的实际手牌是无关紧要的,我只是   需要一个名字。

     

我已经解析并整理了所有卡并进行了测试   为所有可能的手设置。我现在需要的只是一个方便的   存储手的方式。我的疯狂方法如下,在伪代码中   术语:

     

我希望水平设置一个动态列表,我可以按照从最高到最低的顺序填充卡片的NUMBER值。对于   例如," Q J T 7 4 2 1"。 T是10.值的重复   忽略。接下来,我希望每个值都在下面   甲板中存在的每个值的套装列表。例如,   J将有一个子列表,其值为" D H"代表我有   杰克的钻石和杰克的心。

     

我相信这是处理这些卡片最优雅的方式,   因为大多数扑克牌手只处理价值观,这种方式我没有   比如担心连续的相同值的牌   测试。然后,处理西装的两个测试很容易   通过参考键下的值进行测试。

     

深吸一口气,几乎就在那里。

     

所以Lookup的实例看起来很完美!它有一个确切的"一个   多重价值的关键"我想要的结构。但是,它没有   允许我添加西装,因为我来到他们身边。我必须全部添加它们   一次或根本没有,因为列表在进入后是不可变的。

     

所以我要么

     
      
  1. 在我进行查询之前必须立即找到所有套装
  2.   
  3. 以某种方式将值添加到查找列表或
  4.   
  5. 使用别的东西。
  6.         

    关于这些的任何想法?

更新

TL; DR SPARKNOTES VERSION:如何在Lookup内的键中添加更多值?

* IMOPRTANT注意: *此程序的输出应该是一个包含最高手牌名称的字符串,例如"四种类型",&#34 ;两对"或者"高牌。"

我找到了一个解决方案(我很遗憾地丢失了链接并且无法再找到),他们建议使用新列表重新创建整个Lookup。它可能只是我,但我发现解决方案非常......丑陋...无论如何,我探索或测试的其他几个解决方案是:


<方法1

滚动并使用与每个值关联的套装填充另一个数组。基本上(这次实际伪代码&gt; _&gt;):

  1. 创建一个ArrayLists数组(数组1)
  2. 遍历排序的字符串数组&#34;&#34; (数组2)
  3. 每张卡片:
  4. 取字符串索引[1]处的字符(表示套装),并在从字符串索引[0]中提取的索引号处添加到数组1中的ArrayList。
  5. 这样我就可以获得我想要的相关套装的价值清单。西装列表是最小的引导大小,以后更容易迭代。通过一些额外的步骤,我甚至可以使伞阵列成为一个ArrayList,并按顺序使用卡值填充它,这样就没有间隙,也没有重复的数字。这将让我看到我想要的锯齿状阵列。要清楚,这不是家庭作业。然而,它来自我的室友过去完成的编码课项目,这就是为什么我有我的限制和要求。我问过的其他人告诉我SE在这个时候被这些家庭作业问题所困扰,所以我理解你的怀疑态度。这是一个个人项目,因为我想学习C#(我现在所知道的只是Java,我喜欢用C#方法传递参数指针的声音,而Java不这样做。)

    如果是等级,我会在那里结束,因为它有效。但我不太喜欢arraylists的arraylists,他们似乎对我来说很混乱。所以我想知道是否还有其他方法。


    <方法2

    我还考虑过简单地处理不可避免地出现的副本。例如,这是我对笔直的测试:

     for (int i = 0; i < 5; i++)
            {
                int counter = 0;
                for (int j = i; j < i + 4; j++)
                {
                    int secondCard = getValue(cardsArray[j + 1]);
                    int firstCard = getValue(cardsArray[j]);
                    if (secondCard == firstCard)
                    {
                        break;
                    }
                    if (secondCard == (firstCard + 1))
                    {
                        counter++;
                        if (counter == 4)
                        {
                            isStraight = true;
                            return "straight";
                        }
                    }
                }
            }
    

    此代码不起作用。它需要在某处或其他地方进行一些调整以完全工作,但我想在我尝试修复之前分析它是否值得。尽管如此,它还是可以准确地测试直线。另外还有一些注意事项:firstCard和secondCard是出于可读性和调试目的,并且isStraight就在那里,以便我在以后测试同花顺时不再重新发明轮子。

    这个嵌套循环将遍历所有牌直到第5张牌(因为你不能直接使用少于5张牌的十张分类牌),然后按照你的预期检查接下来的五张牌。如果在这次迭代中我遇到重复的条目,则意味着它与另一套服装的卡片相同,而我只是&#34;打破&#34;。由于这一个陈述应该发生的是现在我们已经将第二次迭代增加了一次以检查下一张卡而不是当前的卡。我们拥有的有序卡的数量将保持不变,以便列出像&#34; 1D 2D 3S 3H 4D 5C&#34;在找到直线时将跳过第二个3。尽管休息了,但我对这个解决方案的优雅感到非常满意,无论我是否有权利。

    这一切都可以追溯到使用一个简单的字符串数组(&#34; cards&#34;)的缺陷,这正是我的代码现在定制的。我讨厌修复问题,我宁愿避免它们。也许我会不必要地挑剔,但我一直在学习。


    <方法3

    我对一系列字符串的弱点的考虑使我看到了Dictionaries,它看起来很有吸引力。它可以很容易地按顺序保存我的值,如果我有一个适合的钥匙(TryGet),很容易找到,所有这些都在一个整洁,量身定制的包装中。创建多个数组列表并执行&#34;(查找我的值的索引); ARRAY1 [指数]。新增(值)&#34;将被&#34; Dictionary.Add(value,suit)&#34;取代。但我只能在创作时为一把钥匙添加西装。我无法做出一个&#34; 2&#34;键和添加&#34; S&#34;然后当我发现下一张卡片是&#34; 2D&#34;在&#34; 2&#34;下添加D键。字典只是不支持,甚至根本不添加多个值。我可以创建列表字典,但我仍然无法编辑列表,因为字典主要是查询数据结构。查找支持每个键的多个值,但在初始&#34; Add()&#34;之后仍然无法更改。我再一次可以重新创造&#34;整个查找或字典添加一个西装,并保持一切顺序。但对我而言,这似乎重建了整座桥梁,因为这条电缆太长而且我没有工业能力的切割机。这个问题应该有一个更简单的解决方案,比如可以去获取一些切割器(可能导入一个类?)。


    结论

    既然你的建议我的需求与手工评分系统所能提供的并没有什么不同,那么我会提出另一个问题:

    手牌分数是否与某些牌直接相关?就像我之前提到的那样,我想要的结果是#34;你可以做的最好的手就是满堂红&#34;不是&#34;这名球员手牌最多。&#34;因此,我可以计算得分最高的手并推断出一个满堂红的&#34;从那个分数?如果是这样,那么我猜这都是不必要的代码,但在这种情况下,无论如何我都想解决这个问题。

    当我写这篇编辑时,我突然意识到这基本上是一个虚荣问题。我不喜欢&#34;我的解决方案。我也不想使用已接受的解决方案(表查找),因为这不是一个复制品项目的编码项目。我非常感谢任何意见。

2 个答案:

答案 0 :(得分:1)

让我们以最简单的方式做到这一点。首先,假设您有一个包含10个字符串的数组,每个字符串都是一张卡片的名称。像“四心之心”和“黑桃皇后”。这真的很不方便。所以我们要做的第一件事就是将这些字符串转换为数字来表示每张卡片。一个非常方便的方法是使用数字0-12表示心形,13-25表示钻石等。所以你有代码(可能是查找表)将名称转换为数字:

Ace of Hearts = 0
Two of Hearts = 1
Three of Hearts = 2
...
Queen of Hearts = 11
King of Hearts = 12
Ace of Diamonds = 13
...
...
Ace of Clubs = 26
...
...
Kind of Spades = 51

所以你有一组代表10张牌的数字。称之为cardsArray

int[] cardsArray = new int[10];
// here, fill the cards array from the input

如果您按照套装和价值排序,则很容易检查是否有冲洗。请记住,只有10张牌,因此排序不会花费大量时间。排序非常简单:

int[] sortedBySuit = 
    cardsArray
    .OrderBy(x => x/13)  // sorts by suit
    .ThenByDescending(x => x % 13) // then by value, descending
    .ToArray();

然后你可以按顺序遍历数组并确定你是否有同花顺,同花顺,以及同花顺中的高牌(如果有的话)是什么。

你必须保存这些信息,例如,因为四种类型的节拍打败了。所以你也需要检查一下。

接下来,按值排序:

int[] sortedByValue =
    cardsArray
    .OrderByDescending(x => x % 13)
    .ToArray();

现在,您可以按顺序浏览该列表,以确定高卡,对,三种,四种或直道。当您找到每种类型的手牌时,您可以保存手牌信息(“王高直”或“三十”,以及手牌的价值[高牌为1,对牌为2,为直,冲,满屋等)正确的顺序])到列表。

然后,您只需从您找到的那些中选择具有最高价值的牌。

这绝对不是最快的做事的方式,但它很简单,使用的内存非常少,并且对于原型来说足够快。它肯定比使用字典或数组数组等简单。

答案 1 :(得分:0)

要说清楚,我没看过你的小说。

  

TL; DR SPARKNOTES VERSION:如何在Lookup内的键中添加更多值?

通常,当我需要一个带有多个值的密钥的“字典”时,我使用List<KeyValuePair<string, int>>。您可以使用LINQ to Objects来选择所有值。例如:

    static void StackOverflowExample()
    {
        var cardList = new List<KeyValuePair<string,int>> ()
        {
            new KeyValuePair<string, int>("Club", 8),
            new KeyValuePair<string, int>("Spade", 9),
            new KeyValuePair<string, int>("Heart", 10)
        };

        var results = cardList.Where(p => p.Key == "Heart");
    }

var结果是IEnumerable<KeyValuePair<string,int>>。希望这有帮助。