Форум: "Основная";
Текущий архив: 2004.02.17;
Скачать: [xml.tar.bz2];
ВнизГенератор случайных чисел Найти похожие ветки
← →
Norfolk (2004-02-07 12:19) [0]Проблема собственно такая:
Необходим генератор случайных чисел, генерирующий число в заданном промежутке, но так, чтобы число не повторялось. То есть число должно генерироваться не при открытии программы, а при выполнении какого-либо действия (скажем при щелчке на кнопке), и когда все возможные варианты исчерпаны форма должна закрываться.
На мой взгляд решение данной проблемы только одно:
Вести массив уже сгенерированных чисел и делать проверку сгенерированного числа с элементами массива. Но то, что я сам навоял толком не работает, то есть числа всё равно повторяются.
Если видете другое решение данного вопроса, прошу поделиться мыслями (желательно с исходниками), либо написать алгоритм ведения массива и проверки.
Заранее спасибо.
← →
Randomizer (2004-02-07 12:32) [1]Покажи, что ты сделал и тебе укажут на ошибку.
Другого способа так сразу и не предложишь...
← →
Начинающий веб-дизайнер (2004-02-07 12:33) [2]2. Заполняешь статический массив числами равными индексу, потом хорошенько перемешиваешь этот массив, потом берёшь из него элементы по порядку, как дойдёшь до конца массива - всё.
3. Динамический массив заполняешь числами в порядке возрастания.
По нажатию на кнопку генерируешь случайное число в диапазоне индексов массива, выводишь соответствующий элемент массива на экран, после чего удаляешь его из массива. Как только длина массива станет равной 0 значит числа кончились
← →
Norfolk (2004-02-07 13:36) [3]
> Покажи, что ты сделал и тебе укажут на ошибку.
Сделал я примерно так:
var
TestIndex: array [0..49] of byte;
i, j: byte;
...
...
procedure TTesterForm.NextBtnClick(Sender: TObject);
var
k: byte;
begin
Randomize;
i := Random(49);{Здесь немного не так, вместо 49 стоит значение из файла}
for k:=0 to j do
begin
if TestIndex[k]=i then
i := Random(49);
end;
j := j+1;
...{В этой строчке выводим результат}
end;
...
Собственно в чём ошибка я понял. В цикле снова генерируется случайное число если был найден элемент массива равный сгенерированному ранее числу. Но число сгенерированное в цикле далее не проверяется с элементами массива, стоящими до текущего.
Следующим моим шагом было создание вложенного цикла, чтобы проверка происходила сначала цикла несколько раз, но и это не помогло, просто частота появления одинаковых чисел немного уменьшилась:
for p := 0 to 10 do
for k := 0 to i do
← →
Norfolk (2004-02-07 13:39) [4]
> 2. Заполняешь статический массив числами равными индексу,
> потом хорошенько перемешиваешь этот массив, потом берёшь
> из него элементы по порядку, как дойдёшь до конца массива
> - всё.
Если сделать так, то при каждом запуске программы будет одна и таже последовательность числел, что нехорошо.
А за ответ спасибо.
← →
Anatoly Podgoretsky (2004-02-07 13:49) [5]Нет последовательность будет каждый раз разная, вот только уточни, что может быть вместо Random(49)
← →
Norfolk (2004-02-07 13:58) [6]
> что может быть вместо Random(49)
Вместо Random(49) у меня Random(Test[0].Many) Где Test[0].Many массив типа записи, взятый из файла. Для конкретного файла эта величина постоянная, но программе приходиться работать с разными файлами.
← →
Начинающий веб-дизайнер (2004-02-07 14:03) [7]
> Если сделать так, то при каждом запуске программы будет
> одна и таже последовательность числел, что нехорошо.
- всё зависит от того как перемешивать.
Как то я делал такое, тоже заносил сгенерированные числа в массив, там примерно такой алгоритм
function ЧИСЛОЕСТЬВМАССИВЕ(ЧИСЛО): boolean;
begin
Result:= False;
for i:= 0 to Count-1 do
begin
Result:= ЧИСЛО = Массив[i];
if Result then Break
end;
end;
procedure ГЕНЕРАЦИЯЧИСЛА
begin
if ДЛИНАМАССИВА=ДИАПАЗОН then
ВЫХОД
else
begin
ЧИСЛО:= Random(ДИАПАЗОН);
while ЧИСЛОЕСТЬВМАССИВЕ(ЧИСЛО)
ЧИСЛО:= Random(ДИАПАЗОН);
ДОБАВИТЬВМАССИВ(ЧИСЛО);
ВЫВЕСТИ(ЧИСЛО);
end;
end;
← →
Начинающий веб-дизайнер (2004-02-07 14:10) [8]Но при больших диапазонах будет долго думать, или вообще функция RANDOM может не выдать нужного числа, лучше способы 2 или 3
← →
Norfolk (2004-02-08 13:55) [9]
> Как то я делал такое, тоже заносил сгенерированные числа
> в массив, там примерно такой алгоритм
Вот то, что я написал по представленному Вами алгоритму:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ActnList;
function NumArray(Num: byte): boolean;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
ActionList1: TActionList;
Action1: TAction;
procedure Button1Click(Sender: TObject);
procedure Action1Execute(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Arr: array of byte;
implementation
{$R *.dfm}
function NumArray(Num: byte): boolean;
var
i: byte;
begin
Result := False;
for i := 0 to Length(Arr) do
begin
Result := Num=Arr[i];
if Result then Break
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Num: byte;
begin
if Length(Arr)=10 then
Close
else
begin
Randomize;
Num := Random(9);
while NumArray(Num) do
Num := Random(9);
SetLength(Arr, Length(Arr)+1);
Arr[Length(Arr)] := Num;
Edit1.Text := IntToStr(Num);
end;
end;
procedure TForm1.Action1Execute(Sender: TObject);
begin
SetLength(Arr,1);
end;
end.
Программа работает, только вот числа всё равно повторяются, кроме того программа при закрытии выдаёт ошибку RunTime error и какой-то номер.
← →
Ilg (2004-02-08 14:51) [10]Скорее всего ошибку создает строка
Arr[Length(Arr)] := Num;
,
т. к. номера массива идут с 0.
Если ты хочешь, присваивать значение последнему элементу - делай так:
Arr[High(Arr)] := Num;
← →
MBo (2004-02-08 14:53) [11]http://mbo88.narod.ru/RND.ZIP
← →
Mihey (2004-02-08 16:14) [12]Заполнение массива случайными неповторяющимися числами:
procedure FillArray(var A: array of Integer);
var
I, S, R: Integer;
begin
for I := 0 to High(A) do A[I] := I;
for i := High(A) downto 0 do begin
R := Random(I);
S := A[R]; A[R] := A[I]; A[I] := S;
end;
end;
Быстрои сердито, безо всяких сравнений.
← →
Fenik (2004-02-08 16:27) [13]>Mihey © (08.02.04 16:14) [12]
По-моему, это не совсем случайные числа будут.
← →
MBo (2004-02-08 16:41) [14]>Fenik
числа от 0 до N-1 будут перемешаны.
Другое дело, что набор возможных комбинаций будет не абсолютно равномерным, но это обычно допустимо.
← →
Fenik (2004-02-08 16:47) [15]Вот, что выдал алгоритм Михея:
0 - 3
1 - 2
2 - 4
3 - 5
4 - 7
5 - 9
6 - 8
7 - 6
8 - 0
9 - 1
А если мне нужно массив [0..9] заполнить неповторяющимися случайными числами из отрезка [1500..100000]?
← →
MBo (2004-02-08 16:54) [16]>Fenik
для отрезка N...M
Rnd = N+(M-N)*MiheyNumber/10+Random((M-N)/10)
← →
Fenik (2004-02-08 17:12) [17]>MBo © (08.02.04 16:54) [16]
>Rnd = N+(M-N)*MiheyNumber/10+Random((M-N)/10)
Нифига.
Результат:
<cite>0 - 16
1 - 22
2 - 10
3 - 12
4 - 16
5 - 20
6 - 14
7 - 24
8 - 18
9 - 23
Код:
procedure FillArray(var A: array of Integer);
var
I, S, R: Integer;
begin
for I := 0 to High(A) do A[I] := I;
for i := High(A) downto 0 do begin
R := Random(I);
S := A[R]; A[R] := A[I]; A[I] := S;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
const n = 10;
m = 25;
var A: array of Integer;
i, rnd: Integer;
begin
Randomize;
SetLength(A, 10);
FillArray(A);
for i := 0 to High(A) do begin
rnd := Round(N+(M-N)*A[i]/10+Random(Round((M-N)/10)));
Memo1.Lines.Add(Format("%d - %d", [i, Rnd]));
end;
end;</cite>
← →
MBo (2004-02-08 17:22) [18]И что значит >Нифига. ?
Получено 10 неповторяющихся чисел в диапазоне 10-25, как и нужно было.
недостаток - предложенный примитивный метод дает равномерное распределение.
← →
Fenik (2004-02-08 17:27) [19]>MBo © (08.02.04 17:22) [18]
:))
Галюцинации у меня, однако. Минуту назад я видел там две пары повторяющихся.. А сейчас их нет.
← →
Fenik (2004-02-08 19:01) [20]Аааааа!! Блин, теперь точно вижу!
0 - 16
1 - 22
2 - 10
3 - 12
4 - 16
← →
Mihey (2004-02-08 20:17) [21]2 Fenik:
Весьма странно. Алгоритм я проверял так:
procedure TForm1.Button1Click(Sender: TObject);
var a: array [0..30] of Integer;
i, k, l: Integer;
begin
Randomize;
for l := 1 to 50000 do
begin
for i := 0 to High(a) do
begin
a[i] := 0;
end;
FillArray(a);
for i := 0 to High(a) do
begin
for k := 0 to High(a) do
begin
If (a[i] = a[k]) and (i <> k) then
begin
ShowMessage("You are a big bad niggar!!!!");
Abort;
end;
end;
end;
end;
ShowMessage("Finished");
end;
Раз десять, ни разу совпадения.
← →
Думкин (2004-02-08 21:26) [22]> [20] Fenik © (08.02.04 19:01)
Это из-за округлений. Для однозначности надо написать несколько иначе - МВо привел лишь схему.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.02.17;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.008 c