2

私は TStack を使用して、プログラムに単純な元に戻す/やり直し機能を実装しようとしています。この背後にある考え方は、アクションが実行されると、プログラムの現在の状態が保存される、つまりスタックにプッシュされるということです。ユーザーが [元に戻す] をクリックすると、プログラムの最後の状態が再読み込みされます。つまり、スタックからポップされます。

この考え方の欠点は、スタックが永遠に成長し続けることができないことです。つまり、容量値に達すると、新しいアイテムが一番上にプッシュされるため、最も古いアイテム (スタックの一番下にあるアイテム) を削除する必要があります。

Delphi の TStack オブジェクトには、この「クリーンアップ」を自動的に実行すると想定した Capacity プロパティが含まれていますが、スタックをオーバーロードすると (たとえば、11 個のアイテムを容量 10 のアイテムにプッシュすると)、より多くのアイテムに対応するために容量が更新されます。

この場合、TStack をより効果的に使用する方法について誰かアドバイスをもらえますか? 別の方法として配列構造を使用する方法があることは理解していますが、スタックを使用することの将来の容易さが気に入っています。

よろしく

4

1 に答える 1

3

実際にTStackは、動的配列によって電力が供給されます。
本当に望むなら、この事実を悪用して、スタックにアイテムを一番下から削除させることができますが、スタックと戦うことになります。

循環リストを使用する方が良いと思います。

シンプルなデザインは、このように機能する可能性があります。

type
  TCircularList<T> = class(TObject);
  private
    FStorage: TList<T>;
    FCapacity: cardinal;  //duplication for performance reasons
    FCurrentIndex: cardinal;
  protected
    function GetItem(index: cardinal): T;
    procedure SetItem(index: cardinal; const Value: T);
  public
    constructor Create(Size: cardinal = 10);
    destructor Destroy; override;
    procedure Add(const Item: T);
    property Items[index: cardinal]: T read GetItem write SetItem; default;
  end;

constructor TCircularList<T>.Create(Size: cardinal = 10);
begin
  inherited Create;
  Assert(Size >= 2);
  FStorage:= TList<T>.Create;
  FCapacity:= Size;
  FStorage.Capacity:= Size;
end;

destructor TCircularList<T>.Destroy;
begin
  FStorage.Free;
  inherited;
end;

procedure TCircularList<T>.Add(const Item: T);
begin
  FCurrentIndex:= (FCurrentIndex + 1) mod FCapacity;
  FStorage[FCurrentIndex]:= Item;
end;

function TCircularList<T>.GetItem(index: cardinal): T;
var
  cIndex: cardinal;
begin
  cIndex:= Index mod FCapacity;
  Result:= FStorage[index]; 
end;

procedure TCircularList<T>.SetItem(index: cardinal; const Value: T);
var
  cIndex: cardinal;
begin
  cIndex:= index mod FCapacity;
  FStorage[index]:= Value;
end;

明らかに、last および delete メソッドのようないくつかのメソッドが必要になりますが、それはあなたに任せます。ここから外挿できるはずです。

ユーザビリティに関するコメント
UX の観点から言うと、元に戻す/やり直し機能のアイデアは最低だと思います。
スナップショットのリストを持っていないのはなぜですか。ディスクに多数のバックアップ ファイルを保存した場合と同じように、時間を前後に移動できます。
元に戻す機能を使用するには、最後の x ステップで何を行ったかを正確に記憶する必要がありますが、これはあまりうまくスケールしません。
また、制限が必要な理由もわかりません。メモリ/ディスク容量が許す限り元に戻す/スナップショットを許可しないのはなぜですか?

于 2016-09-07T18:59:39.043 に答える