ArrayIndex eines anderen Objektes benutzen

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Nugi89
Beiträge: 68
Registriert: Do 26. Feb 2015, 13:46

ArrayIndex eines anderen Objektes benutzen

Beitrag von Nugi89 »

Hallo habe mir ein Snake-Spiel gebastelt und nun ja habe da dass Problem das dass Futter ab und zu auf der Schlange erstellt wird.
Um das Problem zu lösen habe ich bereits versucht auf den Index der Schlange zuzugreifen das gelingt mir aber nicht :oops:

Hier mal der Quelltext der Abfrage:

[code=laz] if (Happen.Haeppchen.x = Snake.FTeile[].x) and (Happen.Haeppchen.y = Snake.FTeile[].y) then
begin
//Abfrage für das Fressen des Futters und wachsen
if (Snake.FTeile[0].x = Happen.Haeppchen.x) and (Snake.FTeile[0].y = Happen.Haeppchen.y) then
begin
fressen;
end
else
begin
Umsetzen;
end;
end;[/code]
ich hoffe mir kann jemand helfen das Problem zu lösen ich hänge gerade ziemlich durch.
Habe bei Snake.FTeile[].x bewusst leer gelassen.

Danke schon mal im Voraus.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von theo »

:?:

Nugi89
Beiträge: 68
Registriert: Do 26. Feb 2015, 13:46

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Nugi89 »

also der index meiner schlange erweitert sich ja pro futter was ich einsammel und ich möchte jetzt den gesamten index des arrays haben damit ich ihn in meiner abfrage benutzen kann.
Oder mal anders gefragt wie kann ich es verhindern, das sich das Futter auf der selben Koordinate wie ein Teil der Schlange befindet?

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Michl »

Du müsstest etwas mehr zu deiner Datenstruktur preis geben, sonst kann dir nicht wirklich erfolgreich geantwortet werden.

Generell könnte man die Abfrage so gestalten (falls die Schlange "SnakeArray" aus einem Array of TPoint besteht):

Code: Alles auswählen

function IsSnakeOnPoint(p: TPoint): Boolean;
var
  aPoint: TPoint;
begin
  Result := false;
  for aPoint in SnakeArray do
    if (p.x = aPoint.x) and (p.y = aPoint.y) then
      Result := true;
end;
oder

Code: Alles auswählen

function IsSnakeOnPoint(p: TPoint): Boolean;
var
  i: Integer;
begin
  Result := false;
  for i := 0 to High(SnakeArray) do
    if (SnakeArray[i].x = p.x) and (SnakeArray[i].y = p.y) then
      Result := true;
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Nugi89
Beiträge: 68
Registriert: Do 26. Feb 2015, 13:46

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Nugi89 »

Bei meiner schlange sind nur die FTeile vom array of TPoint.

Hier ist mal der ganze Code von der Schlange:

[code=laz]TSchlange = class(TObject)
FTeile: array[0..40*30-1] of TPoint;
FAnzahlTeile: Word;
FRichtung: Byte;
FWurdeBewegt: boolean;
FFarbe: TColor;
Richtung: Byte;
AnzahlTeile: Word;
FCanvas: TCanvas;
constructor Create;
function PruefeObTot: boolean;
function LiesTeil(index: Word): TPoint;
function Farbe: TColor;
property Teile[index: Word]: TPoint read LiesTeil;
property Canvas: TCanvas read FCanvas write FCanvas;
procedure Init;
procedure Render;
procedure Update;
procedure WachseUm1;
procedure AendereRichtung(NeueRichtung: integer);
end;

implementation

{ TSchlange }

constructor TSchlange.Create;
begin
FFarbe:= clWhite;
end;

function TSchlange.PruefeObTot: boolean;
var
i: integer;
index: word;
begin
for index:= 1 to FAnzahlTeile do
begin
if (FTeile[0].x = FTeile[index].x) and (FTeile[0].y = FTeile[index].y) then
begin
Result:= true;
Exit;
end;
end;

Result:= false;
end;

function TSchlange.LiesTeil(index: Word): TPoint;
begin
Result:= FTeile[index];
end;

function TSchlange.Farbe: TColor;
begin
Result:= FFarbe;
end;

procedure TSchlange.Init;
begin
FAnzahlTeile:= 2;
FTeile[0]:= Point(3, 3);
FTeile[1]:= Point(2, 3);
FTeile[2]:= Point(1, 3);

FRichtung:= 3;
FWurdeBewegt:= true;
end;

procedure TSchlange.Render;
var
index: word;
Startx, Starty: integer;
Endex, Endey: integer;
begin
FCanvas.Pen.Color:= Self.FFarbe;
FCanvas.Brush.Color:= Self.FFarbe;

for Index:= 0 to FAnzahlTeile do
begin
Startx:= FTeile[index].x * 16;
Starty:= FTeile[index].y * 16;
Endex:= FTeile[index].x * 16 + 16;
Endey:= FTeile[index].y * 16 + 16;
FCanvas.Rectangle(Startx, Starty, Endex, Endey);
end;
end;

