![]() |
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 |
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] |
Re: 6-Dimensionale Baumstruktur - Spielfeld
Ein Feld sieht folgendermaßen aus:
Delphi-Quellcode:
Jedes feld hat wie du gesagt hast 6 Nachbarn. Das erste Feld ist in der Mitte auf der Ebene 0.
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; 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. |
Re: 6-Dimensionale Baumstruktur - Spielfeld
was ist daran denn jetzt 6-dimensional?
|
Re: 6-Dimensionale Baumstruktur - Spielfeld
Zitat:
|
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:
Die Prozedur TMittelFeld.initialisiere erstellt ein Feld über create, welches die Mitte darstellt
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; 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 |
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. |
Re: 6-Dimensionale Baumstruktur - Spielfeld
Hi!
Ich gehe Sternförmig vom Mittelpunkt aus nach außen.
Delphi-Quellcode:
Es wird 6 mal, also für jede Kante des Sechseck, die Prozedur
//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;
Delphi-Quellcode:
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.
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; Das Problem ist wie gesagt, dass die Felder nach der Prozedur wieder alle nil sind. MFG richard |
Re: 6-Dimensionale Baumstruktur - Spielfeld
Delphi-Quellcode:
Was willst du damit erreichen? So geht es jedenfalls auf keinen Fall. So in etwas schon eher:
self := TMittelfeld.Create;
Delphi-Quellcode:
Mitte := TMittelFeld.Create;
Mitte.Initialize; DoSomething; Mitte.Free; |
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 14:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz