2012-03-19 2 views
1

난수를 사용하면 진정한 난수가 생성되지 않지만 반복을 방지하기 위해이 코드가 작동하지 않아야하는 이유를 알지 못합니다. 목표는 코드를 실행에 오류가없는 0에서 44 사이 (포함되지 않음)에서 8 개 고유 번호를 유도하는 것이지만, 반복이 발생합니까 :반복되지 않는 난수에 순환 루프 및 정수 배열 사용

//Loop Begins Within Main 
for (int i = 0; i < 8; i++) 
{ 
    //Begins Recursion 
    int x = Unique8(rndm, num8); 
    num8[i] = x; 
} 

//Recursion Takes Place Outside of the Main with Static Declarations 
static Random rndm = new Random(); 
static int[] num8 = new int[8]; 

static int Unique8 (Random rndm, int[] num8) 
{ 
    int x = rndm.Next(1, 43); 

    //Seeks if Number is Repeated 
    if (num8.Contains(x)) 
    { 
     //If So, Recursion Takes Place 
     Unique8(rndm, num8); 
    } 

    //Returns Value to Original Loop to be Assigned to Array 
    return x; 
} 

랜덤 때문에의 번호를 재생하는 경우 알고리즘, 왜 그들은 재귀를 통과하고 있습니까? 왜 이것이 무한 루프가되지 않습니까?

나는 이것에 대한 좋은 해결책을 발견했다. 갑판을 뒤섞고 맨 위에 카드를 긋는 것과 비슷하다. 원래의 정렬 된 배열을 만드는 것은 쉽지만 어떻게 혼합되어 있는지 이해할 수 없습니다. 당신은 장애

+0

스레드로부터 안전하지 않습니다 [범위 내에서 생성 N 임의의 고유 번호]의 BTW –

+0

가능한 중복 (http://stackoverflow.com : 그럼 방금 그린 번호를 제거하는 List.RemoveAt를 사용/questions/4299138/generate-n-random-and-unique-numbers-within-a-range) –

+0

제한이 없으므로 잘못된 방법입니다. 그것이 종결 될 것이라는 보장은 없습니다. –

답변

9

C#에서 배열 당신은 반환 값으로 아무것도하지 않는

//If So, Recursion Takes Place 
Unique8(rndm, num8); 

를 참조하려면 어떻게 - 당신이 운이 경우에 당신은

x = Unique8(rndm, num8); 
+1

심지어 Unique8 (rndm, num8)을 반환합니다. –

2

로 변경할 수 있어야 , 코드는 stackoverflow이 될 수 있습니다. 셔플 링을 사용하여 8 개의 고유 번호를 얻는 또 다른 방법이 있습니다.

int[] array = new int[43]; 
for (int i = 0; i < array.Length; i++) array[i] = i+1; 

FisherYatesShuffle(array); 

int[] newArray = array.Take(8).ToArray(); 

public static void FisherYatesShuffle<T>(T[] array) 
{ 
    Random r = new Random(); 
    for (int i = array.Length - 1; i > 0; i--) 
    { 
     int j = r.Next(0, i + 1); 
     T temp = array[j]; 
     array[j] = array[i]; 
     array[i] = temp; 
    } 
} 
0

한 가지 방법은 L.B 이미 게시 한대로 피셔 예이츠 셔플 사용하는 것입니다. 과거에 해본 또 다른 방법은 가능한 모든 값을 가진 목록을 채운 다음 0과 목록 개수 사이의 임의의 숫자를 생성하여 목록에서 무작위로 추출하는 것입니다.

List<int> myList = new List<int>(43); 
for (int i = 0; i < array.Length; i++) myList.Add(i+1); 


for (int j = 0; j < 8; j++) 
{ 
    int idx = rndm.Next(myList.Count); 
    num8[i] = myList[idx]; 
    myList.RemoveAt(idx); 
} 
+0

이 작업은 기본적으로 'return rndm.Next (myList.Count);와 동일하지 않습니다. – sji

+0

@sji : 아니에요. 목록에서 사용한 항목을 다시 가져 오지 않도록 목록에서 제거해야합니다. –