procedure TSchlange.Update;
var
index: Word;
begin

//Teile hinterher ziehen
for index:= FAnzahlTeile downto 1 do
begin
FTeile[index]:= FTeile[index - 1];
end;

//Ablauf für das Verlassen des Spielfeldes und Wiedererscheinen auf der gegenüberliegenden Seite
case FRichtung of
0: //Bewegung nach oben
begin
FTeile[0].y:= FTeile[0].y - 1;
if FTeile[0].y < 0 then
begin
FTeile[0].y:= 29;
FWurdeBewegt:= true;
end;
end;

1: //Bewegung nach unten
begin
FTeile[0].y:= FTeile[0].y + 1;
if FTeile[0].y > 29 then
begin
FTeile[0].y:= 0;
FWurdeBewegt:= true;
end;
end;

2: //Bewegung nach links
begin
FTeile[0].x:= FTeile[0].x - 1;
if FTeile[0].x < 0 then
begin
FTeile[0].x:= 39;
FWurdeBewegt:= true;
end;
end;

3: //Bewegung nach rechts
begin
FTeile[0].x:= FTeile[0].x + 1;
if FTeile[0].x > 39 then
begin
FTeile[0].x:= 0;
FWurdeBewegt:= true;
end;
end;
end;
end;

procedure TSchlange.WachseUm1;
begin
FAnzahlTeile:= FAnzahlTeile + 1;
end;

procedure TSchlange.AendereRichtung(NeueRichtung: integer);
begin
case NeueRichtung of
0: //Nach Oben
begin
if not Self.FRichtung = 1 then
begin
Self.FRichtung:= 0;
end;
end;

1: //Nach Unten
begin
if not Self.FRichtung = 0 then
begin
Self.FRichtung:= 1;
end;
end;

2: //Nach Links
begin
if not Self.FRichtung = 3 then
begin
Self.FRichtung:= 2;
end;
end;

3: //Nach Rechts
begin
if not Self.FRichtung = 2 then
begin
Self.FRichtung:= 3;
end;
end;
end;

FRichtung:= NeueRichtung;
FWurdeBewegt:= false;
end;

end.[/code]

Nugi89
Beiträge: 68
Registriert: Do 26. Feb 2015, 13:46

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Nugi89 »

