Hi!
Ich hab' im Moment leider kein Delphi oder Turbo-Pascal da, deshalb mache ich meine Beispiele mal aus dem Gedächtnis im TurboPascalformat. Ich nutze Records, damits nicht zu komplex wird (für den Anfang). Ja, es ist übrigends so, dass man RECORD durch OBJECT ersetzen kann. CLASS hat (glaube ich) eine leicht andere Syntax.
Ich würde mir einen Datensatz für die einzelnen Besitzvarianten erstellen. Das hat IMHO den Vorteil, dass man dann beim Verwalten mit allgemeinen Routinen auskommen kann, ohne dass man dabei dann sachen wie Milität oder Landwirtschaft unterscheiden muss.
Irgendwie werden die ganzen Dinge ja vergleichbar sein: man muss ein paar Werte verwalten, dass wird bei Milität und bei Landwirtschaft auch so sein.
TypeGameBesitz:record
TypeID:integer;
OwnerID:integer;
Desc:string;
Wert1:extended;
end;
In TypeID wird ein Wert eingetragen, der festlegt, um was es geht, am besten definiert man die Rypen als Konstanten:
const
ID_Militaer = 1;
ID_Landwirtschaft = 2;
ID_Energiewitschaft = 3;
ID_Kulturstand = 4;
Der Vorteil ist, dass du dann später recht einfach neue Typen hinzufügen kannst: an den eigentlichen Verwaltungsroutinen braucht man nichts zu ändern, nur die Auswertung muss erweitert werden.
Die OwnerID ist ein kleiner Kunstgriff im Voraus: da speichern wir die Nummer des Spielers ab, der dann diesen Besitz zugeordnet wird. Desc ist einfach eine Beschreibung, die sollte man auch als Konstante anlegen:
const
ID_DescMilitaer = 'Militär';
ID_DescLandwirtschaft = 'Landwirtschaft';
ID_DescEnergiewitschaft = 'Energiewirtschaft';
ID_DescKulturstand = 'Kultur';
OK, kommen wir zu den Planeten:
TypeGamePlanet:record
PlanetID:integer;
Desc:string;
besitz:array[1..20] of ^TypeGameBesitz;
end;
Das meiste ist schon bekannt: der Planet bekommt eine Kennung (Kennnummer) und eine Beschreibung. Würde ich wieder als Konstanten anlegen.
Die Besitztümer speichern wir einfach in einem Array ab. Die Beschränkung auf 20 Elemente ist jetzt willkührlich. Dassann man erweitern, sinnvoll wäre eigentlich eine variable Grösse, da kannst du dich ja austoben. ;-)
Im Prinzip braucht man jetzt noch ein paar Routinen zur Verwaltung des ganzen. fangen wir mit einer zur Initialisierung der Besitzthümer an.
Ich hoffe, ich komme mit der Systax für zeiger nicht durcheinander...
function InitGameBesitz(ID;Owner:interger; NewDesc:string; NewValue:Extended):^TypeGameBesitz;
begin
InitGameBesitz := new(TypeGameBesitz);
with InitGameBesitz^ do
begin
TypeID:0id,
OwnerID:=Owner;
Desc:=NewDesc;
Wert1:=NewValue;
end;
end;
Für den Planet muss man nun drei Funktionen schreiben:
1. Eine Init zum Initialisieren des Planeten mit seiner Nummer, der Beschreibung.
Hier sollte dann auch der Array gelöscht werden.
2. Eine Funktion zum Abspeichern oder ändern eines Besitzes.
Als Parameter würde die Funktion nur einen zeiger auf einen besitz bekommen. Mit dessen BesitzID (die den Typ des Besitzes festlegt) und der OwnerID kann man feststellen, ob der Spieler (OwnderID) bereits einen solchen Besitz auf dem Planeten hat, falls nein, wird er neu im Array gespeichert, falls ja, dann muss man den Eintrag austauschen.
3. Eine Funktion, die einen Besitz in ihrem Array sucht. Sie erwartet ebenfalls den BesitzTyp und die Nummer des Spielers. Sie durchsucht dann das Array und liefert NIL oder einen Zeiger auf den entsprechenden Besitz zurück.
Wie gesagt: der Vorteil ist, dass diese ganzen Verwaltungsroutinen dann unabhängig vom besitztyp funktionieren. Egal, ob das nun Militär oder Landwirtschaft ist.
Was so noch nicht geht, ist verschiedene Definition von Besitztypen parallel zu nutzen. dazu muss man dann an die Objekte ran. Das wäre aber auch nciht alzu schwer, da ich mit meinem "Plan" bereits eine typische Struktur erzeugt habe, die man dann recht einfach in Objekte überführen kann: es gibt feste Datentypen und Routinen, die nur einen speziellen datentyp bearbeiten können - aber es gibt noch keine formelle Verbindung zwischen diesen beiden Bestandteilen. das machen erst Objekte: die können dann neben variablen auch Prozeduren und Funktionen wie eine Vraiable aufnehmen. Die Deklaration des Besitzes als Objekt sieht dann so aus:
TypeGameBesitz:object
{Variablen des Objektes:}
TypeID:integer;
OwnerID:integer;
Desc:string;
Wert1:extended;
{Funktionen des Objektes:}
constructor Init(ID;Owner:interger; NewDesc:string; NewValue:Extended);
function GetValue:extended;
end;
constructor TypeGameBesitz.Init(ID;Owner:interger; NewDesc:string; NewValue:Extended)
begin
TypeID:=ID;
OnerID:=Owner;
Desc:=NewDesc;
Wert1:=NewValue;
end;
function TypeGameBesitz.GetValue:extended;
begin
GetValue:=Wert1;
end;
Eine neue Variable (bei Objekten spricht man von Instanz) legt man dann per New an:
var NewBesitz:^TypeGameBesitz;
NewBesitz:=new(TypeGameBesitz,Init(ID_Militaer, IDPlayerI1, D_DescMilitaer, 1.5));
Wenn man nun Wert1 aus der Waribake lesen will, dann kann man die Funktion nutzen:
var DummyE:extended;
DummyE:=NewBesitz^.GetValue;
So, dass reicht für Heute. ;-)
Ach ja, das Verwenden von abgekieteten Objekten:
Nur ein schnelles Beispiel, indem wir eine Klasse für eine Flotte anlegen:
TypeGameBesitzFlotte:object(TypeGameBesitz)
{Variablen des Objektes:}
TypeGameBesitz{Funktionen des Objektes:}
shipname:string;
constructor Init(ID;Owner:interger; NewDesc:string; NewValue:Extended; NewShipName:string);
end;
Den Construktor muss man entsprechend neu schreiben, er kann aber kann den Contructor der Parent-Klasse aufrufen:
constructor TypeGameBesitzFlotte.Init(...)
begin
{Erst die geerbten Variablen initialisieren:}
inherited Init(usw...);
{dann die eigene:}
shipname:=NewShipname;
end;
Später kann man in dieser Klasse dann auch die Funktionen oder Variablend es Vorgängers erreichen, also kann man GetValue ganz normal nutzen. Was auch eght, ist eine Variable vom tp TypeGameBesitzFlotte anzulegen und diese als Parameter an einen Wert zu übergeben,d er eigentlich vom Typ TypeGameBesitz sein müsste.
-> Die Routinen von TypeGamePlanet laufen also auch, wenn ich dort diese abgeleitete Version übergebe, man muss also9 dort nichts ändern!
Bis dann
Andreas