Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi 6-Dimensionale Baumstruktur - Spielfeld (https://www.delphipraxis.net/77820-6-dimensionale-baumstruktur-spielfeld.html)

Tormentor32 25. Sep 2006 11:30


6-Dimensionale Baumstruktur - Spielfeld
 
Hallo Leute, ich habe ein Problem bei einem kleinen Spiel, welches ich grade Programmiere.

Es gibt ein Spielfeld, welches aus 6-Ecken besteht, jedes Feld hat entweder Farbe 1 oder Farbe 2.
Wenn man auf ein Feld klickt, dann änder sich die Färbe des Feldes, auf das man geklickt hat, und Die Farben aller benachbarten Felder.

Mein Problem ist folgendes:

Beim erstellen der Felder entstehen manche Felder doppelt, denn wenn ich vom Mittelpunkt aus nach oben und dann nach obenrechts gehe, oder erst nach obenrechts und dann nach oben, erhalte ich die gleichen Felder, sie werden also doppelt erstellt.

Über eine Variable wird die Anzahl der Ebenen angegeben, dh. wieviele "Kreise" sich um den Mittelpunkt ziehen => Je mehr Ebenen ich habe, desto mehr überflüssige Felder weden erstellt. Ich habe das Überflüssige Felder erstellen bereits ein wenig eingedömmt durch eine überprüfung, ob der Direkte Nachbar auch ein Feld ist, oder nil ist.

Ich weiß allerdings nicht, wie ich das über Mehrere Ebenen hinkrigen soll, es muss da doch sicher einen bestimmten algorhytmus geben oder?

Gruß richard

Der_Unwissende 25. Sep 2006 11:39

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
Hi und herzlich Willkommen in der DP :dp:

Nur weil ich mir noch nicht sicher bin, ob ich alles verstanden habe, frage ich mal nach:
Du hast ein Spielfeld dass 6 Ecken hat? Oder besteht das Spielfeld aus Feldern, die jeweils 6 eckig sind?

Ein Feld solltest du als den Mittelpunkt betrachten. Jedes Feld hat dann einfach 6 Nachbarn. Diese Nachbar sind allerdings nur Referenzen (Zeiger auf die Nachbarn). So kannst du dann anfangen dein Feld aufzubauen. Wichtig ist, dass diese Regel dann für die äussersten Felder nicht gelten kann.
Um hier jetzt sagen zu können, wie du am einfachsten dein ganzes Feld erzeugst, musst du allerdings angeben, wie die Größe des Feldes festgelegt wird, wie das Spielfeld also aufgebaut ist (wieviele Felder, wie angeordnet) und kann man die Größe manuell anpassen oder ist die fest?

Gruß Der Unwissende

[Add]
noch ein wenig nachgedacht, ich denke es jetzt so zu verstehen, du hast ein Sechseck und um dieses sechseck herum hast du sechs weitere, jetzt wächst du nach aussen, oder? Also hast jetzt wieder jedes von diesen sechs Nachbarn.
Jedes solches Feld solltest du einfach in einer Struktur speichern, die sich ihre sechs nachbarn (Referenz/Zeiger) merken kann. Nun fängst du mit einem Element an. Am Anfang gibt es nur dieses Feld, du schaust dir jetzt alle 6 Nachbarn an, ist einer dieser Nachbarn noch unbekannt (= nil), so erzeugst du den Nachbarn und weißt hier beiden Feldern den Zeiger auf den jeweiligen Nachbarn zu. Alle Felder speicherst du dabei in einer Liste, bis du die gewünschte Anzahl von Feldern hast.
Wichtig ist, dass du dir auch immer merkst, welche Felder noch nicht komplett fertig sind (da fehlen dann die Nachbarn).
Ist die gewünschte Anzahl von Elementen erreicht, setzt du hier keine neuen Nachbarn mehr ein.

Hoffe es ist halbwegs klar wie ich das meine
[/ADD]

Tormentor32 25. Sep 2006 12:03

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
Ein Feld sieht folgendermaßen aus:

Delphi-Quellcode:
TFeld = Class(TObject)
    FFarbe: TColor;

    FEbene: integer;

    FIdentNr: string;
    FPosition: TPoint;

    Image: Timage;

    FFelder: Array[1..6] of TFeld;
    FParent: TFeld;

    FIndex: integer;
    procedure Initialisiere(Ebene,Nummer: integer; const EbeneMax: integer; Parent: TFeld;Position: TPoint);
end;
Jedes feld hat wie du gesagt hast 6 Nachbarn. Das erste Feld ist in der Mitte auf der Ebene 0.
in der Prozedur "Initialsiere" wird 1 Feld erstellt, und anschließend von jedem Nachbar die Prozedeur "Initialsiere" erneut rekursiv aufgerufen und die Ebene erhöht, bis sie den gewünschten Wert erreicht hat.

Am Anfang hatte ich noch gar keine Überprüfung, das heißt es wurden 6^Ebenen Felder erstellt.

Da ich noch nicht viel mit Rekursion zu tun hatte, weiß ich nicht, wie ich auf ein bestimmtes feld zugreifen kann. Daraus folgt, dass ich schlecht überprüfen kann, ob zwei verschiedene Wege zum selben Feld führen, und somit das Feld doppelt erstellt wird.

Cöster 25. Sep 2006 14:02

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
was ist daran denn jetzt 6-dimensional?

Tormentor32 25. Sep 2006 14:58

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
Zitat:

Zitat von Cöster
was ist daran denn jetzt 6-dimensional?

Jedes Feld zeigt auf 6 weitere Felder des gleichen Typs

Tormentor32 28. Sep 2006 11:30

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
So, ich habe das Konzept verworfen und ein neues gemacht, dabei habe ich aber auch wieder ein Problem :wall:

Ich habe ein Klasse TFeld und drei Unterklassen TMittelFeld, THauptFeld und TKindFeld

Delphi-Quellcode:
  TFeld = class(Tobject)
    FKoordinate: TPunkt;
    FFarbe: integer;
    image: Timage;
    constructor create;
  end;

    TKindFeld = class(TFeld)
      FNextKindFeld: TKindFeld;
      FLetzter: boolean;
      procedure inititialisiere(Ader,Ebene,Index: Integer; Letzter: Boolean);
    end;
    THauptFeld = class(TFeld)
      FKindFeld: TKindFeld;
      FNextHauptFeld: THauptFeld;
      FLetzter: boolean;
      procedure initialisiere(Ader,Ebene: integer; Letzter: Boolean);
    end;

    TMittelFeld = class(TFeld)
      FHauptFelder: array[1..6] of THauptFeld;
      procedure initialisiere;
    end;
Die Prozedur TMittelFeld.initialisiere erstellt ein Feld über create, welches die Mitte darstellt
und anschließend 6 Felder vom Typ THauptFeld über die prozedur THauptFeld.initialisiere, die im array FHauptFelder gespeichert sind.

Das Problem ist, dass die Variable

Mitte: TMittelFeld;

nach der Prozedur

Mitte.initialisiere

wieder auf nil zeigt, nur in der Prozedur selbst kann ich auf sie zufreifen, und wenn die Prozedur fertig ist, und ich darauf zugreifen will, kommt die Fehlermeldung

"Zugriffsverletzung"

da Mitte wieder den Wert "nil" hat.

Wie kriege ich es hin, dass die variable auch nach der initialisierung immer noch den Wert hat, und nicht wieder auf nil zeigt?

vielen dank schonmal

MFG Richard

Khabarakh 28. Sep 2006 12:02

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
Ohne Code kann man dazu weniger als nichts sagen, also stelle ich dir mal mein Konzept vor:

Du hast eine Methode BuildNodes oderwieauchimmer, die das nördlichste bzw. östlichste - je nachdem, wie dein Spielfeld ausgelegt ist - Feld, die zu erzeugende Ebenennummer und die maximale Ebene entgegennimmt. Die Methode wandert nun ausgehend vom nördlichsten Element einmal am Rand herum und erzeugt die nächsten Felder. Dabei werden neu erzeugte Felder sofort mit dem zuvor erzeugten und dem bisherigen Rand verbunden, das letzte Element muss natürlich zusätzlich mit dem zuerst erzeugten verbunden werden. Nun kannst du ganz einfach die Methode mit dem neuen nödlichsten Feld und der inkrementierten Ebenennummer rekursiv aufrufen, die Abbruchbedingung sollte klar sein ;) .
Mit dieser Methode benötigst du keine weitere Liste außer den Referenzen in den Feldern selbst, auch ist eine Klasse für alle Felder vollkommen genügend.

