0

これは、オブジェクトのディープ コピーまたはクローン作成に関する問題ではありません。すでに何百万ものオブジェクトが存在するためです。最初はそれが自分で探していたものであり、それが私の唯一の選択肢である場合は、おそらくそれに頼るだろうという事実にもかかわらずです。しかし、このような単純なことには不必要に複雑すぎるようです。

私はいくつかの C++ コードを Delphi に翻訳してきました。基本的に、これに従って SDL を使用して Tetris をあからさまにコピーしています。SDLに関しては学習経験でしたが、今ではDelphiのような方法でもあります. 完全に翻訳できないコードを含む特定のページにリンクしています。ゲームは意図したとおりに動作しますが、現在落下しているブロックを切り替えて、その正方形を下にある他のブロックに追加し、次のブロックを現在落下しているブロックとして設定する必要があるポイントが来ます。

コピーしすぎない私のコードの一部を次に示します: TSingleSquareTBlockおよびChangeFocusBlock手順。

TSingleSquare = class
  private
    S_TextureSurf: pSDL_SURFACE;
    S_BlockType: TBlockType;
    S_CenterX, S_CenterY: integer;
  public
    constructor Create(CX, CY: integer; T: pSDL_SURFACE; BT: TBlockType);
    destructor Destroy; override;
    procedure Draw(W: pSDL_SURFACE);
    procedure Move(D: TDirection);
    function GetCenterX: integer;
    function GetCenterY: integer;
    procedure SetCenterX(lX: integer);
    procedure SetCenterY(lY: integer);
  end;

Ttmp_ar = array of integer;
TSquaresArray = array of TSingleSquare;

TBlock = class
  private
    B_CenterX, B_CenterY: integer;
    B_BlockType: TBlockType;
    B_SquaresArray: TSquaresArray;
    B_TextureSurf: pSDL_SURFACE;
  public
    constructor Create(CX, CY: integer; TS: pSDL_SURFACE; BT: TBlockType);
    destructor Destroy; override;
    procedure SetupSquares(SX, SY: integer);
    procedure Draw(W: pSDL_SURFACE);
    procedure Move(D: TDirection);
    procedure Rotate;
    function GetRotatedSquares: Ttmp_ar;
    function GetSquaresArray: TSquaresArray;
    function GetBlockType: TBlockType;
  end;

procedure ChangeFocusBlock;
var
  Square_ar: TSquaresArray;
  i: integer;
begin
  Square_ar := g_FocusBlock.GetSquaresArray
  SetLength(g_OldSquares, (Length(g_OldSquares) + Length(Square_ar)));
  for i := Low(Square_ar) to High(Square_ar) do
    begin
      g_OldSquares[i+Length(g_OldSquares)-Length(Square_ar)] := Square_ar[i];
      Square_ar[i] := nil;
    end;
  g_FocusBlock := nil;
  g_FocusBlock := g_NextBlock;
  g_NextBlock := nil;
  g_FocusBlock.SetupSquares(BLOCK_START_X, BLOCK_START_Y);
  g_NextBlock := TBlock.Create(NEXT_BLOCK_CIRCLE_X, NEXT_BLOCK_CIRCLE_Y, GameBitmap, TBlockType(Random(11)));
end;

私は解放g_FocusBlockしていないことを知っており、ここでメモリリークが発生していますが、そもそも解放する適切な場所が見つからないため、このままにしておくと、メモリリークが私の唯一の問題になります。解決策を探し始めたら、後で反復しようとしたときにお尻に噛みつきましたが、その理由を理解しています。四角形は、解放されるはずg_OldSquaresの四角形をまだ指しています。g_FocusBlockすべてのステップでブレークポイントを追加し、値に何が起こっているかを観察すると、混乱が生じます。解放された後、設定してg_OldSquares新しい次のブロックを作成した後、すべてが順調に見えます。ただし、後で繰り返しますg_FocusBlockg_NextBlockg_OldSquaresメモリ内で再利用されているため、正方形の一部が上書きされていることに気付きましたか? ウォッチリストの値が真であると突然信じられなくなりましたか?

このテキストの壁の要点はg_OldSquares、ウォッチリストを介して検査するときにアドレスが同じであるにもかかわらず、何が起こっているのか、なぜその値が変わらないのかを理解したいということです。

しかし、もっと重要なことは、これを適切に機能させるための適切な行動方針は何でしょうか? オブジェクトを実際に相互に割り当てることができるようにするための使用TPersistentとオーバーライドを認識していますAssign(ただし、それを達成する方法も完全にはわかりません)が、ここでも「リンク」または共有メモリを取り除く必要があります(間違って使用された言葉をお詫びします。私はプログラミングに堪能ではありません) と の間g_OldSquaresg_FocusBlock後者を解放できるようにします。

恥ずかしさを始めましょう。

編集:

これを行うとAccessViolationが発生します

for i := Low(g_OldSquares) to High(g_OldSquares) do
  begin
    row := (g_OldSquares[i].GetCenterY - top) div row_size;
    Inc(squares_in_row[row])
  end;

constructor TBlock.Create(CX, CY: integer; TS: pSDL_Surface; BT: TBlockType);
var
  i: integer;
begin
  B_CenterX := CX;
  B_CenterY := CY;
  B_BlockType := BT;
  B_TextureSurf:= TS;

  case BT of
    SQUARE_BLOCK..REVERSE_S_BLOCK: SetLength(B_SquaresArray, 4);
    STRAIGHT_TRI_BLOCK..BENT_TRI_BLOCK: SetLength(B_SquaresArray, 3);
    TWO_BLOCK: SetLength(B_SquaresArray, 2);
    DOT_BLOCK: SetLength(B_SquaresArray, 1);
  end;

  SetupSquares(CX, CY);
end;

destructor TBlock.Destroy;
var
  i: integer;
begin
  for i := Low(B_SquaresArray) to High(B_SquaresArray) do
    B_SquaresArray[i].Free;
  inherited;
end;
4

1 に答える 1