That does sort, but not efficient. RTL functions need to be correct in every sense. Even if it looks simple, there needs to be a solid foundation in theory.

I will describe an example why that should be the case:

A card game with 52 cards needs a period of 2^233 for the random generator to have an equidistributed chance on every permutation possible.

That means that the very simple but extremely fast LCG as used by Delphi (2^64) is not very useful, because it will generate distinct patterns, but FPC's Mersenne twister PRNG satisfies this requirement (a period over 2^6000) but is slower. So even the choice of PRNG has influence on such a simple piece of code as a Sattolo cycle. Taken that into account I have settled on this one, but note the comments of the previous one are still valid:

generic procedure shuffle<T>(var Values:array of T);

var

i,j:integer;

temp:T;

begin

for i := High(Values) downto 1 do

begin

j := Random(i);

temp:=Values[i];

Values[i]:=Values[j];

Values[j]:=temp;

end;

end;

This removes the speed penalty for randomrange that avk made me aware of and still satisfies both Sattolo and the PRNG limitation as described above.

It has (N-1)! ( <- permutation sign, not exclamation mark) and a single cycle per iteration. So for N=20 it has 19 cycles, which is optimal. As side effect, none of the members will end up in it starting place, what your code actually does.

If you are interested I wrote an elaborate wiki article about the subject in general, complete with chart.