Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > Lazarus, FreePascal, Kylix, etc.
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

 
 
Herramientas Buscar en Tema Desplegado
  #12  
Antiguo 09-05-2018
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
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
  { you can add units after this };

type
  TCheckDuplicate = specialize TFPGMap; // Para verificar que el numero no este repetido
  TRandomInt = class; // La clase "externa" que usaras
  TRandomIntEnumerator = class // la clase que se encarga de generar los numeros, usando un enumerador
  private
    FMax: int64; // Cuantos numeros por generar?
    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;
{ TRandomInt }

constructor TRandomInt.Create(max: int64);
begin
  inherited Create;
  FMax := max;
end;

function TRandomInt.GetEnumerator: TRandomIntEnumerator;
begin
  Result := TRandomIntEnumerator.Create(Self, FMax);
end;

{ TRandomIntEnumerator }

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); // O colocas el maximo posible
  while True do
  begin
       //Verifico que no se ha generado antes...
       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;

// Como se usa:
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...
__________________
El malabarista.

Última edición por mamcx fecha: 09-05-2018 a las 23:11:35.
Responder Con Cita
 



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
sumando valores de un listview danielmj Varios 28 14-11-2014 21:52:30
VALORES FANTASMAS FIREBIRD 2.1 valores Grandes ASAPLTDA Firebird e Interbase 17 02-12-2012 12:09:02
Rellenar con 0.... buitrago Varios 6 17-11-2011 20:02:53
¿Cómo insertar una imágen en un lisbox o un memo? Acuarius3000 Gráficos 3 27-06-2005 08:44:53
arastrar archivos a un lisbox gulder C++ Builder 3 05-05-2005 13:31:50


La franja horaria es GMT +2. Ahora son las 23:56:21.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi