|
Antwort |
Registriert seit: 30. Dez 2002 Ort: Brandshagen 1.819 Beiträge Delphi 2007 Professional |
#31
Also, ich hab noch mal nachgedacht. Du solltest die PlayList nicht den Playern zuordnen, sondern die Player den PlayClasses. Das macht mehr Sinn.
Wenn du Hilfe bei der Erstellung der Klassen brauchst sag bescheid, dann mach ich das (brauch mal ne kleine Ablenkung mit ner leichten Aufgabe). Gruß oki
42
|
Zitat |
Registriert seit: 5. Mär 2008 131 Beiträge Delphi 2005 Personal |
#32
Puuu Oki, das ist harte Kost für mich.
Mit Klassen habe ich mich noch nicht so viel beschäftigt und kenne deren Vor- und Nachteile überhaupt nicht. Ich habe auch noch nicht geschnallt, wie du das mit den Verknüpfungen, wann und wo welcher spieler weiterspielt oder ausscheidet über die Klassen regeln willst. Das mit einer kompletten Teilnehmerliste ist OK die hätte ich sowieso gebraucht auch schon wegen der eventuellen Namensänderung. Du schreibst das so als wäre das alles kein Problem. Für mich sind da ein paar böhmische Dörfer schon dabei, werde allerding versuchen mich am Wochenende schlau zu machen, und wie gesagt fehlen dir noch ein paar Infos die ich am Wochenende zusammenschreiben werde, nur damit du nicht unnötig zeit investierst und sagst das hättest du mir gleich sagen sollen. Datenmodel erstellen ? wie ? aber ich bin lernbereit, denn wie gesagt ich bin Hobbyprogrammierer. Leider habe ich am Wochenende kein Inet, es kann daher sein, dass ich mich erst am Montag wieder melde.(bin aber heute bis 16 Uhr erreichbar und schaue nochmal hier vorbei.
Zitat von oki:
Vertrau mir, ich wies was ich tu( kennst du den Spruch? stammt aus einer alten Serie)
Gruss Dieter |
Zitat |
Registriert seit: 30. Dez 2002 Ort: Brandshagen 1.819 Beiträge Delphi 2007 Professional |
#33
Slatch Hammer (ob richtig geschrieben, keine Ahnung?), das war der Bulle, der in seine Knarre verliebt war und ständig mit der rumgeballert hat (z.B. Fliegen von der Wand ).
das zum wichtigen Teil der der Nachricht. So, nun zum Datenmodell. das ist gar nicht so schwer. Fangen wir mal ganz vorne an; die Player. Hier mal auf die Schnelle die Klassen für die Spieler und die Spielerliste. Alle Funktionen für die Statistiken usw. die direkt die Spieler betreffen generieren wir dann in der PlayerList.
Delphi-Quellcode:
Alles, was die Spiele betrifft kommt dann in die PlayList. Das später.
unit Player_Classes;
interface type // Forward TPlayerList = class; // Der ShowMode definiert, wie der Name des Spielers ausgegeben wird TShowNameMode = (snm_FullName, // Vorname und Name anzeigen snm_Name, // nur Nachname anzeigen snm_ShortFirstName // Vorname abgekürzt, Nachname voll ); (* Klasse eines einzelnen Spielers. Der Member PlayerList gibt die übergeordnete Liste an, die den Spieler hält. *) TPlayerClass = class(TObject) private FBirthday: TDateTime; FFirstName: String; FName: String; FPlayerList: TPlayerList; FShowNameMode: TShowNameMode; function GetFullName: String; procedure SetBirthday(const Value: TDateTime); procedure SetFirstName(const Value: String); procedure SetName(const Value: String); procedure SetShowNameMode(const Value: TShowNameMode); public property PlayerList : TPlayerList read FPlayerList write FPlayerList; property Birthday : TDateTime read FBirthday write SetBirthday; property FirstName : String read FFirstName write SetFirstName; property Name : String read FName write SetName; property ShowNameMode : TShowNameMode read FShowNameMode write SetShowNameMode; property FullName : String read GetFullName; end; TPlayerList = class(TObjectList) private protected function GetItem(Index: Integer): TPlayerClass; procedure SetItem(Index: Integer; AObject: TPlayerClass); public function Add(AObject: TPlayerClass): Integer; function Extract(Item: TPlayerClass): TPlayerClass; function Remove(AObject: TPlayerClass): Integer; function IndexOf(AObject: TPlayerClass): Integer; procedure Insert(Index: Integer; AObject: TPlayerClass); function First: TPlayerClass; function Last: TPlayerClass; procedure PlayerChanged; property Items[Index: Integer]: TPlayerClass read GetItem write SetItem; default; end; implementation { TPlayerClass } function TPlayerClass.GetFullName: String; begin case FShowNameMode of snm_FullName: Result := Format('%s %s', [FFirstName, FName]); snm_Name: Result := FName; snm_ShortFirstName: Result := Format('%s. %s', [FFirstName[1], FName]); end; end; procedure TPlayerClass.SetBirthday(const Value: TDateTime); begin if FBirthday = Value then Exit; FBirthday := Value; if Assigned(FPlayerList) then FPlayerList.PlayerChanged; end; procedure TPlayerClass.SetFirstName(const Value: String); begin if FFirstName = Value then Exit; FFirstName := Value; if Assigned(FPlayerList) then FPlayerList.PlayerChanged; end; procedure TPlayerClass.SetName(const Value: String); begin if FName = Value then Exit; FName := Value; if Assigned(FPlayerList) then FPlayerList.PlayerChanged; end; procedure TPlayerClass.SetShowNameMode(const Value: TShowNameMode); begin if FShowNameMode = Value then Exit; FShowNameMode := Value; if Assigned(FPlayerList) then FPlayerList.PlayerChanged; end; { TPlayerList } function TPlayerList.Add(AObject: TPlayerClass): Integer; begin AObject.FPlayerList := self; Result := inherited Add(AObject); end; function TPlayerList.Extract(Item: TPlayerClass): TPlayerClass; begin Result := TPlayerClass(inherited Extract(Item)); result.FPlayerList := nil; end; function TPlayerList.First: TPlayerClass; begin Result := TPlayerClass(inherited First); end; function TPlayerList.GetItem(Index: Integer): TPlayerClass; begin Result := TPlayerClass(inherited GetItem(Index)); end; function TPlayerList.IndexOf(AObject: TPlayerClass): Integer; begin Result := inherited IndexOf(AObject); end; procedure TPlayerList.Insert(Index: Integer; AObject: TPlayerClass); begin AObject.FPlayerList := self; inherited Insert(Index, AObject); end; function TPlayerList.Last: TPlayerClass; begin Result := TPlayerClass(inherited Last); end; {----------------------------------------------------------------------------- Procedure: PlayerChanged Author: Dipl. Ing. Olaf Keitsch Date: 05-Jun-2009 Arguments: None Result: None Describtion: Diese Methode wird von den Settern der Player aufgerufen. An dieser Stelle kann die Aktualisierung des anzeigenden Controls aufgerufen werden. -----------------------------------------------------------------------------} procedure TPlayerList.PlayerChanged; begin // do it end; function TPlayerList.Remove(AObject: TPlayerClass): Integer; begin AObject.FPlayerList := nil; Result := inherited Remove(AObject); end; procedure TPlayerList.SetItem(Index: Integer; AObject: TPlayerClass); begin AObject.FPlayerList := self; inherited SetItem(Index, AObject); end; end. In der Klasse PlayerList kannst du jetzt in den Propertys noch ergänzen, was du direkt zu den Spielern an Angaben erfassen willst. Hier kommt aber nichts zu den Spielen rein. Gruß oki
42
|
Zitat |
Registriert seit: 5. Mär 2008 131 Beiträge Delphi 2005 Personal |
#34
Hallo Oki,
Mensch du bist schneller als die Polizei erlaubt, hast du das alles fertig in der Schublade? Hab dir schnell mal zusammengeschrieben, damit du alle Infos hast die du brauchst. Da ein Dart Event aus mehreren Turnieren (Einzel Doppel in den jeweiligen Klassen) besteht die meist gleichzeitig laufen, habe ich mich entschlossen einen Eventmanager (Eigenständiges Programm) zu programmieren Im Manager sollen alle wichtigen eingaben die alle Turniere Betreffen erfolgen -Eingabe der Anzahl der vorhandenen Automaten -Sperrung eines Automaten -Eingabe der Spieler zum jeweiligen Turnier -starten eines Turniers (eigenständiges Programm je nach Anzahl der Spieler hier sind wir gerade mit unserer Komponente.) -unterbrechen eines Turniers -Turnier wieder aufnehmen. -ein Spieler gibt auf weil er dringend weg muss dann soll der Spieler an allen Turnieren an denen er angemeldet ist praktisch als Freilos weitergeführt werden, bis das Freilos ausgeschieden ist. Alles was alle Turniere betrifft wird in einer zentralen Datei gespeichert. hier rufen die einzelnen Turniere ihre Daten ab oder schreiben hinein. Ist wichtig bei Stromausfall, damit der Event an diesem Punkt weitergeführt werden kann. (sonst kann es passieren dass eine Horde über mich herfällt) Ablauf Erstellung eines Events Eingabe der Anzahl der vorhandenen Automaten Eingabe des Event namens = Dateiname der Ini Speicherung des Events in einem Verzeichnis. Anlegen einer INI - Datei mit den Grundeinstellungen Belegung der Automaten (Überwachung) jeder Automat an dem gespielt wird muss als belegt gekennzeichnet werden, damit er zur Auswahl in den Turnieren nicht mehr zur Verfügung steht. Automatenausfall Es muss möglich sein einen Automaten zu sperren (defekt) wird gerade dort gespielt muss eine Info zur Partie gehen, damit dort ein neuer Automat ausgewählt werden kann. Freilose(Überwachung) ist eine Partie mit einem Freilos komplett so wird sofort das Freilos als Verlierer gewertet und wird dementsprechend weitergereicht bzw. scheitet aus dem Turnier aus. Spieler spielt bereits in einem anderen Turnier (Überwachung) Jeder Spieler der gerade eine Partie spielt muss gekennzeichnet werden, damit er nicht nochmals zu einer Partie aufgerufen werden kann. Ein Spieler beendet vorzeitig das Turnier. gibt ein Spieler das Turnier vorzeitig auf so wird er ab dieser Runde behandelt wie ein Freilos. So nun hast du denke ich alle Infos die du brauchst. Ich hab dir ja gesagt dass das ganze ziemlich komplex ist. (Hoffentlich habe ich dich jetzt nicht verjagt) Wenn du willst kannst du dir ja ein Paar Gedanken machen. Ich werde mich mal mit deinen Klassen beschäftigen, scheint auf den zweiten Blick die Lösung für einige Probleme zu sein, bin aber noch nicht ganz durchgestiegen. Richtig ! An die Serie kann ich mich noch erinnern. Gruss bis Montag Dieter. |
Zitat |
Registriert seit: 30. Dez 2002 Ort: Brandshagen 1.819 Beiträge Delphi 2007 Professional |
#35
Hallo Dieter,
Dank für deine Erläuterungen. Bin zwar noch nicht ganz durchgestiegen bei den Themen Automaten, Events usw., fehlt mir die Praxis. Trotzdem sehe ich das alles nicht so wild. Entscheidend ist hier einfach nur der intelligente Klassenaufbau für die Spiele. Da hab ich das Thema Turniere usw. noch nicht ganz geschnallt. Vorallem die Abhängikeiten usw. Das ignoriere ich jetzt aber mal geflissentlich. Hat in der Ebene in der wir gerade stecken wohl noch keine Auswirkungen. Ich versuche gerade herauszubekommen, was wir alles für die PlayClass an Eigenschafen brauchen. Auf deutsch, was ist alles für ein Spiel (Paar) an Informationen relevant. Die beiden Spieler ist sicher klar. Dann der Spielstand. Was gehört noch alles zu einem Spiel? Der Automat vielleicht? Da musst du mal paar Angaben machen. Die PlayList hält dann zwar die einzelnen Spiele eines Turniers (denke ich), muss dann aber sicher noch einige Funktionen haben. Da musst du wieder helfen. Ich hatte mir das Händling dafür so vorgestellt. Die PlayList hält die PlayClass'es. wird in einer PlayClass ein Spielstand gespeichert, so wird die Playlist davon informiert (so wie das mit den Änderungen bei den Playern). Dabei wird dann aber das PlayObject mitgeliefert (Methode ChangePlayClass der PlayList). Das die PlayList dann weis, in welchem Spiel sich der Spielstand wie geändert hat, kann sie automatisch ermitteln, in welche weiteren Play-Objekte seiner Liste die entsprechenden Spieler eingetragen werden müssen. Ein Status für das entsprechende Spiel zum Sperren usw. kann dann die Playlist mit vergeben. Dazu kann man der PlayClass eine entsprechende Eigenschaft verpassen. Das alles ist schon mit Sicht auf die spätere Anzeige gedacht. Da machen sich solche Statusflags immer toll um die Anzeige anzupassen. Naja, ich denk mir da mal was aus. bis die Tage, Gruß oki
42
|
Zitat |
Registriert seit: 30. Dez 2002 Ort: Brandshagen 1.819 Beiträge Delphi 2007 Professional |
#36
Hi,
ich hab mal die Klassen für die Spieler, Spielerliste, Spiele und Spielliste fertig gestellt. Leider hab ich das System für den Eintrag eines Spielers in ein neues Spiel noch nicht ganz durchschaut. Für die Gewinner ist das ja recht einfach. Bei den Verlierern hab ich da so meine Probleme. Ich pack hier mal die Procedure rein.
Delphi-Quellcode:
Hier noch einige Bemerkungen zum Ablauf. Wird in einem Spiel ein Spielstand (oder eine andere Eigenschaft) geändert so ruft das Spiel die Procedure ChangePlay seiner PlayList auf und übergibt sich selbst sowie den Namen der Eigenschaft an die Procedure.
procedure TPlayList.ChangePlay(APlayClass: TPlayClass; AProperty : String);
var AWinner, ALooser : TPlayerClass; procedure PlayerinGame(APlayer : TPlayerClass; AOldPlay : TPlayClass; winning : Boolean); var NewPlay : TPlayClass; begin if winning then begin // Spieler ist Gewinner des alten Spieles case ORD(AOldPlay.FGame) of ORD('R') : begin // Gewinner der ersten Runde if Odd(AOldPlay.Number) then begin NewPlay := GetPlay('G', 1, (AOldPlay.Number+1) div 2); if Assigned(NewPlay) then NewPlay.FPlayer1 := APlayer; end else begin NewPlay := GetPlay('G', 1, (AOldPlay.Number) div 2); if Assigned(NewPlay) then NewPlay.FPlayer2 := APlayer; end; end; ORD('G') : begin if Odd(AOldPlay.Number) then begin NewPlay := GetPlay('G', AOldPlay.FRound+1, (AOldPlay.FNumber+1) div 2); if Assigned(NewPlay) then begin NewPlay.FPlayer1 := APlayer; end else begin // das war das letzte Gewinnerspiel, ab ins Filale NewPlay := GetPlay('F', 0, 0); if Assigned(NewPlay) then NewPlay.Player1 := APlayer; end; end else begin NewPlay := GetPlay('G', AOldPlay.FRound+1, (AOldPlay.FNumber) div 2); if Assigned(NewPlay) then begin NewPlay.FPlayer2 := APlayer; end else begin // das war das letzte Gewinnerspiel, ab ins Filale NewPlay := GetPlay('F', 0, 0); if Assigned(NewPlay) then NewPlay.Player1 := APlayer; end; end; end; ORD('V') : begin NewPlay := GetPlay('V', AOldPlay.Round + 1, 1); if Assigned(NewPlay) then begin NewPlay.FPlayer1 := APlayer; end else begin // das war das letzte Gewinnerspiel, ab ins Filale NewPlay := GetPlay('F', 0, 0); if Assigned(NewPlay) then NewPlay.Player2 := APlayer; end; end; end; end else begin // Spieler ist Verlierer des alten Spieles case ORD(AOldPlay.FGame) of ORD('R') : begin // Gewinner der ersten Runde if Odd(AOldPlay.Number) then begin NewPlay := GetPlay('V', 1, (AOldPlay.Number+1) div 2); if Assigned(NewPlay) then NewPlay.FPlayer1 := APlayer; end else begin NewPlay := GetPlay('V', 1, (AOldPlay.Number) div 2); if Assigned(NewPlay) then NewPlay.FPlayer2 := APlayer; end; end; ORD('G') : begin // jo, da hab ich noch kein System entdeckt ??????????? end; ORD('V') : begin // das wars dann, kein weiteres Spiel :-( // oder doch? :-) hab ich das System aber auch noch nicht durchschaut end; end; end; end; begin // ein Spieler ist ein Freilos? if ((AProperty = 'Player1') or (AProperty = 'Player2')) and (Assigned(APlayClass.Player1) and Assigned(APlayClass.Player2)) and ((APlayClass.Player1.FPlayerType = pt_Looser) or (APlayClass.Player2.FPlayerType = pt_Looser)) then begin if APlayClass.Player1.FPlayerType = pt_Looser then begin // Player2 hat gewonnen AWinner := APlayClass.FPlayer2; ALooser := APlayClass.FPlayer1; end else begin // Player1 hat gewonnen AWinner := APlayClass.Player1; ALooser := APlayClass.Player2; end; // neues Spiel für Gewinner ermitteln PlayerinGame(AWinner, APlayClass, True); // neues Spiel für Verlierer ermitteln PlayerinGame(ALooser, APlayClass, False); // Counter der gespielten Spiele der Spieler erhöhen AWinner.PlayCount := AWinner.PlayCount + 1; ALooser.PlayCount := ALooser.PlayCount + 1; // aktuelle Platzierung der Spieler setzen AWinner.Position := FPlayerList.Count - AWinner.PlayCount; ALooser.Position := FPlayerList.Count - ALooser.PlayCount - 1; // Spielstatus auf beendet APlayClass.Status := ps_finish; Exit; end; // der Spielstand hat sich geändert if AProperty = 'PlayResult' then begin if (APlayClass.FPlayResult.Player1 <> 0) or (APlayClass.FPlayResult.Player2 <> 0) then begin // es gibt einen Spielstand <> 0 if APlayClass.FPlayResult.Player1 > APlayClass.PlayResult.Player2 then begin // Player1 hat gewonnen AWinner := APlayClass.Player1; ALooser := APlayClass.Player2; end else begin // Player2 hat gewonnen AWinner := APlayClass.Player2; ALooser := APlayClass.Player1; end; // neues Spiel für Gewinner ermitteln PlayerinGame(AWinner, APlayClass, True); // neues Spiel für Verlierer ermitteln PlayerinGame(ALooser, APlayClass, False); // Counter der gespielten Spiele der Spieler erhöhen AWinner.PlayCount := AWinner.PlayCount + 1; ALooser.PlayCount := ALooser.PlayCount + 1; // aktuelle Platzierung der Spieler setzen AWinner.Position := FPlayerList.Count - AWinner.PlayCount; ALooser.Position := FPlayerList.Count - ALooser.PlayCount - 1; // Spielstatus auf beendet APlayClass.Status := ps_finish; end; end; end; Die Procedure der PlayList macht jetzt folgendes. Erstens wird geschaut, ob der geänderte Parameter des Spiels der Spielstand oder der Typ des Spielers ist (Freilos bei Spieler). Ist ein gültiger Spielstand eingetragen, so wird der Gewinner und Verlierer des Spiels ermittelt. Dann werden diese an die Procedure PlayerinGame übergeben. Diese erhält folgender Werte: APlayer = Spieler der in ein neues Spiel eingetragen werden soll AOldPlay = Spiel das gerade zu Ende gespielt wurde winning = gibt an, ob der Spieler der Gewinner oder Verlierer des Spieles ist. Nun prüft die Procedure erst mal, welches Spiel das gerade gespielte Spiel ist, um das neue Spiel zu ermitteln, in das der aktuelle Spieler jetzt eingetragen werden soll. Der erste Block der Abfrage für den Gewinner sollte eigentlich soweit ok sein. Keinen Plan hab ich noch für den zweiten Block, Eintrag des Verlierers. Das vorallem wenn er ein V- oder G-Spiel verloren hat. Da die Procedure eine eigene Methode der PlayList ist, wird hier auf eigene Hilfsfunktionen zugegriffen. Das ist z.B. die Funktion GetPlay. GetPlay sucht in der Liste nach einem Spiel mit der angegebenen Bezeichnung und gibt die Instanz dieses Spieles als Ergebnis zurück. Wurde kein Spiel mit dieser Bezeichnung gefunden, so liefert die Funktion nil. Das ergibt natürlich, dass in der Liste alle Spiele schon eingetragen sind. Erledigt wird das bei der Übergabe der Spielerliste an die PlayList. Dabei wird auf Basis der Anzahl der in der PlayerList eingetragenen Spieler der gesamte Spielplan automatisch erstellt und alle Spiele eingetragen. Das ist auch schon fertig und hat so keine großen Probleme bereitet. Hier mal diese Funktion zur Kontrolle:
Delphi-Quellcode:
Du brauchst die Methoden hier nicht rauskopieren. Ich hab die Unit mit den Klassen schon fertig und hänge sie hier bei einem der nächsten Beiträge mit ran, dann kannst du sie dir direkt downloaden.
procedure TPlayList.UpdatePlayCount;
var APlayerCount : Integer; Counter, CRound : Integer; procedure AddPlays(AGame : Char; ARound, ANumberCount : Integer); var BCounter : Integer; begin for BCounter := 1 to ANumberCount div 2 - 1 do begin if not Assigned(GetPlay(AGame, ARound, BCounter)) then begin // Spiel ist noch nicht angelegt Add(TPlayClass.Create(AGame, ARound, BCounter)); end; end; end; begin if not Assigned(FPlayerList) or (FPlayerList.Count = 0) then begin Clear; end else begin Clear; APlayerCount := FPlayerList.Count; // bei ungerade Anzahl von Spielern einen dazu if odd(APlayerCount) then inc(APlayerCount); // R-Spiele anlegen AddPlays('R', 1, APlayerCount div 2); // G-Spiele anlegen Counter := APlayerCount div 4; CRound := 1; while (Frac(Counter/2) = 0) do begin AddPlays('G', CRound, Counter); inc(CRound); Counter := Counter div 2; end; // V-Spiele anlegen Counter := APlayerCount div 4; CRound := 1; while (Frac(Counter/2) = 0) do begin AddPlays('V', CRound, Counter); inc(CRound); if not odd(CRound) then Counter := Counter div 2; end; // Finale anlegen Add(TPlayClass.Create('F', 0, 0)); end; end; Ja, somit müssen wir nur noch die kleinen Probleme mit der Spielzuordnung für die Verlierer lösen und das Datenmodell ist fertig. Dann können wir uns um den visuellen Teil kümmern. Dann bis die Tage, Gruß oki
42
|
Zitat |
Registriert seit: 5. Mär 2008 131 Beiträge Delphi 2005 Personal |
#37
hallo Oki,
ich werde versuchen dir den Ablauf zu erklären, nimm bitte dazu den Spielplan den ich hier mal an ein post von mir angehängt habe zur Hand. R ist Runde1 hier beginnt das Turnier. Die Anzahl der Spieler beträgt entweder 8 oder 16 oder 32 oder 64 usw., sonst funktioniert ein Doppel KO System nicht. Die Gewinner jeder Paarung gehen in die Gewinnerrunde G1 die Verlierer in die Verliererrunde V1. Der Gewinner der Gewinnerrunde G1 geht weiter in die Gewinnerrunde G2 der Verlierer der Gewinnerrunde G1 geht in die Verliererrunde V2 und war an die jeweilige Position A,B,C usw. (gelbes Kästchen unterhalb der Paarung) welche bei der Gewinnerrunde G1 angegeben ist (Verlierer -> A). Der Verlierer aus der Verliererrunde V1 scheidet aus dem Turnier aus, weil er ein zweites mal verloren hat, der Gewinner der Verliererrunde V1 kommt weiter in die Verliererrunde V2 und trifft dort mit einem Verlierer aus der ersten Gewinnerrunde G1 zusammen. Schau dir den Plan genau an, dann weist du wann ein Verlierer der Gewinnerrunde in die Verlierrunde kommt und an welcher Position er weiterspielt, den Zwischendurch gibt es auch runden bei den Paarung rein von der Verlierrunde zusammentreffen(haben kein gelbes Kasten unterhalb der Paarung). Der Automat gehört nur bedingt zur Paarung, er ist für den eigentlichen Ablauf nicht notwendig.(praktisch nur der Spielort wo das Spiel stattfindet) sollte aber bei der paarung dabei sein wegen der Übersichtlichkeit. Ich hoffe, dass du das nun verstanden hast, solltest du dennoch noch fragen haben, stehe ich dir gerne zur Verfügung. bis dann Dieter |
Zitat |
Registriert seit: 30. Dez 2002 Ort: Brandshagen 1.819 Beiträge Delphi 2007 Professional |
#38
Hallo optiplex,
soweit habe ich den Spielplan verstanden. Der Punkt ist, dass es Sinn macht ein allgemeines Zuordnungsprinzip, einen Algorithmus zu finden, mit dem man mathematisch das nächste Spiel ermitteln kann. Somit wird die procedure universell und gilt für alle Anzahlen von Spielern, egal ob 8, 16, 32 usw. Man muss halt nicht für jede Anzahl von Spielern eine eigene Zuordnungsprocedure schreiben. Das habe ich versucht, bin an der erwähnten Stelle gescheitert. Da hatte ich auch noch nicht begriffen, dass das KO-System auf eine Spieleranzahl zur Basis 8 definiert ist. Ich erkläre mal meine Vorgehensweise für den Teil den ich bis jetzt in den Griff bekommen haben (dabei war die Annahme, dass ausschließlich eine gerade Anzahl von Spielern notwendig ist). [edit] Sorry, hier noch mal was die Eigenschaften bei TPlayClass (und somit für den Parameter APlayClass) bedeuten.
Delphi-Quellcode:
Bsp.:
FGame: Char; // Spiel; R, V, G
FNumber: Integer; // Spielnummer 1..x FPlayer1: TPlayerClass; // Spieler 1 FPlayer2: TPlayerClass; // Spieler 2 FPlayList: TPlayList; // übergeordnete PlayList FPlayResult: TPlayResult; // Ergebnis des Spiels FRound: Integer; // Runde FStatus: TPlayState; // Spielstatus R1-2 R = Game 1 = Round 2 = Number - = nur optischer Trenner im String. [/edit] In der procedure wird der Spieler der einem neuen Spiel zugeordnet werden soll, das aktuell gespielte Spiel sowie ein Flag ob der übergebene Spieler der Gewinner der Partie war übergeben: procedure TPlayList.ChangePlay(APlayClass: TPlayClass; AProperty : String); Als erstes prüfe ich, ob der Spieler der einem neuen Spiel zugeordnet werden soll ein Gewinner ist:
Delphi-Quellcode:
Jetzt berücksichtige ich, welches Spiel das gerade gespielte Spiel war:
if winning then begin
// Spieler ist Gewinner des alten Spieles
Delphi-Quellcode:
Also, der Spieler hat in einer Runde 'R' (erste Spielrunde aller Spieler) gewonnen. Anhand des Spielplanes hab ich eine recht einfache logische Folge entdeckt. Der Gewinner einer Runde "R" geht wie folgt als Spieler in ein Spiel der Runde "G" :
case ORD(AOldPlay.FGame) of
ORD('R') : begin // Gewinner der ersten Runde Gewinner aus: R1 wird erster Spieler G1 R2 wird zweiter Spieler G1 R3 wird erster Spieler G2 R4 wird zweiter Spielr G2 .... und endlos so weiter. Daraus folgt, das der Gewinner aller ungeraden Spielnummern für "R" immer der erste Spieler des folgenden Gewinnerspieles wird und der Gewinner mit den geraden Spielnummern für "R" immer der zweite Spieler. Die Nummer des zu ermittelnden "G"-Spieles ist immer das Ergebnis die auf eine gerade Zahl aufgerundete Spielnummer von "R" geteilt durch 2. R-Nummer wird zur G-Nummer 1 -> 1 2 -> 1 3 -> 2 4 -> 2 ......... 17 -> 9 18 -> 9 19 -> 10 20 -> 10 ......... somit entstehr folgender Code:
Delphi-Quellcode:
Soweit so gut. Das lässt so einfach für alle Spieler ermitteln, die Gewinner einer Runde sind, Egal ob sie vorher einmal verloren haben. Ich denke unter dieser Erläuterung sollte der Code für die gewonnenen "G" und "V"-Spiele nachvollziehbar sein, auch wenn er einer etwas anderen Logik folgt.
if Odd(AOldPlay.Number) then begin // Gewinner einer ungeraden Spielrunde
NewPlay := GetPlay('G', 1, (AOldPlay.Number+1) div 2); // das Spiel "G1-x" holen, wobei x gleich (y+1)/2 aus R1-y für das ungerade Spiel ist if Assigned(NewPlay) then NewPlay.FPlayer1 := APlayer; // wird Spieler 1 end else begin // Gewinner einer geraden Spielrunde NewPlay := GetPlay('G', 1, (AOldPlay.Number) div 2); // // das Spiel "G1-x" holen, wobei x gleich y/2 aus R1-y für das gerade Spiel ist if Assigned(NewPlay) then NewPlay.FPlayer2 := APlayer; // wird Spieler 2 end; In den weiteren Spielrunden für "G" und "V" prüfe ich zusätzlich, ob wirklich ein neues Spiel gefunden wurde. Ist dies nämlich nicht der Fall, so ist der Gewinner ein Teilnehmer für das Finale. Da gibt es keinen Ausweg.
Delphi-Quellcode:
Dabei ist recht einfach zu erkennen, dass der Gewinner eines "G"-Spieles der erste Spieler des Finales und der Gewinner des "V"-Spieles der zweite Spieler des Finales wird (für mich ist das aber wurscht, es bleiben eh nur zwei übrig; wer das erster oder zweiter Spieler ist scheint wohl nur für die Profis wichtig zu sein).
if Assigned(NewPlay) then begin
NewPlay.FPlayer1 := APlayer; end else begin // das war das letzte Gewinnerspiel, ab ins Finale NewPlay := GetPlay('F', 0, 0); if Assigned(NewPlay) then NewPlay.Player1 := APlayer; end; Soweit war das alles recht logisch. Meine Probleme fangen mit den Verlierern der "G" und "V"-Spiele an. Für die Verlierer der R-Spiele ist das so einfach wie oben beschrieben bei den Gewinnern. Ich habe folgendes gesehen (für 16 Spieler) Verlierer des Spiels geht in Spiel: Gx-y -> Va-b G1-1 -> V2-4 2.Spieler G1-2 -> V2-3 2.Spieler G1-3 -> V2-2 2.Spieler G1-4 -> V2-1 2.Spieler G2-1 -> V4-2 2.Spieler G2-2 -> V4-1 2.Spieler G3-1 -> V6-1 2.Spieler da steckt auch ein System dahinter. Schau mal, ob du das umgesetzt bekommst. Das sollte rein mathematisch gehen. Ein Ansatz ist, dass für 16 Spieler 4 G1 Spiele existieren, wobei das Va-b Spiel a=x*2 und b=16/4-y-1 ist. x und y entnimmt man Gx-y. Jo, so klappts. Das ganze muss jetzt noch für die Verliererspiele ausgetüftelt werden. Läßt sich mit dem neu ermittelten Spielnamen kein Spiel in der Spielliste finden, so ist das Turnier für diesen Spieler zu ende. Die Berechnung der Platzierung ist bei mir noch falsch, aber dazu später. Gruß oki
42
|
Zitat |
Registriert seit: 30. Dez 2002 Ort: Brandshagen 1.819 Beiträge Delphi 2007 Professional |
#39
Ähhm, das sieht jetzt aber nicht so schwer aus:
Delphi-Quellcode:
"V"-Spiele muss noch. Neu ist der Teil:
// Spieler ist Verlierer des alten Spieles
case ORD(AOldPlay.FGame) of ORD('R') : begin // Gewinner der ersten Runde if Odd(AOldPlay.Number) then begin NewPlay := GetPlay('V', 1, (AOldPlay.Number+1) div 2); if Assigned(NewPlay) then NewPlay.FPlayer1 := APlayer; end else begin NewPlay := GetPlay('V', 1, (AOldPlay.Number) div 2); if Assigned(NewPlay) then NewPlay.FPlayer2 := APlayer; end; end; ORD('G') : begin NewPlay := GetPlay('V', AOldPlay.Round*2, 16/4 - AOldPlay.Number - 1); if Assigned(NewPlay) then NewPlay.FPlayer2 := APlayer; end; ORD('V') : begin // das wars dann, kein weiteres Spiel :-( // oder doch? :-) hab ich das System aber auch noch nicht durchschaut end; end;
Delphi-Quellcode:
umgesetzt wie vorher beschrieben. Sieht irgendwie zu einfach aus.
ORD('G') : begin
NewPlay := GetPlay('V', AOldPlay.Round*2, 16/4 - AOldPlay.Number - 1); if Assigned(NewPlay) then NewPlay.FPlayer2 := APlayer; end; Hab ich da was verpennt? Gruß oki
42
|
Zitat |
Registriert seit: 5. Mär 2008 131 Beiträge Delphi 2005 Personal |
#40
Hallo Olaf,
das mit der Basis 8 ist falsch, damit ein Spielplan aufgeht egal ob Doppel KO oder einfach KO benötigst du immer 2,4,8,16,32,64,128 usw spieler sonst geht das Turnier einfach nicht auf. deshaslb musst du fehlende Spieler durch Freilose ersetzen und diese Freilose must du an bestimmten stellen einsetzen damit jedes Freilos Spätestens in der 2 Verliererrund ausscheidet. Siehe Beispiel (Anhang Plan.jpg) dies sind 12 Parungen=24 Spieler und das Turnier geht nicht auf. Ist ein Spieler in der Verliererrunde und verliert dann ist er ausgeschieden hier kommt nur der Gewinner weiter. Ich habe dir gleich gesagt, dass es so einfach nicht ist, wie du dir das am Anfang vorgestellt hast. Gruss Dieter |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |