Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Strafzeitenverwaltung in eigener Unit (https://www.delphipraxis.net/152335-strafzeitenverwaltung-eigener-unit.html)

torud 18. Jun 2010 17:09


Strafzeitenverwaltung in eigener Unit
 
Hallo Wissende,

nach einiger Abstinenz bin ich nun auch mal wieder hier und hoffe, dass ich meine Frage im richtigen Sub-Forum stelle.

Ich bin gerade dabei ein kleines Uhrenprogramm für Eishockey zu erstellen. In diesem Programm soll eine Spielzeituhr realisiert werden (schon erledigt) und die Strafzeiten müssen für beide Teams erstellt und verwaltet werden.

Ich bin nun etwas am Grübeln, wie ich das am Besten anstellen kann, weil ja die Strafzeiten ablaufen müssen, intern dann aber die eventuell noch 2. laufende Strafzeit des gleichen Teams an Stelle der ersten bereits abgelaufenen Strafzeit gestellt werden soll.

Also mal ganz grob, bevor ich hier zu viel Verwirrung stifte.

Die einfachste Version ist. Das Spiel läuft, es wird gefoult, durch Team A (Heim) und der foulende Spieler erhält eine Zeitstrafe von 2 Minuten. Im Besten Fall läuft die Zeit ab (von 2:00 auf 0:00 oder umgekehrt) und die Uhr kann intern gelöscht werden.

Ungefähre Ausgabe wäre dann:

XML-Code:
<Team who="A" />
<Penalty Nr="1" Time="1:59" />
Nun kann es aber sein, dass innerhalb der aktuell laufenden 2 Minuten Strafe, ein weiteres Foul eines Spielers vom Team A begangen wird. In dem Fall soll also eine weitere Strafzeit hinzugefügt werden. Wir hätten in dem Fall, die noch laufende erste Strafzeit und die neu hinzugekommene Strafzeit.

XML-Code:
<Team who="A" />
<Penalty Nr="1" Time="0:38" />
<Penalty Nr="2" Time="2:00" />
Das Spiel geht nun weiter und beide Strafzeiten laufen. Die "erste" Strafzeit läuft nun auf 0:00 runter. Nun sollte die 2. Strafzeit an Stelle der ersten Strafzeit rutschen.

XML-Code:
<Team who="A" />
<Penalty Nr="1" Time="1:22" />
Ich würde die ganze Logik gern in eine eigene Unit oder Klasse stecken, muss aber zugeben, dass ich nicht wirklich weiss, wo ich anfangen soll. Ich habe schon ein paar Funktionen in Units ausgelagert, aber eine gesamte Struktur noch nie.

Kann mir bitte jemand ein paar Tipps geben? Ich stell auch gern die Sourcen hier ein, wenns soweit ist.

DeddyH 18. Jun 2010 18:21

AW: Strafzeitenverwaltung in eigener Unit
 
Spontan würde ich da eine TObjectList in Betracht ziehen. Du definierst Dir ein Objekt mit den entsprechenden Feldern und fügst dies in die Liste ein. Ist die Zeit abgelaufen, löschst Du das Objekt wieder aus der Liste. Die Ausgabe erfolgt dann zyklisch (Timer) mittels einer Schleife über die Objekte.

Namenloser 18. Jun 2010 18:26

AW: Strafzeitenverwaltung in eigener Unit
 
Man könnte statt der TObjectList auch Delphi-Referenz durchsuchenTQueue benutzen.

DeddyH 18. Jun 2010 18:27

AW: Strafzeitenverwaltung in eigener Unit
 
Das sollte in diesem Fall auf das selbe Ergebnis hinauslaufen, aber klar, wieso nicht?

Namenloser 18. Jun 2010 18:37

AW: Strafzeitenverwaltung in eigener Unit
 
Natürlich kommt das gleiche Ergebnis heraus, wäre ja auch schrecklich, wenn nicht, oder? :shock:
Ich finde, wenn Delphi schon eine Klasse speziell für solche Fälle anbietet, kann man die ruhig auch mal benutzen ;)

