2013-01-13 54 views
2

我是C#的新手,我正在做一个数组应用程序。我有如下所示的数字数组:生成随机数与我的数组值不重复

int[] array2 = new int[] { 1, 3, 5, 7, 9 }; 

我需要做的是改变数组中的这些数字的顺序没有重复,因为当我使用随机函数,这说明我重复的数字。

我看到了这种方法,但不知道如何与数字应用它:http://www.dotnetperls.com/shuffle

+0

你试图在这里实现什么,你的示例数组没有任何重复? –

+0

不是'var array2 = new int [] {1,3,5,7,9} .OrderBy(_ => rnd.Next())'够了吗? – I4V

+1

您是否需要保证*每一种可能的订购都有可能* *?你是否还需要保证:*不可能推断未来洗牌过程中的洗牌*? (后面的要求对于偶然的游戏是必要的;如果你能从目前的套牌推断未来的套牌,那么在线扑克变得更容易)。如果两个问题的答案都是肯定的,那么这里发布的答案都不是正确的。如果你不关心攻击者的小偏见或能力来预测你的内部状态,那么这里发布的答案是合理的。 –

回答

5

您可以使用下面的LINQ链:

int[] array2 = new int[] { 1, 3, 5, 7, 9 }; 
var random = new Random(); 
var total = (int)array2. 
    OrderBy(digit => random.Next()). 
    Select((digit, index) => digit*Math.Pow(10, index)). 
    Sum(); 

首先,它命令元素随机,那么它选择乘以10的每个元素,并将它们相加,并将结果转换为整数。另请注意,我没有为您的Random实例提供有用的种子。您可能想要这样做,以产生伪随机结果。

您可能还想使用描述为here的取幂方法,以避免必须转换为整数。

编辑:Rhumborl指出,你可能只需要洗牌阵列。在这种情况下:

var shuffledArray = array2.OrderBy(n => random.Next()). 
    ToArray(); 

应该为你工作。

+0

我认为OP想要在它的末尾仍然有一个数组,在这种情况下只是'var random = new Random(); array2 = array2.OrderBy(n => random.Next())。ToArray();'会做。 – Rhumborl

+0

@Rhumborl我以问题的标题为基础回答了问题,但从内容来看,你所说的话可能是对的。我将编辑我的帖子。 – Mir

+0

仍是一个很好的帖子,请保留详细信息 – Rhumborl

0

所以,正如你所说,你已经有一个数组的数组来处理。所以我不会告诉你如何让一个数组填充唯一的数字。

这就是你如何洗牌你的数组。

  1. 找出如何在0和数组长度之间生成随机数。
  2. 写一个循环,从length_of_the_array-1比0去(使用该指数作为IDX1)

在循环中执行以下操作:

一个。使用步骤1中的方法生成一个介于0到idx1之间的随机数(包括)。(让随机数为idx2。)
b。在idx1和idx2中交换阵列中的元素。

一个简单的交换可以通过执行像这样来完成:

INT TMP =阵列[IDX1];
array [idx1] = array [idx2];
array [idx2] = tmp;

循环结束,你剩下一个混洗阵列。

+0

downvoter解释? – Sanchit

+0

你正在描述的shuffle算法引入了偏差;这是描述不正确的Knuth Fischer Yates洗牌的最常见方式。杰夫有一个很好的分析来描述为什么这个算法在这里是错误的:http://www.codinghorror.com/blog/2007/12/shuffling.html –

+0

Roee Gaveril的回答给出了shuffle算法的正确实现。 –

1

如果你在C#中工作,最好使用C#结构。

您可以使用此通用功能

using System; 
using System.Collections.Generic; 

public static class ListExtensions 
{ 
    public static void Shuffle<T>(this IList<T> list) 
    { 
     var randomNumber = new Random(DateTime.Now.Millisecond); 
     var n = list.Count; 
     while (n > 1) 
     { 
      n--; 
      var k = randomNumber.Next(n + 1); 
      var value = list[k]; 
      list[k] = list[n]; 
      list[n] = value; 
     } 
    } 
} 

,然后你的代码应该是这样的:

List<int> list2 = new List<int>(){1, 3, 5, 7, 9}; 
Shuffle(list2); 
+0

Knuth shuffle的良好实现。我注意到int的数组已经可以转换为'IList ',所以如果你不想使用'List ',就不需要。 –

+1

不应该是'list2.Shuffle()'?当你创建一个扩展方法。 – comecme

0

我不太清楚您可以通过更改顺序没有重复的意思。如果你只是想生成永不重复,你可以做这样的事情

private Random rand = new Random(); 
private List<int> used = new List<int>; 
protected int randomNonrepeating() { 
    int i = rand.next(); 
    while(used.contains(i)) 
     i = rand.next(); 
    used.add(i); 
    return i; 
} 

我的猜测是一个随机数,这不是你看上去很什么,但。如果您只是想在提供的链接上修改算法以使用整数数组而不是字符串。你只需要改变类型。像这样的东西

using System; 

using System.Collections.Generic;使用System.Linq的 ;

static class RandomStringArrayTool static Random _random = new Random();

public static string[] RandomizeStrings(int[] arr) 
{ 
List<KeyValuePair<int, int>> list = new List<KeyValuePair<int, int>>(); 
// Add all strings from array 
// Add new random int each time 
foreach (var s in arr) 
{ 
    list.Add(new KeyValuePair<int, int>(_random.Next(), s)); 
} 
// Sort the list by the random number 
var sorted = from item in list 
     orderby item.Key 
     select item; 
// Allocate new string array 
int[] result = new string[arr.Length]; 
// Copy values to array 
int index = 0; 
foreach (KeyValuePair<int, int> pair in sorted) 
{ 
    result[index] = pair.Value; 
    index++; 
} 
// Return copied array 
return result; 
} 

}

希望这有助于。

+0

如果列表很大,那么您的第一个算法效率不高。如果列表中有一千个项目,算出算法运行多长时间是有益的。 –

+0

你的第二种算法很好,但是你已经写了它大约需要15倍。 '返回(从列表中的项目orderby _random.Next()选择项目).ToArray();'会做得很好。 –