Tormentor32 28. Sep 2006 12:17

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
Hi!

Ich gehe Sternförmig vom Mittelpunkt aus nach außen.

Delphi-Quellcode:
//Mittelpunkt des Spielfeldes
procedure TMittelFeld.Initialisiere;
var i: integer;
begin
  self := TMittelfeld.Create;
  self.image.Left := Mittelpoint.X;
  self.image.Top := Mittelpoint.Y;
  self.image.Show;
  self.FKoordinate := MittelPunkt;
  FrmMain.SechsEck(self.image.Canvas,breite div 2,0,breite);
  for i := 1 to 6 do
    begin
      // Abarbeitung der 6 Zweige
      self.FHauptFelder[i].{HauptFeld}Initialisiere(i,1,false);
    end;
end;
Es wird 6 mal, also für jede Kante des Sechseck, die Prozedur

Delphi-Quellcode:
procedure THauptFeld{TFrmMain}.{HauptFeld}Initialisiere({Feld: THauptFeld;}Ader,Ebene: integer; Letzter: Boolean);
var bHilf: Boolean;
begin
  self := THauptFeld.Create;

  self.FKoordinate.Ader := Ader;
  self.FKoordinate.Ebene := Ebene;
  self.FKoordinate.Index := 0;

  self.image.Left := FrmMain.PunktToPoint({Feld}self.FKoordinate).X;
  self.image.Top := FrmMain.PunktToPoint({Feld}self.FKoordinate).Y;

  self.image.Show;

  FrmMain.SechsEck({Feld}self.image.Canvas,breite div 2,0,breite);
  self.image.Canvas.TextOut(breite div 2,2,inttostr(ader)+ ' '+inttostr(Ebene)+' 0');
  self.Fletzter := Letzter;
  bHilf := ((ebene+1) >= AnzahlEbenen);

  if not self.FLetzter
    then
      self.FNextHauptFeld.Initialisiere(ader,Ebene+1,bHilf);

  bHilf := (ebene = 2);
  if (ebene > 1)
    then
      self.FKindFeld.inititialisiere(Ader,Ebene,1,bHilf);