torud 18. Jun 2010 18:51

AW: Strafzeitenverwaltung in eigener Unit
 
Hallo,

erstmal danke für Euren Hinweise. Wie gesagt mein Wissen über Units und eigene Klassen ist arg begrenzt. Ich habe jetzt mal so angesetzt. Allerdings erschliesst sich mir noch nicht ganz, wie ich dass dann aufrufen soll, ob ich die Zeiten dann über nen Timer im Hauptfenster aktualisieren muss oder in der Klasse selbst und wo ich nun die Penalties als Liste erhalte...

Fragen über Fragen.

Irgendwas mach/denk ich da noch falsch...

Hier erstmal mein aktueller Stand. Danke für einen prüfend beleerenden Blick.

Delphi-Quellcode:
unit unt_penalties;

interface

type
  TPenalties = class
  public
    Team   : Char;   //character of Team (A or B)
    TTime  : String; //total time of penaltie
    CTime  : String; //current time of penalty
    constructor Create;
    class function AddPenalty(Team:Char;TimeOfPenalty : String): String;   //add a penalty
    class function DeletePenalty(Team:Char;TimeOfPenalty : String): String; //delete a penalty
    class function EditPenalty(Team:Char;TimeOfPenalty : String): String;  //edit a penalty
  end;

implementation

constructor TPenalties.Create;
begin
  inherited;
end;

class function TPenalties.AddPenalty(Team:Char;TimeOfPenalty : String): String;
begin
  //add a penalty
end;

class function TPenalties.DeletePenalty(Team:Char;TimeOfPenalty : String): String;
begin
  //delete a penalty
end;

class function TPenalties.EditPenalty(Team:Char;TimeOfPenalty : String): String;
begin
  //edit a penalty
end;

end.

Namenloser 18. Jun 2010 19:53

AW: Strafzeitenverwaltung in eigener Unit
 
Der Code ist so Unsinn. Du hast hier 2 Klassen zu einer einzigen verschmolzen, bzw. du hast hier eine Klasse, die gleichzeitig die Daten eines einzelnen Eintrages speichert *und* eine Liste von ebendiesen Einträgen verwalten soll. Das kann nicht funktionieren. Grundregel der OOP: Jede Klasse hat genau *eine* Aufgabe zu erfüllen.

Was du brauchst sind 2 Klassen:
- die erste Klasse repräsentiert einen Strafzeit-Eintrag
- die zweite Klasse verwaltet Instanzen dieser Klasse in einer Liste (kann z.B. TQueue oder TObjectList sein)

Ich vermute außerdem, dass du Objekte und Klassen durcheinander wirfst. Ein Objekt ist alles in deiner Umgebung: eine Lampe, ein Schuh, eine Tastatur, eine Maus, ein Mensch... eben Dinge mit bestimmten Eigenschaften (wie z.B. Farbe, Größe etc.) und Methoden (z.B. Laufen, Springen, Essen...).

Eine Klasse hingegen ist quasi ein Bauplan für ein solches Objekt - sie gibt an, welche Felder, Eigenschaften, Methoden etc. es gibt. Das Objekt, d.h. eine Klasseninstanz, ist dann das konkrete "Ding", das durch die Klasse definiert wurde. Hiervon kann es natürlich auch mehrere geben, genau so wie man mehrere Häuser nach dem gleichen Bauplan bauen kann.

Benutzen tust du in der Regel immer nur die konkreten Objekte, nicht die Klassen. Daher sind auch die vielen class functions sicher nicht das was du willst, diese beziehen sich nämlich nicht auf die Instanzen einer Klasse, sondern auf die Klasse (den Bauplan) selbst, was eigentlich nur für Spezialfälle gedacht ist. Du willst aber mit Objekten arbeiten, und das ist mit class functions, so wie du sie verwendest, nicht machbar, da du z.B. nicht auf ein Feld (Variable) eines einzelnen Objekts zugreifen kannst, da die Klasse gar nicht wissen kann, welches Objekt gemeint ist, denn davon kann (und soll) es ja schließlich mehrere geben.

Ich würde dir dringend empfehlen, ein Tutorial (oder noch besser ein Buch) über OOP zu lesen, bevor du weitermachst. Ohne die Grundlagen zu kennen, wirst du dir nämlich nur unnötig in den Fuß schießen. Als Anfänger kann es sehr leicht passieren, dass man seine Klassen nicht sinnvoll aufteilt (wie man z.B. bei deinem Code sieht), und dann hinterher u.U. ein Programm erhält, dass zwar Klassen und Objekte nutzt, aber in trotzdem in keinster Weise objektorientiert ist.

torud 18. Jun 2010 21:00

AW: Strafzeitenverwaltung in eigener Unit
 
Moin Philip,

danke für deine umfangreichen Ausführungen. Ich glaube/hoffe, dass ich es nun etwas besser verstehe. Ich habe nun auch den Code so aufgesplittet, dass die eigentliche Zeitstrafe eine Klasse abgeleitet von TObject ist und Penalties eine Klasse abgeleitet von TObjectlist ist.

Der Code sollte nun um einiges besser aussehen.

Zum besseren Verständnis erlaube ich mir aber trotzdem noch ein paar Fragen. Vorher aber schon mal der Code. Ich habe ihn so kurz wie möglich gehalten.

Delphi-Quellcode:
unit unt_penalty;

interface

type
  TPenalty = class
  public
    Team   : Char;   //character of Team (A or B)
    TTime  : String; //total time of penaltie
    CTime  : String; //current time of penalty
    Direction : byte; //direction of running time 0:asc;1:desc
    constructor Create;
  end;

implementation

constructor TPenalty.Create;
begin
  inherited;
end;

end.
Delphi-Quellcode:
unit unt_penalties;

interface

uses Contnrs, unt_Penalty;

type
  TPenalties = class(TObjectList)
  public
    constructor Create;
    function AddPenalty(Penalty : TPenalty; PenaltyList : TObjectList): TObjectList;   //add a penalty
    function DeletePenalty(Penalty : TPenalty; PenaltyList : TObjectList): TObjectList; //delete a penalty
    function EditPenalty(Penalty : TPenalty; PenaltyList : TObjectList): TObjectList;  //edit a penalty
  end;

implementation

uses Classes;

constructor TPenalties.Create;
begin
  inherited;
end;

function TPenalties.AddPenalty(Penalty : TPenalty; PenaltyList : TObjectList): TObjectList;
begin
  //add a penalty
  with PenaltyList do
    begin
      Add(Penalty);
    end;
end;

function TPenalties.DeletePenalty(Penalty : TPenalty; PenaltyList : TObjectList): TObjectList;
begin
  //delete a penalty
  with PenaltyList do
    begin
      Delete(IndexOf(Penalty));
    end;
end;

function TPenalties.EditPenalty(Penalty : TPenalty; PenaltyList : TObjectList): TObjectList;
begin
  //edit a penalty
end;

end.
Und so habe ich es testhalber im MainForm mal eingebunden:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  MyPenalty  : TPenalty;
  MyPenalties : TPenalties;
begin
  //erzeugen des penalty und zuweisen der daten
  MyPenalty := TPenalty.Create;
  MyPenalty.Team := 'A';
  MyPenalty.TTime:= '00:02:00';
  MyPenalty.CTime:= '00:02:00';
  MyPenalty.Direction:= 0;
  //erzeugen der penaltyliste und hinzufügen des penalty
  myPenalties := TPenalties.Create;
  mypenalties.AddPenalty(MyPenalty, MyPenalties);
end;
Es lässt sich kompilieren, aber ich habe natürlich noch das Problem, dass ich nicht weiss, wie ich dann an die einzelnen Penalty-Einträge in der Penaltyliste komme, wenn ich diese z.B.

Löschen, Editieren oder wegen laufenden Uhr updaten möchte...

Die Daten (die einzelnen Zeitstrafen) muss ich natürlich auch im Programm visualiseren, d.h. ich muss natürlich vorher die Daten nach Teams und Höhe der laufenden Uhr sortieren und dann intern (später auch extern) anzeigen.

