如何在List <int>中找到具有重复项的连续数字?</int>

时间:2015-02-10 00:58:46

标签: c# list sorting

我很无聊所以我决定尝试&amp;制作一个我自己的Yahtzee游戏,与实际游戏一样精确的规则,只是想测试我的编程技巧(这还不是很令人惊讶)。

下面张贴的代码用于检查直道(小型和大型)。 我确定你可以亲眼看到,但万一你不这样做,它就像这样:

所有5个骰子的值都放在List中,然后使用List<T>.Sort()方法对其进行排序。

现在它们应按升序排列在列表中(例如1,2,3,4,5)。

为了找出它是否是一个大直线,我只是使用一个int,如果检测到一个小直线,它会增加1的值,然后由于我的&#找到一个大直线34;大直=小直* 2&#34;逻辑,可能有缺陷,但似乎对我有意义:)。

这很有效,但并非总是如你所知,如果我在中间某处有重复值,这段代码就不会起作用,例如1,2,3,3,4,6。这一系列的数字仍然应该给我一个小的直线,但它不会。

现在我的实际问题是:如何修改此代码,以便它始终能够检测到小代码和小代码。大直道?

List<int> valList = new List<int>();
foreach (Dice d in dList)
{
    valList.Add(d.Value);
}
valList.Sort();

txtSmall.Text = "0";
txtLarge.Text = "0";
int straight = 0;
if (valList[0] == valList[1] - 1 && valList[1] == valList[2] - 1 && valList[2] == valList[3] - 1)
    straight++;
if (valList[1] == valList[2] - 1 && valList[2] == valList[3] - 1 && valList[3] == valList[4] - 1)
    straight++;
switch (straight)
{
    case 1:
        if (txtSmall.IsEnabled)
            txtSmall.Text = "30";
        break;
    case 2:
        if (txtSmall.IsEnabled)
            txtSmall.Text = "30";
        if (txtLarge.IsEnabled)
            txtLarge.Text = "40";
        break;
}

PS:万一你需要知道我的Dice课程是什么,这里是(虽然我不明白你为什么需要它):

class Dice
{
    private static CryptoRandom r = new CryptoRandom();
    public static int uBound = 1;
    public static int lBound = 7;
    public string Path { get; set; }
    private int value;
    public int Value
    {
        get { return value; }
    }
    private bool locked;
    public bool Locked
    {
        get { return locked; }
    }

    public Dice(int lowerBound = 1, int upperBound = 6)
    {
        uBound = upperBound + 1;
        lBound = lowerBound;
        this.Roll();
        this.locked = false;
    }

    public void Roll()
    {
        this.value = r.Next(lBound, uBound);
    }

    public void Lock()
    {
        this.locked = true;
    }

    public void Unlock()
    {
        this.locked = false;
    }
}

PPS:如果有更好的方法来检测这些内容,请随时分享,但也请尝试回答我的问题:)。

3 个答案:

答案 0 :(得分:2)

一种非常简单的方法是在排序之前调用Distinct,这会删除所有重复项:

List<int> allDice = new List<int>() { 1, 2, 3, 3, 4, 6 };
IEnumerable<int> uniqueDice = allDice.Distinct();
IEnumerable<int> sortedDice = uniqueDice.Sort(x => x);

//etc.

否则,您的方法是合理的。没有什么能够迅速成为寻找小直道的更好方法。

答案 1 :(得分:2)

如果性能不是问题,我正确理解问题,我会尝试这样的事情:

var count = dList.Count; //6
var straights = dList.Select(dice => dice.Value)
    .Distinct() //5,3,1,6,4
    .OrderBy(dice => dice.Value) //1,3,4,5,6
    .Select(dice => dice.Value + (count--)) //7,8,8,8,8
    .GroupBy(n => n) //[7,{7}],[8,{8,8,8,8}]
    .OrderByDecending(group => group.Count());

var longestStraight = straights.First().Count(); //4

答案 2 :(得分:1)

这是另一种方法,只是为了好玩:

/// <summary>
/// Determines if the dice passed in contain a strait
/// </summary>
/// <param name="dice">The dice to test</param>
/// <returns>0 if there are no straits, 1 if there is a small strait, 
/// or 2 if it contains both a large and small strait</returns>
private static int ContainsStrait(IEnumerable<int> dice)
{
    var uniqueDice = dice.Distinct().ToList();
    if (uniqueDice.Count < 4) return 0;

    uniqueDice.Sort();

    int consecutiveNumbers = 1;
    int lastValue = -1;

    foreach (var uniqueDie in uniqueDice)
    {
        if (uniqueDie == lastValue + 1)
        {
            consecutiveNumbers++;
        }
        else
        {
            consecutiveNumbers = 1;
        }

        lastValue = uniqueDie;
    }

    return (consecutiveNumbers > 4) ? 2 : (consecutiveNumbers > 3) ? 1 : 0;
}

测试它:

private static void Main()
{
    var rolls = new List<List<int>>
    {
        {new List<int> {3, 3, 3, 3, 3, 3}},
        {new List<int> {1, 2, 3, 4, 3, 2}},
        {new List<int> {2, 2, 3, 4, 5, 2}},
        {new List<int> {3, 3, 3, 4, 5, 6}},
        {new List<int> {1, 2, 3, 4, 5, 2}},
        {new List<int> {2, 2, 3, 4, 5, 6}}
    };

    foreach (var roll in rolls)
    {
        int result = ContainsStrait(roll);

        Console.WriteLine("The roll: {0} does {1}contain a small strait {2} a large strait",
            string.Join(", ", roll),
            result > 0 ? "" : "not ",
            result == 2 ? "and" : result == 1 ? "but not" : "or");
    }
}