end;
Sie erstellt Hauptfelder, die Auf ein nächstes Hauptfeld, sowie auf ein Kindfeld zeigen, Es werden n Hauptfelder erzeugt, wobei n die Anzahl an Ebenen ist, also Kreisen, die sich um den Mittelpunkt herumziehen. Die "KindFelder" füllen die Zwischenräume zwischen den 6 "Adern" der Mitte, also die verlängerten Seiten, die aus Hauptfeldern bestehen.

Das Problem ist wie gesagt, dass die Felder nach der Prozedur wieder alle nil sind.

MFG richard

Khabarakh 28. Sep 2006 12:43

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
Delphi-Quellcode:
self := TMittelfeld.Create;
Was willst du damit erreichen? So geht es jedenfalls auf keinen Fall. So in etwas schon eher:
Delphi-Quellcode:
Mitte := TMittelFeld.Create;
Mitte.Initialize;
DoSomething;


Mitte.Free;

Tormentor32 28. Sep 2006 13:08

Re: 6-Dimensionale Baumstruktur - Spielfeld
 
Ich bin doch an der Stelle in der Prozedur von Mitte, also müsste das self sich doch auf Mitte beziehen oder?


edit: Juhu! :hello: Ich habs endlich hingekriegt, ich habe einfach einen Weiter Parameter übergeben, der das Feld angibt! Danke für die Hilfe!


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz