2013-08-30 4 views
0

У меня есть программа, которую я создал для личного использования, которая будет случайным образом выбирать фильм из набора отмеченных элементов в списке. Одной из функций, которые я запрограммировал в этом приложении, является способность генерировать «многоуровневый результат». То, что я подразумеваю под многоуровневым результатом, заключается в том, что алгоритм должен сначала случайным образом выбирать три фильма, затем произвольно выбирать два из них, а затем, в конечном итоге, случайным образом выбирать финальный фильм из этих двух.Произвольный выбор подмножества из списка

Чтобы проиллюстрировать, что я имею в виду:

Список фильмов: Вопль, Вопль 2, Shriek 3, Monsters Inc, Бэмби, Бэмби 2

Этап 1: Вопль 3, Бэмби, Бэмби 2

Tier 2: Вопль 3, Бэмби

Tier 3: Bambi

я успешно выполнил это с помощью следующего кода:

Private Sub btnPick_Click(sender As System.Object, e As System.EventArgs) Handles btnPick.Click 
    If boxMovies.CheckedItems.Count <> 0 Then 
     Dim rnd As New Random 

     If My.Settings.Tier = True Then 
      lbl1.Text = boxMovies.CheckedItems.Item(rnd.Next(boxMovies.CheckedItems.Count)) 
      Randomize() 
      lbl2.Text = boxMovies.CheckedItems.Item(rnd.Next(boxMovies.CheckedItems.Count)) 
      Randomize() 
      lbl3.Text = boxMovies.CheckedItems.Item(rnd.Next(boxMovies.CheckedItems.Count)) 

      Randomize() 
      Dim stp2() As String = {lbl1.Text, lbl2.Text, lbl3.Text} 
      lbl4.Text = stp2(rnd.Next(stp2.Length)) 
      Randomize() 
      lbl5.Text = stp2(rnd.Next(stp2.Length)) 

      Randomize() 
      Dim stp3() As String = {lbl4.Text, lbl5.Text} 
      lbl6.Text = stp3(rnd.Next(stp3.Length)) 
     Else 
      MessageBox.Show(boxMovies.CheckedItems.Item(rnd.Next(boxMovies.CheckedItems.Count)), "Movie Result", MessageBoxButtons.OK) 
     End If 
    Else 
     MessageBox.Show("Please pick at least one movie!", "No Movies Selected", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) 
    End If 

End Sub 

Проблема, которая возникает у меня, состоит в том, что фильмы могут генерироваться случайным образом дважды в любом заданном уровне. Изображение ниже поможет проиллюстрировать то, что я имею в виду:

enter image description here

Обратите внимание, как в 2-го уровня, «Звездные войны Saga» генерируется дважды. Это в конечном итоге приводит к тому, что «Звездные войны Saga» являются гарантированным результатом в Уровне 3.

Мне было интересно, был ли простой способ (не стесняйтесь улучшать мой код, я понимаю, что это, вероятно, неэффективно, я просто что-то бросил быстро), чтобы решить эту проблему. Я хотел бы, чтобы результаты на каждом уровне были уникальными для этого уровня.

ответ

1

Представьте, что у вас есть вектор V с N фильмами (или индексы к фильмам).

For i:=0 to 2 do 
    r := rand(N-i-1)   // A random integer fro 0..N-i-1 inclusive 
    AddToResult(V[r]) 
    V[r] := V[N-i-1]   // Override the selected element with the last one. 

Идея состоит в том, чтобы выбрать случайный элемент из списка и поместить последний элемент вместо извлеченного элемента. Таким образом, новый список будет иметь длину N-1 и не будет включать извлеченный элемент. Этот новый список имеет другой порядок, но поскольку мы выбираем случайный, мы не заботимся об этом.

+0

Это работает в некоторой степени, если выбран только один фильм, он выдает ошибку. –

+0

@JasonBristol Это просто классический алгоритм для выбора m случайных элементов из списка из n элементов, где m <= n. Прежде всего, вы должны проверить, хотите ли вы выбрать меньшее количество элементов, количество доступных в списке элементов. – jbaylina

+0

@JasonBristol Я скорректировал последнюю строку псевдокода. (Я изменил i с -1). – jbaylina

Смежные вопросы