Einzelnen Beitrag anzeigen

Karvus

Registriert seit: 26. Aug 2013
2 Beiträge
 
Delphi XE4 Starter
 
#1

Exception Fehler beim neuem Zeichnen

  Alt 27. Aug 2013, 10:12
Delphi-Version: XE2
Hallo Delphi-Praxis Gemeinde!

Ich weiß nicht wie das bei euch üblich ist, aber da das mein erster Post ist: Moin ich bin der Karvus und werde euch demnächst öfter mit Fragen nerven weil ich im Zuge meiner Ausbildung aktuell Delphi lerne

Nun zu meinem Problem bzw. erstmal zum Background:
Ich versuche aktuell als "Fingerübung" ein Vier Gewinnt spiel nach diesem Tutorial zu programmieren. Aktuell bin ich dabei die "Spielsteine" durch einen klick ins Feld zu bekommen (im Tutorial übrigens hier falls sich unbedingt wer einlesen will ). Das mache ich mit dem MouseDown Ereignis der Paintbox. Soweit alles klar und von mir denke ich auch verstanden.
Jetzt zum Problem:
Wenn ich meinen Code compilieren will funktioniert auch alles ganz super. Bis mein Resize Ereignis der Form aufgerufen wird, ich also das Fenster bewege, in dem wiederum nur die Methode GroessenEinstellungenAnpassen
Delphi-Quellcode:
procedure TForm1.GroessenEinstellungenAnpassen;
begin
  FGrafik.Width := pbxAnzeigeflaeche.Width; //Größe verstellen
  FGrafik.Height := pbxAnzeigeflaeche.Height;
  FLinks := FGrafik.Width div 2 - FSpielfeldBreite div 2 * FFelderbreite;
  FUnten := FGrafik.Height div 2 + FSpielfeldHoehe div 2 * Ffelderbreite;

  SymbolErstellen(FFelderbreite-1, sSpieler1);
  SymbolErstellen(FFelderbreite-1, sSpieler2);
  SymbolErstellen(1, sLeer);
end;
aufgerufen wird (weswegen der Satz im nachhinein garnicht so nötig ist ...). Da kommt der Fehler

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project1.exe ist eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x005b41d8: read of address 0x00fcc1e4' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------


Wenn ich jetzt aber "anhalte" erscheint mein Fehler aber in Zeile 124
Delphi-Quellcode:
FGrafik.Canvas.Draw(FLinks + i* FFelderbreite+1,
      FUnten - (j+1) * FFelderbreite + 1, FSpielerBmp[FSpielfeld[i,j]]);
und das ist in einer ganz anderen funktion . Die beiden haben doch nichts miteinander zu tun, außer dass sie bei FGrafik verwenden oder?

Hoffe ihr könnt mir helfen.

P.S.:
Wenn starte kommt die manchmal auch direkt aber nicht immer was ich noch weniger versteh.

Hier ist der Code:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TFeldbesetzung = (sLeer, sSpieler1, sSpieler2);
  TForm1 = class(TForm)
    Panel1: TPanel;
    pnlSpieler: TPanel;
    pbxAnzeigeflaeche: TPaintBox;
    btNeu: TButton;
    btLaden: TButton;
    btSpeichern: TButton;
    btEinstellungen: TButton;
    btBeenden: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure pbxAnzeigeflaechePaint(Sender: TObject);
    procedure btNeuClick(Sender: TObject);
    procedure pbxAnzeigeflaecheMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private-Deklarationen }
    FSpielfeld: array [0..6, 0..5] of TFeldBesetzung;
    FGrafik : TBitmap;
    FLinks, FUnten : Integer;
    FSpielfeldBreite,FSpielfeldHoehe, FFelderBreite : Integer;
    FSpielerFarbe: array[TFeldBesetzung] of TColor;
    FSpielerbmp: array[TFeldBesetzung] of TBitmap;
    FSpielerName: array[TFeldBesetzung] of string;
    FAktiverSpieler: TfeldBesetzung;
    Spielaktiv: boolean;

    procedure GitterZeichnen (breite, hoehe, feldbreite: Integer);
    procedure Darstellen;
    procedure GroessenEinstellungenAnpassen;
    procedure SymbolErstellen (breite: Integer; spieler : TFeldBesetzung);
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.btNeuClick(Sender: TObject);
var
i,j : Integer;
begin //Felder als leer deklarieren
  for i := 0 to FSpielfeldBreite - 1 do
    begin
  for j := 0 to FSpielfeldhoehe - 1 do
    FSpielfeld[i,j] := sLeer;
    end;
  Spielaktiv := True;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FGrafik := TBitmap.Create; //Bitmap erstellen
  FSpielfeldbreite :=7;
  FSpielfeldhoehe := 6;
  FFelderBreite := 25;

  FSpielerBmp[sSpieler1] := TBitmap.Create; //3 Bitmaps für jeweilige Spieler und leer im Array
  FSpielerBmp[sSpieler2] := TBitmap.Create;
  FSpielerBmp[sLeer] := Tbitmap.Create;
  FSpielerFarbe[sLeer] := clWhite;
  FSpielerFarbe[sSpieler1] := clGreen;
  FSpielerFarbe[sSpieler2] := clRed;
  FSpielerName[sLeer] := 'Leer';
  FSpielerName[sSpieler1] := 'Spieler 1';
  FSpielerName[sSpieler2] := 'Spieler 2';

  if random(1) =0 then //Zufälliger aktiver Spieler
   FAktiverSpieler := sSpieler1
  else
   FAktiverSpieler := sSpieler2;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
