Tu problema es que estas mezclando muchas cosas e ignorando la recomendacion de casimiro.
Tienes que aislar cada sub-tarea y una vez este resuelto, ir a la siguiente.
Tu primer problema es generar los numeros aleatorios. Es claro que no entiendes bien esto porque vas pegando el codigo sin darte cuenta que es ineficiente o que tiene errores obvios (como el que sacaste de ese foro).
Una cosa importante es tratar de eliminar las variables globables y semiglobales de tu programa, que mutar estado es de lo mas problematico y fuente de muchos errores.
Te paso un ejemplo de como limitas el codigo a un unico problema: Generar numeros aleatorios no repetidos, y ademas, de forma elegante:
Código Delphi
[-]
program project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, SysUtils, fgl
;
type
TCheckDuplicate = specialize TFPGMap; TRandomInt = class; TRandomIntEnumerator = class private
FMax: int64; FIndex: int64;
FGen: TRandomInt;
FSet: TCheckDuplicate;
public
constructor Create(generator:TRandomInt; max: int64);
function MoveNext: Boolean;
function GetCurrent: int64;
property Current: int64 read GetCurrent;
end;
TRandomInt = class(TObject)
private
FMax: int64;
public
constructor Create(max: int64);
function GetEnumerator: TRandomIntEnumerator;
end;
constructor TRandomInt.Create(max: int64);
begin
inherited Create;
FMax := max;
end;
function TRandomInt.GetEnumerator: TRandomIntEnumerator;
begin
Result := TRandomIntEnumerator.Create(Self, FMax);
end;
constructor TRandomIntEnumerator.Create(generator:TRandomInt; max: int64);
begin
inherited Create;
FSet := TCheckDuplicate.Create;
FIndex := 0;
FMax := max;
FGen := generator;
end;
function TRandomIntEnumerator.GetCurrent: int64;
var
num: int64;
begin
num := random(MaxInt); while True do
begin
if FSet.IndexOf(num) = -1 then
begin
break;
end;
FSet.Add(num);
num := random(MaxInt);
end;
Result := num;
end;
function TRandomIntEnumerator.MoveNext: Boolean;
begin
Result := FIndex < FMax;
Inc(FIndex);
end;
var
i:int64;
begin
for i in TRandomInt.Create(100000) do
begin
writeln(IntToStr(i));
end;
ReadLn;
end.
Nota que queda funcionando sin necesidad de decidir si usas array u otra cosa, y sin complicar con variables la claridad del codigo. Cada vez que uses
for i in TRandomInt se encargara clase solita de manejar sus datos y reglas internas.
El chequeo de si el numero ya fue usado antes se puede eliminar y la clase queda totalmente eficiente ya que no consume casi nada de memoria, pero veo que te enrueda mucho y el paso de quitar los duplicados quedaria complicado ya que tocaria reajustar las matrices.
Asi, es totalmente encapsulado!
---
Ya teniendo el tema resuelto de los numeros la parte visual deberia resultarte trivial y con los que te han mostrado suficiente...
P.D: Hay mas cosas que se pueden optimizar (como cambiar el hashset por un bitset) pero creo que es suficiente asi...