2

I am using delphi 7 and im trying to shuffle a set of numbers from one list box to another.

02H,02D,02S,02C,03H,03D,03S,03C,10H,10D,10S,10C,11H,11D,11S,11C,20H,20D,20S,20C,30H,30D,30S,30C.

but for some reason, 30C always seems to be last, when i random 0,2 or 0,1 it seems to always give me 0.

procedure TMainForm.btShuffleClick(Sender: TObject);
var I: integer;
begin
    lstShufd.Clear;
    while lstNew.Count <> 0 do
        begin
             Randomize; 
             I:=RandomRange(0,lstNew.Count-1);
             lstShufd.Items.Add(lstNew.Items.Strings[I]);
             lstNew.Items.Delete(I);
        end;
end;
waynemodz
  • 118
  • 9
  • 4
    Why are you calling `Randomize` in every loop? It sets the random seed from the clock, so you are probably getting the same value several times. Use it only once in your program. – some Dec 27 '13 at 11:08
  • 1
    For a quick summary of shuffling methods, see also [`Randomize StringList`](http://stackoverflow.com/a/14006825/576719). – LU RD Dec 27 '13 at 11:41
  • I wonder why the so many beginners are calling `Randomize` in the loop... – Free Consulting Dec 27 '13 at 12:28
  • 1
    @FreeConsulting To get a more random number! Another way is to call random multiple times to get a more random value. But it doesn't work that way. – some Dec 27 '13 at 12:53
  • @LURD sorry, didn't realized this :o) – Sir Rufo Dec 27 '13 at 14:48
  • HI all, ive tried randomize outside and inside the loop, it still refuses to shuffle the last number. should i just place the the last number randomly? – waynemodz Dec 29 '13 at 21:09

1 Answers1

6

You have two errors:

  1. You must not call Randomize repeatedly in the way you do in the question. Doing so will destroy the distributional properties of your random sequence. Typical usage is to call Randomize once at the start of the program.
  2. RandomRange returns a value I in the range AFrom <= I < ATo. So you are passing the wrong parameters. Use RandomRange(0, lstNew.Count) or even just Random(lstNew.Count).

The second of these errors explains the behaviour that you observe. In your code, by calling RandomRange(0, lstNew.Count-1) you get a value in the range 0 <= I < lstNew.Count-1 and so the final item in lstNew, that is the item with index lstNew.Count-1 cannot be chosen until the final iteration of the loop.

The documentation for RandomRange says:

function RandomRange(const AFrom, ATo: Integer): Integer;

Description

Returns a random integer from a specified range.

RandomRange returns a random integer from the range that extends between AFrom and ATo (non-inclusive). RandomRange can handle negative ranges (where AFrom is greater than ATo).

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Found a [better documentation](http://docwiki.embarcadero.com/Libraries/XE5/en/System.Math.RandomRange) "RandomRange returns a random integer from the range that extends between AFrom and ATo (non-inclusive)" – some Dec 27 '13 at 11:26
  • 3
    @some You should always read the actual documentation rather than DelphiBasics which is low quality. – David Heffernan Dec 27 '13 at 11:37
  • Well, I guess that it is the equivalent to w3shools, but it was the first result on Google. To my defense it was almost a decade ago that I used Delphi, when it was still owned by Borland. Where is the official documentation now? – some Dec 27 '13 at 12:03
  • 1
    @some, you've linked the official documentation in your comment. It is for Delphi XE5 though, but since there is no official Delphi 7 online help, it is one of "the best" you can link to. As far as I remember, there was (and maybe still is) the online help for Delphi 2009 as the oldest Delphi version online help. – TLama Dec 27 '13 at 12:23
  • @TLama When I link to online docs, I remove the version from the URL. That way the link resolves to the latest version, and is not tied forever to XE5. – David Heffernan Dec 28 '13 at 10:32