Hast Du hierfür noch einen Tipp?
Habe ich sonst noch was falsch gemacht?

jfheins 18. Jun 2010 21:12

AW: Strafzeitenverwaltung in eigener Unit
 
1. Empfehlung: Du solltest TPenalty einen Kontruktor spendieren, dem man alle Daten übergeben kann.
2. Fehler: function AddPenalty BITTE keinen 2. Parameter. Das ist sinnlos, dafür ist doch gerade das Objekt da.
3.
Delphi-Quellcode:
Direction : byte; //direction of running time 0:asc;1:desc
???? Eine Penalty läuft doch immer "ab" oder nicht?
4. Datenhaltung. Strings würde ich hier nicht einsetzen. Viel besser wäre ein Zeitpunkt, zu dem die Strafzteit abläuft. Ich weis jetzt nicht, wie du die Spielzeit intern mitnimmt, aber dementsprechend wäre TTime oder integer angebracht. Daten und Darstellung bitte trennen.

das wäre es erstmal von meiner Seite ;)

torud 18. Jun 2010 21:37

AW: Strafzeitenverwaltung in eigener Unit
 
Hallo,

also ich habe die Penalty etwas angepasst.

Delphi-Quellcode:
unit unt_penalty;

interface

uses Classes;

type
  TPenalty = class
  public
    Team   : Char;   //character of Team (A or B)
    TTime  : String; //total time of penaltie
    CTime  : String; //current time of penalty
    Direction : byte; //direction of running time 0:asc;1:desc
    constructor Create(ATeam:Char; ATTime, ACTime : String; ADirection : byte); overload;
    constructor Create; overload;
  end;

implementation

constructor TPenalty.Create;
begin
  inherited;
end;

constructor TPenalty.Create(ATeam:Char; ATTime, ACTime : String; ADirection : byte);
begin
  inherited Create;
  Team     := ATeam;
  TTime    := ATTime;
  CTime    := ACTime;
  Direction := ADirection;
end;

end.
Das Create ist nun doppelt drin. Vielleicht kann das eine ja nun auch ganz raus!?

Zu Deinen Punkten Julius:
1. erledigt
2. ich bin echt ´n Blinder. :cyclops:
3. Wie sicher bist Du Dir da? Ich habe heute einiges an Zeit verbracht dies auf Offiziellen Seiten nachzulesen. Fakt ist. Die reine Spielzeit kann sowol aufsteigen, als auch absteigend angezeigt werden. Kommt auf die Liga an. Insofern, dachte ich mir, dass es günstig sein könnte diese Eigenschaft zu vergeben...
4. Ja. Das ist aktuell meinem internen Zeitverfahren geschuldet und der Frage, an welcher Stelle ich denn dann nun die Zeiten (aktuell Spielzeit und jede einzelne laufende Strafzeit) intern und später dann auch extern aktualisieren lassen soll. Aktuell läuft auf dem Hauptform einfach nur ein Timer, der die Sekunden und Minuten hoch- oder runterzählt.

Verrückt ist im übrigen auch, dass folgendes nach dem Zuweisen der ersten Testdaten nicht möglich ist:
Delphi-Quellcode:
  //erzeugen des penalty und zuweisen der daten
  MyPenalty := TPenalty.Create;
  MyPenalty.Team := 'A';
  MyPenalty.TTime:= '00:02:00';
  MyPenalty.CTime:= '00:02:00';
  MyPenalty.Direction:= 0;
  //erzeugen der penaltyliste und hinzufügen des penalty
  myPenalties := TPenalties.Create;
  mypenalties.AddPenalty(MyPenalty);
  //erneutes zuweisen des penalty aus der liste, um zugriff zu prüfen
  MyPenalty := mypenalties[0];
  ShowMessage(MyPenalty.Team);
Inkompatible Typen TPenalty und TObject (ein as TObject half auch nicht...)


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:23 Uhr.
Seite 1 von 3  1 23      

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