Delphi 生成不重复随机数类
作者:互联网
原文链接:http://www.cnblogs.com/kernelj/archive/2010/01/27/1657296.html
interface
uses Windows,Classes;
type
TRandomEngine = class(TObject)
private
FSelected : TBits;
FArrSize,FNumbersUsed : longint;
FMinNumber,FMaxNumber : longint;
FUnique : boolean;
procedure SizeSelArray;
procedure SetFMinNumber(NewValue : longint);
procedure SetFMaxNumber(NewValue : longint);
function GetFNumbersFree : longint;
public
constructor Create;
destructor Destroy; override;
procedure Reset;
function GetRandom : longint;
function IsUsed(Index : longint) : boolean;
property MinNumber : longint read FMinNumber write SetFMinNumber;
property MaxNumber : longint read FMinNumber write SetFMaxNumber;
property Unique : boolean read FUnique write FUnique;
property NumbersUsed : longint read FNumbersUsed;
property NumbersTotal : longint read FArrSize;
property NumbersFree : longint read GetFNumbersFree;
end;
// ===================================
// 创建和释放对象
// ===================================
constructor TRandomEngine.Create;
begin
FSelected := TBits.Create;
FNumbersUsed := 0;
FMinNumber := 0;
FMaxNumber := 0;
FArrSize := 0;
FUnique := false;
Randomize;
end;
destructor TRandomEngine.Destroy;
begin
inherited Destroy;
FSelected.Free;
end;
// ===========================
// Get/Set方法
// ===========================
procedure TRandomEngine.SetFMinNumber(NewValue : longint);
begin
if (NewValue <> FMinNumber) then
begin
FMinNumber := NewValue;
if FMinNumber > FMaxNumber then FMaxNumber := FMinNumber;
SizeSelArray;
end;
end;
procedure TRandomEngine.SetFMaxNumber(NewValue : longint);
begin
if (NewValue <> FMaxNumber) then
begin
FMaxNumber := NewValue;
if FMaxNumber < FMinNumber then FMinNumber := FMaxNumber;
SizeSelArray;
end;
end;
function TRandomEngine.GetFNumbersFree : longint;
begin
Result := FArrSize - FNumbersUsed;
end;
// =======================================
// 调整布尔数组(FSelected)的大小
// =======================================
procedure TRandomEngine.SizeSelArray;
var i : longint;
begin
FArrSize := FMaxNumber - FMinNumber + 1;
if FArrSize > 0 then
begin
FSelected.Size := FArrSize;
for i := 0 to FArrSize - 1 do FSelected[i] := false;
end;
FNumbersUsed := 0;
end;
// =======================================
// 重置可用,已用,未用数字。
// 为IsUsed()重置Fselected数组,
// 使之为false。
// =======================================
procedure TRandomEngine.Reset;
begin
SizeSelArray;
end;
// ===================================================
// 如果已设定Unique,数字已使用,
// 则返回true/false。
// ===================================================
function TRandomEngine.IsUsed(Index : longint) : boolean;
var Retvar : boolean;
begin
if (Index < FMinNumber) or (Index > FMaxNumber) then
Retvar := false
else
RetVar := FSelected[Index - FMinNumber];
Result := RetVar;
end;
// ===================================================
// 根据最小和最大值返回随机数。如果
// 已设定Unique,则根据Fselected数
// 组生成(即保证数字未用过)。
// ===================================================
function TRandomEngine.GetRandom : longint;
var V : longint;
NumSelected : boolean;
begin
if FUnique and (FNumbersUsed = FArrSize) then
V := 0
else
begin
repeat
V := Random(FMaxNumber - FMinNumber + 1) + FMinNumber;
if not FUnique then
NumSelected := true
else begin
if FSelected[V - FMinNumber] then
NumSelected := false
else begin
NumSelected := true;
FSelected[V - FMinNumber] := true;
inc(FNumbersUsed);
end;
end;
until NumSelected;
end;
Result := V;
end;
end.
本类可用来产生从MinNumber到MaxNumber之间的随机数,只要设定Unique,每个数字就只使用一次。此外还可以检查数字是否使用过。一个动态的Tbit数组用来保证数字只会返回一次,并看是否所有的数字都使用过。
unit REngine;
interface
uses Windows,Classes;
type
TRandomEngine = class(TObject)
private
FSelected : TBits;
FArrSize,FNumbersUsed : longint;
FMinNumber,FMaxNumber : longint;
FUnique : boolean;
procedure SizeSelArray;
procedure SetFMinNumber(NewValue : longint);
procedure SetFMaxNumber(NewValue : longint);
function GetFNumbersFree : longint;
public
constructor Create;
destructor Destroy; override;
procedure Reset;
function GetRandom : longint;
function IsUsed(Index : longint) : boolean;
property MinNumber : longint read FMinNumber write SetFMinNumber;
property MaxNumber : longint read FMinNumber write SetFMaxNumber;
property Unique : boolean read FUnique write FUnique;
property NumbersUsed : longint read FNumbersUsed;
property NumbersTotal : longint read FArrSize;
property NumbersFree : longint read GetFNumbersFree;
end;
// ===================================
// 创建和释放对象
// ===================================
constructor TRandomEngine.Create;
begin
FSelected := TBits.Create;
FNumbersUsed := 0;
FMinNumber := 0;
FMaxNumber := 0;
FArrSize := 0;
FUnique := false;
Randomize;
end;
destructor TRandomEngine.Destroy;
begin
inherited Destroy;
FSelected.Free;
end;
// ===========================
// Get/Set方法
// ===========================
procedure TRandomEngine.SetFMinNumber(NewValue : longint);
begin
if (NewValue <> FMinNumber) then
begin
FMinNumber := NewValue;
if FMinNumber > FMaxNumber then FMaxNumber := FMinNumber;
SizeSelArray;
end;
end;
procedure TRandomEngine.SetFMaxNumber(NewValue : longint);
begin
if (NewValue <> FMaxNumber) then
begin
FMaxNumber := NewValue;
if FMaxNumber < FMinNumber then FMinNumber := FMaxNumber;
SizeSelArray;
end;
end;
function TRandomEngine.GetFNumbersFree : longint;
begin
Result := FArrSize - FNumbersUsed;
end;
// =======================================
// 调整布尔数组(FSelected)的大小
// =======================================
procedure TRandomEngine.SizeSelArray;
var i : longint;
begin
FArrSize := FMaxNumber - FMinNumber + 1;
if FArrSize > 0 then
begin
FSelected.Size := FArrSize;
for i := 0 to FArrSize - 1 do FSelected[i] := false;
end;
FNumbersUsed := 0;
end;
// =======================================
// 重置可用,已用,未用数字。
// 为IsUsed()重置Fselected数组,
// 使之为false。
// =======================================
procedure TRandomEngine.Reset;
begin
SizeSelArray;
end;
// ===================================================
// 如果已设定Unique,数字已使用,
// 则返回true/false。
// ===================================================
function TRandomEngine.IsUsed(Index : longint) : boolean;
var Retvar : boolean;
begin
if (Index < FMinNumber) or (Index > FMaxNumber) then
Retvar := false
else
RetVar := FSelected[Index - FMinNumber];
Result := RetVar;
end;
// ===================================================
// 根据最小和最大值返回随机数。如果
// 已设定Unique,则根据Fselected数
// 组生成(即保证数字未用过)。
// ===================================================
function TRandomEngine.GetRandom : longint;
var V : longint;
NumSelected : boolean;
begin
if FUnique and (FNumbersUsed = FArrSize) then
V := 0
else
begin
repeat
V := Random(FMaxNumber - FMinNumber + 1) + FMinNumber;
if not FUnique then
NumSelected := true
else begin
if FSelected[V - FMinNumber] then
NumSelected := false
else begin
NumSelected := true;
FSelected[V - FMinNumber] := true;
inc(FNumbersUsed);
end;
end;
until NumSelected;
end;
Result := V;
end;
end.
转载于:https://www.cnblogs.com/kernelj/archive/2010/01/27/1657296.html
标签:begin,end,重复,Delphi,TRandomEngine,longint,随机数,FMinNumber,FMaxNumber 来源: https://blog.csdn.net/weixin_30724853/article/details/96618401