-1

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

我正在进行的项目需要 10 张牌,并且需要报告找到的最好的 5 张牌(“顺子”、“高牌”、“同花”等)。幸运的是,实际的牌是什么无关紧要,我只需要一个名字。

我已经对所有卡片进行了解析和分类,并为所有可能的手牌进行了测试。我现在只需要一种方便的方式来存放双手。我的疯狂方法如下,用伪代码术语:

我想要一个水平的动态列表,我可以用卡片的 NUMBER 值填充,按从高到低的顺序排列。例如,“QJT 7 4 2 1”。T 为 10。重复的值将被忽略。接下来,我希望这些值中的每一个在下面都有一个存在于套牌中的每个值的套装列表。例如,J 将有一个带有值“D H”的子列表,以表示我有一个钻石杰克和一个红心杰克。

我相信这是处理这些牌的最优雅的方式,因为大多数扑克牌只处理价值,这样我就不必担心连续相同价值的牌,比如顺子测试。然后可以通过参考键下的值轻松测试处理西装的两个测试

深吸一口气,差不多了。

所以 Lookup 的一个实例似乎是完美的!它具有我想要的确切的“多值一键”结构。但是,它不允许我在找到西装时添加它们。我必须一次添加它们,或者根本不添加它们,因为列表在输入后是不可变的。

所以我要么

  1. 在我进行查找之前必须一次找到所有的西装
  2. 以某种方式将值添加到查找列表或
  3. 用别的东西。

对这些有什么想法吗?

更新

TL;DR SPARKNOTES 版本:如何向查找内的键添加更多值?

*重要提示: *此程序的输出应该是一个字符串,其中包含可能的最高牌的名称,例如“四对”、“两对”或“高牌”。

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


方法一

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

  1. 创建一个 ArrayLists 数组(数组 1)
  2. 遍历“卡片”的排序字符串数组(数组 2)
  3. 对于每张卡:
  4. 将字符串索引 [1] 处的字符(代表西装)添加到数组 1 中从字符串索引 [0] 中提取的索引号处的 ArrayList 中。

这样我就有了我想要的相关套装的值列表。西装列表是引导的最小尺寸,使以后更容易迭代。通过一些额外的步骤,我什至可以将伞形数组设为 ArrayList,并按顺序用卡片值填充它,这样就没有间隙,也没有重复的数字。这会给我留下一个我想要的参差不齐的数组。需要明确的是,这不是家庭作业。然而,它来自我室友过去完成的一个编码课程项目,这就是我有限制和要求的原因。我问过的其他人告诉我,SE 这段时间被这类家庭作业问题所困扰,所以我理解你的怀疑。这是一个个人项目,因为我想学习 C#(我现在只知道 Java,

如果它是一个年级,我会在那里结束,因为它有效。但我真的不喜欢数组列表的数组列表,它们对我来说似乎很乱。所以我想知道是否有另一种方法。


方法二

我还考虑过简单地处理不可避免地出现的重复项。例如,这是我对顺子的测试:

 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 张卡片(因为您不能直接从 10 张排序卡片中获得少于 5 张卡片),然后按照您的预期检查接下来的 5 张卡片。如果在此迭代过程中我遇到重复条目,则意味着它是另一张花色的同一张牌,我只是“打破”。这条语句的结果应该是,现在我们已经将第二次迭代增加了 1 以检查下一张卡片而不是当前卡片。我们拥有的按顺序牌的数量将保持不变,这样在找到顺子时,“1D 2D 3S 3H 4D 5C”之类的列表将跳过第二个 3。尽管休息了一段时间,但我实际上对这个解决方案的优雅感到非常满意,无论我是否有权这样做。

这一切都可以追溯到使用简单的字符串数组(“卡片”)的缺陷,这是我的代码现在量身定制的。我讨厌解决问题,我宁愿避免它们。也许我是不必要的挑剔,但我一直在学习。


方法 3

我对字符串数组的弱点的考虑将我引向了字典,它看起来很有吸引力。它可以很容易地保持我的价值观,并且很容易找到我是否有适合钥匙的套装(TryGet),所有这些都在一个整洁的定制包装中。创建多个数组列表并执行诸如“(查找我的值的索引);array1[index].Add(value)”之类的操作将被“Dictionary.Add(value, suit)”替换。但是我只能在创建时将西装添加到钥匙上。我无法制作“2”键并添加“S”,然后当我发现下一张卡是“2D”时,在“2”键下添加一个 D。字典只是不支持,甚至根本不支持多个值。我可以制作列表字典,但我仍然可以 t 编辑列表,因为字典主要是查询数据结构。查找支持每个键的多个值,但在初始“Add()”之后仍然无法更改。同样,我可以“重新创建”整个查找或字典来添加西装并保持一切井井有条。但对我来说,这似乎是重建整座桥,因为这根电缆太长而且我没有工业用的切割器。这是一个应该有一个更简单的解决方案的问题,比如可能去获取一些刀具(可能导入一个类?)。但对我来说,这似乎是重建整座桥,因为这根电缆太长而且我没有工业用的切割器。这是一个应该有一个更简单的解决方案的问题,比如可能去获取一些刀具(可能导入一个类?)。但对我来说,这似乎是重建整座桥,因为这根电缆太长而且我没有工业用的切割器。这是一个应该有一个更简单的解决方案的问题,比如可能去获取一些刀具(可能导入一个类?)。


结论

由于您认为我的需求与手牌评分系统可以提供的需求没有什么不同,这让我想到了另一个问题:

手牌分数是否与某些手牌直接相关?就像我之前提到的那样,我想要的结果是“你能做的最好的牌是满屋”而不是“这个玩家的牌最高”。那么我可以计算出最高得分的手牌并从该得分中推断出“满堂彩”吗?如果是这样,那么我想这都是不必要的代码,但是在那种情况下我还是想解决这个问题。

当我写这个编辑时,我突然意识到这基本上是一个虚荣的问题。我不“喜欢”我拥有的解决方案。我也不想使用公认的解决方案(表查找),因为那不是一个复制粘贴项目的编码项目。我将不胜感激任何意见。

4

2 回答 2

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();

现在您可以按顺序浏览该列表以确定高牌、对子、三张、四张或顺子。当您找到每种类型的手牌时,您将手牌信息(“K 高顺子”或“三个 10”,以及手牌的价值 [1 代表高牌,2 代表对子、顺子、同花、满屋等)保存在正确的顺序]) 到一个列表。

然后,您只需从找到的牌中挑选价值最高的牌。

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

于 2013-09-11T23:06:58.127 回答
0

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

TL;DR SPARKNOTES 版本:如何向查找内的键添加更多值?

通常,当我需要一个带有多个值的键的“字典”时,我会使用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>>. 希望这会有所帮助。

于 2013-09-11T00:54:17.870 回答