Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > список со случайными неповторяющимися числами


Автор: bagos 2.8.2009, 16:45
Поставил задачу, получить список из случайных не повторяющихся чисел.
Вот что получилось, вроде работает, но один раз из 10-15 получается список с двумя одинаковыми четверками, что за бред не пойму. Помогите плиз разобраться!
Код


var
 i, ran1, ran2: integer;
 bo: Boolean;
 list: TStringList;
begin
 list := TStringList.Create;
 Randomize;
   for i := 0 to 3 do
   begin
     ran2 := Random(12) + 1;
     bo := false;
     if list.IndexOf(IntToStr(ran2)) = -1 then
       list.Add(IntToStr(ran2))
     else begin
       repeat
         ran1 := Random(12) + 1;
         bo := true;
       until (list.IndexOf(IntToStr(ran1)) = -1);
       if bo then
         list.Add(IntToStr(ran1));
     end;
   end;
   lst2.Clear;
   SortList(list);
   lst2.Items.AddStrings(list);
   list.Free;

Автор: VanHelsing 2.8.2009, 17:12
Забыл давно такое не делал. Решил вспомнить:
Код

procedure TForm1.btnRandomClick(Sender: TObject);
var
  i, Rand:Integer;
begin
   lst1.Clear;
   Randomize;
   for i:=0 to 3 do
    begin
      Rand:=Random(12);
      lst1.Items.Add(IntToStr((Rand)));
    end;
end;

Сделал вот так. Да действительно бывают совпадения. Бывает даже что три одинаковых числа.
Идеи следующие: либо увеличить диапазон генерируемых чисел, либо при каждой генерации делать проверку, есть ли уже такое число или нет.

Автор: Keeper89 2.8.2009, 19:08
Код

procedure GetRandomList(N, a, b: Integer;
                        var randList: TStringList);
var
  x, i: Integer;
begin
  // Получаем N уникальных случайных чисел от A до B

  // Если чисел требуется больше, чем есть на интервале - сообщим
  if (b - a < N) then
  begin
    ShowMessage('Невозможно выполнить операцию!');
    Exit;
  end;

  randomize;
  for i := 1 to N do
  begin
    repeat
      x := a + random(b -a + 1);
    until (randList.IndexOf(IntToStr(x)) = -1);
    randList.Add(IntToStr(x));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  randList: TStringList;
begin
  randList := TStringList.Create;
  GetRandomList(30, -15, 15, randList);
  ListBox1.Items.Assign(randList);
  randList.Free;
end;

Автор: MetalFan 3.8.2009, 21:54
предлагаю еще один алгоритм) подойдет для генерации не повторяющихся чисел в опр.диапазоне.
1. заполняем массив от 1 до N
2. проходимся от 1 до N меняя i-тый элемент на j-тый(случайно выбранный).
тем самым не понадобится делать небыстрый поиск в несортированном списке уже сгенеренных значений. 

Автор: Keeper89 3.8.2009, 22:48
Цитата(MetalFan @  3.8.2009,  22:54 Найти цитируемый пост)
2. проходимся от 1 до N меняя i-тый элемент на j-тый(случайно выбранный).

Немного непонял... А какова гарантия, что этот новый случайный элемент уже не будет в списке?

Автор: Qu1nt 5.8.2009, 14:15
Можно так smile
Код

function Shuffle(List: TStringList; Item1, Item2: Integer): Integer;
begin
  Result := - 1 + Random(3);
end;

procedure ShuffleList(Items: TStrings);
begin
  with TStringList.Create do
  begin
    Assign(Items);
    CustomSort(Shuffle);
    Items.Text := Text;
    Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  Randomize; // вызывать нужно один раз - помести в OnCreate

  with ListBox1 do
  begin
    Clear;
    // заполняем массив
    for i := 0 to 9 do
      Items.Add(IntToStr(i));
    // перетасовываем
    ShuffleList(Items);
  end;
end;

Автор: MetalFan 5.8.2009, 14:31
Qu1nt, во, это я и имел ввиду. т.е. не генерация списка случайных чисел, а перемешивание последовательности.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)