Поиск-Сравнение-

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4160
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 06.01.2004 (Вт) 11:01

Извини, ощущение, что программа написана с новогоднего похмелья. Зачем здесь вообще текст, зачем таймер, если нужен список?
Используя Int(RND*9) получим максимум 9 неповторяющихся целых чисел. Вставь в пустую форму код:
Код: Выделить всё
Option Explicit

Dim m(0 To 8) As Integer, x As Integer, y As Integer

Private Sub Form_Load()
  Randomize Timer
  Me.Show
  Me.Cls
  m(0) = Int(Rnd * 9)
  Me.Print 0, m(0)
  For x = 1 To 8
    Do
      m(x) = Int(Rnd * 9)
      For y = 0 To x - 1
        If m(x) = m(y) Then Exit For
        If y = x - 1 Then Exit Do
      Next y
    Loop
    Me.Print x, m(x)
  Next x
End Sub


случайные числа в массиве и, для контроля, напечатаны на форме.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 06.01.2004 (Вт) 11:40

Rnd не гарантирует, что числа не будут повторяться.

Делаешь список из всех возможных значений (например, 0...9), потом выбираешь случайный элемент из этого списка, добавляешь его в список случайных значений и удаляешь из исходного списка. И повторяешь столько, сколько нужно. Отсутствие повторений гарантировано.
Lasciate ogni speranza, voi ch'entrate.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4160
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 06.01.2004 (Вт) 15:26

alibek
Конечно не гарантирует. Только обрати внимание, что у меня стоит проверка на совпадение и повторный RND. Почти тот же вариант, что и у тебя, только без предварительного составления списка (зачем?).

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 06.01.2004 (Вт) 16:52

Объясняю.
Предположим нужно получать неповторяющиеся трехзначные числа (трехзначные -- всего 1000 возможных значений, от 000 до 999).
Допустим надо получить 990 случайных чисел.
Первое число будет действительно не повторяющимся. А теперь представь, ты получил 989 значений и надо получить последнее. 989 из 1000 значений уже использовано, осталось 11 вариантов. И вероятность того, что Rnd попадет в один из этих 11 вариантов чуть больше одного процента.
Короче, если не повезет, то твоя процедура может очень долго крутиться вхолостую, пока не выпадет то число, которое еще не использовалось (не говоря уже о том, что проверка будет занимать время, тем большее, чем больше вариантов уже использовано).
Lasciate ogni speranza, voi ch'entrate.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4160
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 06.01.2004 (Вт) 18:06

Все верно, время выполнения будет расти пропорционально квадрату количества чисел. Но выборка случайного элемента из списка в твоем варианте - то же самое. Как выбрать случайный элемент? С помощью RND сгенерировать адрес, проверить, использовался он, или нет...

Tarik
Агент Системы
Агент Системы
Аватара пользователя
 
Сообщения: 1222
Зарегистрирован: 03.01.2003 (Пт) 16:05
Откуда: Москва

Сообщение Tarik » 06.01.2004 (Вт) 21:26

Насколько я понял, ключевая фраза в постинге alibek'а такая:
Делаешь список из всех возможных значений (например, 0...9), потом выбираешь случайный элемент из этого списка, добавляешь его в список случайных значений и удаляешь из исходного списка . И повторяешь столько, сколько нужно. Отсутствие повторений гарантировано.

То есть использованные числа уже удалены из списка возможных, поэтому проверять, использовался он или нет уже не нужно.
Изображение

Ever tried? Ever failed? No matter. Try again! Fail again! Fail better!

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4160
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 07.01.2004 (Ср) 16:11

Интересно, кто кого не понял...
Может кто-то мне объяснит смысл слова "удаляешь"?
А что "Отсутствие повторений гарантировано" я и не спорю.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4160
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 07.01.2004 (Ср) 16:28

Sync
Тебе нужно в список "А" добавить из списка "Б" все элементы, которых в "А" еще нет. Я верно сформулировал твой вопрос? Если да, то вот:

Код: Выделить всё
Option Explicit

Private Sub Command1_Click()
Dim n1 As Integer, n2 As Integer, s As String
  For n2 = 0 To List2.ListCount
    s = List2.List(n2)
    For n1 = 0 To List1.ListCount
      If List1.List(n1) = s Then Exit For
      If n1 = List1.ListCount Then List1.AddItem s
    Next n1
  Next n2
End Sub


Помести на форму листбоксы List1 и List2 и кнопку Command1. Этот код кинь в код формы. Заполни листбоксы произвольным количеством произвольных значений. При нажатии на кнопку List1 дополнится недостающими значениями из List2.

Alibek
если ты это и имел ввиду - ListBox или коллекции - тогда все понятно. А удаление элемента из ListBox-а - как бы не более медленный процесс, чем повторные поиски значения в массиве. Просто я вел речь о массивах, а поправку вопроса Sync увидел только сейчас - она появилась в первом посте.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 08.01.2004 (Чт) 10:22

Mikle, удалять можно и из массива, и если этот процесс оптимизировать, то он не будет занимать много времени.
Например, так. Для определения верхней границы массива с исходными значениями используется не UBound(List1), а переменная List1Count (которая изначально равна UBound(List1)). Когда надо удалить элемент I все элементы с I+1 по List1Count перемещаются на одну позицию вниз. Перемещение можно сделать в цикле (даже так будет довольно быстро), но еще лучше использовать API CopyMemory. И после перемещения элементов уменьшить счетчик List1Count=List1Count-1. После того, как список исходных значений не нужен, память можно освободить, Erase List1().
Вот так вот, быстро, дешево и сердито :)

Sync, а вот теперь я уже не понимаю вопроса :)
Тебе надо заполнить список из другого списка, только исключить повторения?
В таком случае (если первый список представляет собой строку, разделенную запятыми), можно делать так.
Код: Выделить всё
'Строковая переменная ValueList содержит числа, в твоей задаче это Text1.Text
Sub AddValue(ByVal Value As Long)
Dim V As String
Const D As String = ","
V = Trim$(Str$(Value))
If InStr(D & V & D, D & ValueList & D) = 0 Then
  If Len(ValueList) > 0 Then ValueList = ValueList & D
  ValueList = ValueList & V
End If
End Sub


Использование:
Код: Выделить всё
Dim I As Long, V As Long
For I = 1 To 10
  Randomize
  V = Fix(Rnd*9)
  AddValue V
Next I
MsgBox ValueList
Lasciate ogni speranza, voi ch'entrate.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4160
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 08.01.2004 (Чт) 16:05

alibek
Согласен, так получится несколько быстрее. Но появилась идея еще быстрее - на место удаленного элемента перемещать последний - ведь порядок элементов в массиве нам НЕ ВАЖЕН. И с API не париться. :)


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 8

    TopList  
cron