【问题标题】:How to select five random non-repeating buttons and copy them to panel1?如何随机选择五个不重复的按钮并将它们复制到panel1?
【发布时间】:2019-10-26 15:00:50
【问题描述】:

我有 20 个在程序启动时自动创建的按钮。如何随机选择五个不重复的按钮并复制到 Panel1 组件中?

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1:TForm1;
  but:array[1..9] of TButton;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
  for i := 1 to 20 do
  begin
    but[i] := TButton.Create(Form1);
    but[i].Parent := Form1;
    but[i].Caption := IntToStr(i);
    but[i].Font.Size := 26;
    but[i].Width := 50;
    but[i].Height := 50;
    but[i].Left := 50 + Round(i mod 3)*but[i].Width;
    but[i].Top := 50 + Round(i / 3)*but[i].Height;
  end;
end;

end.

【问题讨论】:

  • 我建议你查看 Delphi-7 帮助,首先是算术运算符 divmod,然后是 divmod() 过程。您可以省略您现在拥有的 Round() 函数。然后还要考虑对 left 和 top 属性的计算公式进行一些小改动,以改进按钮的布局。

标签: arrays delphi delphi-7


【解决方案1】:

算法是这样的:

  1. 保持对数组中按钮的引用。
  2. 对数组执行统一的随机播放,例如使用Fisher-Yates 随机播放。
  3. 从数组中选择前 5 个项目。

如果您愿意,可以通过在其循环的 5 次迭代后中断随机播放来优化这一点,因为此时已经选择了前 5 个项目。但是,对于这么小的阵列,这可能不是必需的。

Fisher-Yates 的实现有很多,但要注意很大一部分实现不正确!正确的实现也比比皆是,例如这里https://stackoverflow.com/a/20361298/505088

你可以做的比使用 spring4d 库来完成这个任务更糟糕。

就复制按钮而言,创建新按钮并复制您需要的属性。将这项工作想象为实际选择 1 到 20 之间的 5 个随机数字,然后创建 5 个以这些数字为标题的按钮可能更容易。同样,这只是数字的洗牌。

如果您想将 20 个项目放入一个数组中,您需要确保该数组足够大。您的数组可以容纳 9 个项目,但您尝试放入 20 个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 2017-12-15
    • 2018-03-26
    • 2012-11-14
    相关资源
    最近更新 更多