sorry aber weis nicht wie man hier den quelltext vernünftig einfügt :( :oops:

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von af0815 »

Nugi89 hat geschrieben:sorry aber weis nicht wie man hier den quelltext vernünftig einfügt :( :oops:

Sollte so passen. Wenn ich es zu mir hereinkopiere wird es richtig angezeigt.

Ev. im persönlichen Bereich/Einstellungen/ BBCode/Nachrichten erstellen BBCode deaktiviert bzw. unten in der Eingabemaske vom Forum unter Optionen BBCode ausschalten aktiviert ?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Michl »

Nugi89 hat geschrieben:Bei meiner schlange sind nur die FTeile vom array of TPoint.
Dann erstelle doch einfach eine Funktion (z.B. in Klasse TSchlange), die prüft, ob ein Punkt gerade auf einer Schlange liegt (siehe oben). z.B. (ungetested):

Code: Alles auswählen

function TSchlange.IsOnPoint(p: TPoint): Boolean;
var
  aPoint: TPoint;
begin
  Result := false;
  for aPoint in FTeile do
    if (p.x = aPoint.x) and (p.y = aPoint.y) then Result := true;
end;

Diese kannst du von extern aufrufen z.B.

Code: Alles auswählen

var
  Schlange: TSchlange;
...
  repeat
    FutterPunkt.x := Random(40);
    FutterPunkt.y := Random(30);
  until not Schlange.IsOnPoint(FutterPunkt);

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Nugi89
Beiträge: 68
Registriert: Do 26. Feb 2015, 13:46

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Nugi89 »

danke also soweit klappt es ja schonmal, bis auf das dass Futter jetzt nur am rum springen ist. ^^

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Michl »

Nugi89 hat geschrieben:danke also soweit klappt es ja schonmal, bis auf das dass Futter jetzt nur am rum springen ist. ^^
:) Das passiert, wenn man einfach was abtippt... Sorry...

Als kleiner Hinweis:

Code: Alles auswählen

procedure TSchlange.Init;
begin
FAnzahlTeile:= 2;
FTeile[0]:= Point(3, 3);
FTeile[1]:= Point(2, 3);
FTeile[2]:= Point(1, 3);
...

Was ist mit den restlichen Einträgen des Arrays FTeile? Evtl. schaust du dir noch die andere Funktion weiter oben an, evtl. kannst du diese ja mit FAnzahlTeile kombinieren?!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Nugi89
Beiträge: 68
Registriert: Do 26. Feb 2015, 13:46

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Nugi89 »

Mit FTeile aus der procedure TSchlange.Init lege ich ja nur den Startpunkt der 3 Teile der Schlange fest und deren Anfangrichtung.Wüsste jetzt auch gerade nicht wie ich diese mit FAnzahlTeile kombinieren sollte?

aber ich weis worauf du hinaus willst. Hab da gerade voll ein Brett vorm Kopf. :oops:

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Michl »

Da ich das Prog nicht vorliegen habe, versuche ich dir mal den theoretischen Fehler zu erklären.

Mit "aPoint in FTeile" geht die Schleife alle Elemente von FTeile durch. FTeile hat eine Größe von 1200 (30 x 40) Elementen. Wenn du aber nur die ersten drei Elemente initialisert hast, was passiert dann, wenn aPoint auf dem vierten Element ankommt?!

Um so einen Fehler zu finden kann man auch wunderbar den Debugger einsetzen (Breakpoint setzen, mit F7 durch den Code steppen und immer dabei die Variableninhalte anschauen).

Wie auch immer, die Schlange soll sich ja in der Länge verändern. Das realisierst du sicherlich mit der Erhöhung von FAnzahlTeile?! Damit kannst du jetzt auch immer nur die entsprechende Zahl von FTeile nach einer Übereinstimmung durchforsten. So könnte es aussehen:

Code: Alles auswählen

function TSchlange.IsOnPoint(p: TPoint): Boolean;
var
  i: Integer;
begin
  Result := false;
  for i := 0 to FAnzahlTeile - 1 do
    if (FTeile.x = p.x) and (FTeile.y = p.y) then Result := true;
end;
wobei FAnzahlTeile bei 3 Schlangenelementen auch 3 und nicht 2 sein müsste...

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Nugi89
Beiträge: 68
Registriert: Do 26. Feb 2015, 13:46

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Nugi89 »

Werde es mal probieren so und mal mit dem Debugger.
Werde morgen antworten.

Nugi89
Beiträge: 68
Registriert: Do 26. Feb 2015, 13:46

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Nugi89 »

Habe das ganze jetzt mal durchtesten können. der Fresspunkt springt immer noch wie wild hin und her. Mit dem Debugger bin ich den Abschnitt mal durchgegangen und mir scheint als ob die Fresspunkte (p.y und p.x) irgendwie gleich gesetzt werden, obwohl sie aber random erzeugt werden.

Hab das vom Code her so gemacht:
Die eigentliche Abfrage:

Code: Alles auswählen

if(Snake.FTeile[0].x = Happen.Haeppchen.x) and (Snake.FTeile[0].y = Happen.Haeppchen.y) then
begin
  fressen;
end
else
begin
  repeat
    Happen.Haeppchen.x:= Random(35) +2;
    Happen.Haeppchen.y:= Random(25) +2;
  until not Snake.IsOnPoint(Happen.Haeppchen);
end;


Hier die Funktion in der Klasse Schlange:

Code: Alles auswählen

function TSchlange.IsOnPoint(p: TPoint): boolean;
var
  i: integer;
  index: Word;
begin
  Result:= false;
  for i:= 0 to FAnzahlTeile - 1 then
  begin
    if (FTeile[index].x = p.x) and (FTeile[index].y = p.y) then
    begin
      Result:= true;
    end;
  end;
end;


Ich habe keinen Plan wieso das Futter rum springt. :oops:

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: ArrayIndex eines anderen Objektes benutzen

Beitrag von Michl »

Ich habe keine Ahnung, in welcher Methode der obere gepostete Code zum Einsatz kommt und kann dir dazu nichts sagen.

Im zweiten geposteten Code ist aber ein Hund begraben. Ich dokumentiere den Code einmal.

Code: Alles auswählen

function TSchlange.IsOnPoint(p: TPoint): boolean;
var
  i: integer;
  index: Word;  //ein Index - Variable mit dem Inhalt 0 oder sonstiger Zahl
begin
  Result:= false;
  for i:= 0 to FAnzahlTeile - 1 then  //<- das kann nicht kompiliert werden, statt "then" hätte dort ein "do" hin gehört 
  begin
    if (FTeile[index].x = p.x) and (FTeile[index].y = p.y) then  //hier hat der Index immer noch den undefinierten Inhalt...
    begin
      Result:= true;
    end;
  end;
end;

Irgenwie hatte ich da ein "[i]" in dem geposteten Code vergessen (das kommt davon, wenn man den Code nicht testet :roll: )

Besser daher so:

Code: Alles auswählen

function TSchlange.IsOnPoint(p: TPoint): boolean;
var
  index: Word;
begin
  Result := false;
  for index := 0 to FAnzahlTeile - 1 do
  begin
    if (FTeile[index].x = p.x) and (FTeile[index].y = p.y) then
    begin
      Result := true;
    end;
  end;
end;

PS: evtl. ist es besser das Projekt (ohne Exe) in ein Zip zu packen und hier anzuhängen, dann könnte man den Code tatsächlich auch testen.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Antworten