2014-02-14 28 views
-1

我有两个List<int>,我们打电话给一个Pool,另一个Used乱序无法输出两次相同的号码的列表

Pool0XUsed具有已从Pool名单中抽调整数之间的整数。

所以我想要实现的是从Pool列表中获得随机抽签,其中抽签不包含在Used列表中的任何地方。如果我已经使用了所有数字,我希望它跳回0

这就是我想出了,但它没有工作

int x = 0; 
int ri = 0; 
Random r = new Random(); 
while (true) 
{ 
    ri = r.Next(0, Pool.Count); 
    if (!Used.Contains(ri)) 
    { 
     break; 
    } 
    else 
    { 
     x += 1; 
    } 

    if(x == Used.Count) // Here I check if it has tried getting a new random number but failed since the Pool is "empty" 
    { 
     ri = 0; 
     UsedIndexes = new List<int>(); 
     break; 
    } 
} 

当我用这个,但它确实在那里从0-2-4-6-8等等,我不知道为什么跳到一些疯狂的事情。

不应该这样工作吗?我如何解决它?

+4

http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle –

+1

发布的代码是否编译? – NoChance

+0

你怎么“得到”什么?这段代码不会输出任何内容。 –

回答

2
List<int> pool = new List<int>() { 1, 2, 3, 4, 5 }; 
List<int> used = new List<int>(); 
Random r = new Random(); 

while (pool.Count > 0) 
{ 
    int idx = r.Next(pool.Count); 
    used.Push(pool[idx]); 
    pool.RemoveAt(idx); 
} 
// Now used contains random iteration of 1,2,3,4,5 
// To loop again, just assign used back to pool and repeat 
pool = used; 
used = new List<int>(); 

或者,做一个Fisher-Yates shuffle(可以在适当的地方完成),然后通过它们0到n。当你达到n,重新洗牌并从0开始。

+0

是的,费希尔方法看起来很有用,因为我不必再使用“已用”列表。 – Tokfrans

+0

这假定在'pool'列表中没有重复的数字。如果有,然后提取一个较短的列表,只包含非重复,并洗牌那个较短的列表。 – rossum

0

这应该完成你想要的。

Random r = new Random(); 
var pool = new List<int>() { 1, 2, 3, 4, 5 }; 
var used = new List<int>(); 

while(used.Count != pool.Count) { 
    var ri = r.Next(0, pool.Count); 
    var choice = pool[ri]; 
    if (!used.Contains(choice)) { 
     Console.WriteLine(choice); 
     used.Add(choice); 
    } 
} 

used.Clear(); 
+0

不能保证永远不会退出... –

+0

@MattBurland写给我一些失败的测试,我会解决它们,嘿嘿。让我们来看看这个算法的所有TDD!开玩笑,谢谢你的通知。我无法发现它不会退出的情况。照顾开导我们? –

+1

这是不太可能的,但让我们假设随机数发生器每一次都会不断产生数字'1' *,实际上,这与真正的随机过程中任何其他特定的数字序列一样不可能。在这种情况下,你的'!used.Contains(choice)'将总是返回false,你的'used'永远不会被填满。所以这是一个愚蠢的例子,但想象一下,如果有5个数字,你就有500,000个数字。一旦你选择了499,999,用你的算法选择最后的数字需要多长时间?最坏的情况下? –

相关问题