FGrafik.Free;
FSpielerBmp[sSpieler1].Free;
FSpielerBmp[sSpieler2].Free;
FSpielerBmp[sLeer].Free;
end;

procedure TForm1.GroessenEinstellungenAnpassen;
begin
  FGrafik.Width := pbxAnzeigeflaeche.Width; //Größe verstellen
  FGrafik.Height := pbxAnzeigeflaeche.Height;
  FLinks := FGrafik.Width div 2 - FSpielfeldBreite div 2 * FFelderbreite;
  FUnten := FGrafik.Height div 2 + FSpielfeldHoehe div 2 * Ffelderbreite;

  SymbolErstellen(FFelderbreite-1, sSpieler1);
  SymbolErstellen(FFelderbreite-1, sSpieler2);
  SymbolErstellen(1, sLeer);
end;

procedure TForm1.Darstellen;
var
I,j : Integer;
begin
  FGrafik.Canvas.Pen.Color := clBlack; //Weißes Feld zeichnen
  FGrafik.Canvas.Brush.Color := clWhite;
  FGrafik.Canvas.Rectangle(0,0,FGrafik.Width, FGrafik.Height);

  GitterZeichnen(FSpielfeldBreite, FSpielfeldHoehe, FFelderBreite); //Gitter erstellen & auf der Paintbox zeichnen
  pbxAnzeigeflaeche.Canvas.Draw(0,0,FGrafik);

  for I := 0 to FSpielfeldBreite - 1 do
   Begin
      FGrafik.Canvas.Draw(FLinks + i* FFelderbreite+1,
      FUnten - (j+1) * FFelderbreite + 1, FSpielerBmp[FSpielfeld[i,j]]);
   end;

end;

procedure TForm1.pbxAnzeigeflaecheMouseDown(Sender: TObject; //erkennt wo Stein gesetzt werden soll
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
i, spalte, zeile: Integer;
  begin //erkennt Spalte
   spalte := (x - FLinks) div FFelderBreite;
   if (spalte > FSpielfeldbreite-1) or (x < FLinks) then Exit;

   i := 0;
   while FSpielfeld[spalte,i] <> sLeer do //erkennt Zeile
    begin
     Inc(i);
     if i > FSpielfeldHoehe - 1 then Exit;
    end;
   zeile := i;

   FSpielfeld [spalte, zeile] := FAktiverSpieler; //setzt Stein des aktiven Spielers

   if SpielAktiv then //Spieler wechseln
    begin
      if FAktiverSpieler = sSpieler1 then
         FAktiverSpieler := sSpieler2
      else
         FAktiverSpieler := sSpieler1;
    end;

   Darstellen //Grafische Ausgabe des Zuges
end;

procedure TForm1.pbxAnzeigeflaechePaint(Sender: TObject);
begin
Darstellen;
end;

procedure TForm1.SymbolErstellen (breite: Integer; spieler : TFeldBesetzung);
begin
  FSpielerBmp [spieler].Width := breite; //Größe der Kreise einstellen
  FSpielerBmp [spieler].height := breite;

  FSpielerBmp[spieler].Canvas.Pen.Color := clWhite; //Felder leeren
  FSpielerBmp[spieler].Canvas.Brush.Color := clWhite;
  FSpielerBmp[spieler].Canvas.Rectangle(0, 0,breite, breite);

  FSpielerBmp[spieler].Canvas.Pen.Color := FSpielerFarbe[spieler]; //Kreis in Spielerfarbe erstellen
  FSpielerBmp[spieler].Canvas.Brush.Color := FSpielerFarbe[spieler];
  FSpielerBmp[spieler].Canvas.Ellipse(0, 0, breite, breite)

end;

procedure TForm1.FormResize(Sender: TObject);
begin
GroessenEinstellungenAnpassen
end;

procedure TForm1.GitterZeichnen(breite, hoehe, feldbreite: Integer);
var
i : Integer;
begin
  FGrafik.Canvas.Pen.Color := clBlack;
  for i := 0 to hoehe do
    begin
      FGrafik.Canvas.MoveTo(FLinks, Funten - i * feldbreite);
      FGrafik.Canvas.LineTo(FLinks + breite * feldbreite, FUnten - i * feldbreite)
    end;
  for i := 0 to breite do
    begin
      FGrafik.Canvas.MoveTo(FLinks + i*feldbreite, FUnten - hoehe * feldbreite);
      FGrafik.Canvas.LineTo(FLinks + i*feldbreite, FUnten);
    end;
end;


end.
Link zum Crosspost: http://forum.delphi-treff.de/index.p...656#post435656

Geändert von Karvus (27. Aug 2013 um 11:17 Uhr) Grund: Crosspostverlinkung
  Mit Zitat antworten Zitat