# Programmentwurf



## n00b4u (16. Dez 2015)

Guten Tag zusammen, ich bin neu hier und hoffe das ändert sich schnell 

*Warnung! Nur lesen, wenn man Zeit und Lust hat, viel zu lesen und einen Programmentwurf zu zerpflücken! *

Ich möchte mich kurz vorstellen, oder besser gesagt kurz umreißen wo ich wissenstechnisch stehe, ehe ich meine Frage auf das Forum loslasse. Meine Erfahrungen mit Java sind eher theoretischer Natur durch mein Studium. Produktiv programmiert habe ich bisher im .Net-Bereich vornehmlich VB.Net und hier Anpassungen für bestehende ERP-Systeme. Darüberhinaus habe ich erste Gehversuche mit PHP und C# hinter mir.

Da ich mich in letzter Zeit wieder mehr mit Linux/Unix beschäftige, wollte ich meine Java-Kenntnisse vertiefen und habe mir mal ein recht "sportliches" Objekt zurechtgelegt um einzusteigen.


Ich bastle gerade an einem Fussballmanager und habe schon einige Klassen dafür entworfen. Ich bin aber an einem Punkt, an dem mich Fragen beschäftigen die für das weitere Vorgehen durchaus wichtig sind und da ich bisher nur in bestehenden Systemen Erweiterungen programmiert habe, fehlt mir eindeutig die Erfahrung in der Bewertung und Planung meines weiteren Vorgehens.

Kurzum ich habe drei Kernprobleme die ich gerne einem erfahrenem Publikum erörtern möchte und mich über Hilfestellung freuen würde.

1. Die Datenhaltung. Bisher habe ich vornehmlich Erfahrungen mit MSSQL, da ich aber Java programmieren möchte um plattformunabhängig zu sein und wie gesagt erst richtig einsteige, frage ich mich, sollte ich auf mySQL setzen oder alle Spiel- und Speicherstände sowie Objekte einfach in XML-Dateien flanschen? Schön ist das sicher nicht, aber ich denke die wenigsten Spiele (vor allem im Eigenbau, haben ne eigene DB-Engine am laufen oder?)

2. Ich poste mal meine Klassen bisher. Da mir das Fingerspitzengefühl etwas fehlt um die Granularität gut einschätzen zu können, wäre ein Feedback hilfreich, ob ich die Klassen noch weiter aufsplitten soll oder ob ich einzelne Elemente anders lösen sollte, Stichwort Interfaces.

3. Ich habe eine Klasse Spielfeld die über eine Länge und eine Breite verfügt, wenn ich auf dem Spielfeld mit Koordinaten arbeiten möchte, sollte ich dann einen eigenen Datentyp für Koordinate mit x- und y-Wert erstellen? So dass ich den Elementen auf dem Feld, Spieler und Ball jeweils die Position zuordnen kann, oder sollte ich dabei bleiben, jedem Element zwei int Werte x_koordinate und y_koordinate zuweisen und diese dann über die Methoden ändern?

Das würde erstmal reichen und ist denke ich auch genug. Ich bedanke mich vorab schon bei allen, die sich die Mühe machen, das alles zu lesen.

Für Anregungen, Kritik und Hilfe bin ich immer dankbar.

Es folgt der Quelltext:

Klasse Team


```
// Alles was einen Fussballclub ausmacht
// @ranking wird verwendet um die Wahrscheinlichkeit von Spielerwechseln zu einem
// bestimmten Team zu bestimmen. Messi würde sicher nicht für Freiburg spielen
// ranking wird aufsteigend von 1 bis 10 gewertet.
// @fanBase gibt die Fanbase zu Spielbeginn an, mit steigendem Ranking steigt auch die Fanbase. Je mehr Fans desto höher der Umsatz an Fanartikeln.
// @tabellenPlatz gibt die aktuelle Platzierung innerhalb der Liga an

public class Team {
    private String teamName;
    private double startKapital;
    private int fanBase;
    private int ranking;

    private String country;
    private int tabellenPlatz;
    private int staerke;
    private boolean istMeister;
    private boolean istAbsteiger;
    private boolean istAufsteiger;
    private boolean internationalerWettbewerb;
    private boolean istImPokal;
    private boolean istLandesPokalsieger;
    private boolean istInternationalerPokalsieger;
    private boolean schulden = false;
    private int punkteMeisterschaft;
    private int maxKaderplaetze = 25;
    private int startaufstellung = 11;
    private int ersatzbank = 7;
    private Spieler[] spieler;
    private Liga liga;
    private int form;
    private boolean ballbesitz;

    // Methoden zum Erstellen der Teamnamen 
    public Team(String name, String land, int liga, double startkapital, int ranking, int fanbase, boolean istImPokal, boolean spieltInernational, boolean istAufsteiger, boolean istMeister, boolean istAbsteiger){     
        this.teamName = name;
        this.country = land;
        this.startKapital = startkapital;     
    }
 
    public void setTeamName(String nameTeam) {
        this.teamName = nameTeam;
    }
 
    public String getTeamName(){     
        return teamName;
    }
 
    // Methoden die das Kapital des Teams festsetzen und anschließend aktualisieren
    public void setStartkapital(double kapital){     
        if (kapital < 0){         
            schulden = true;
            this.startKapital = kapital;
        }     
        this.startKapital = kapital;
    }
 
    public double getStartkapital(){
    return startKapital;  
    }

    public void updateKapitalKauf(double betrag){     
        if(startKapital >= betrag){         
            this.startKapital = startKapital -betrag;
        }else {         
            this.startKapital = startKapital - betrag;
            schulden = true;         
        }  
    }
 
    // Methoden die die Fanbase betreffen
    public void setFanBase(int fanBase){     
        this.fanBase = fanBase;
    }

    public int getFanbase(){     
        return fanBase;
    }
 
    public void updateFanBase(int fanbaseUpdate){
        // Methode zum erhöhen oder verringern der Fans.
    }
 
    // Methoden die das Ranking beeinflussen
 
    // Methoden die die Liga sowie das Land festlegen
 
    // Methoden zur Ermittlung der Punkte der laufenden Saison
 
    // Methoden zur Ermittlung des Meisters und der Ab- und Aufsteiger
  
public void getStartaufstellung(Spieler spieler[]){
}
}
```

Klasse Spieler


```
* Spieler haben folgende Attribute
* ein String der den Vornamen und ein String der den Nachnamen bildet
* ein double der den Marktwert des Spielers darstellt, dieser Marktwert ändert sich wenn sich die Attribute des Spielers ändern
*
* Folgende Attribute haben Einfluss auf die Fähigkeiten der Spieler:
* int alter, je jünger ein Spieler ist, desto höher ist seine Entwicklungserwartung, je älter ein Spieler wird, desto mehr büßt er an Fähigkeiten ein
* int ausdauer, gibt im Wertbereich von 0 bis 90 an, wie viel Ausdauer ein Spieler hat, wobei 90 für bis zu 90 Minuten reicht.
* int geschwindigkeit gibt an, wie schnell der Spieler ist, Wertbereich von 0 bis 90
* int passgenauigkeit gibt an wie wahrscheinlich ein erfolgreicher Pass ist, 90 entspricht einer Wahrscheinlichkeit von 95%
* int groeße gibt an wie groß ein Spieler ist, größere Spieler sind etwas langsamer als kleinere Spieler, haben aber dafür grundlegend höhere Ausdauer und Kopfballstärken
* int kopfball gibt an wie hoch die wahrscheinlichkeit von gewonnen Kopfballduellen ist, 90 entspricht einer Wahrscheinlichkeit von 95%
* int gewicht, gibt das Gewicht eines Spielers an, schwere Spieler sind langsamer als leichte Spieler, haben aber erhöhte Zweikampfwerte
* int zweikampfwert gibt an, mit welcher Wahrscheinlichkeit ein Zweikampf von einem Spieler gewonnen wird 90 entspricht einer Wahrscheinlichkeit von 95%
* int dribbling gibt an, wie schnell der Spieler mit dem Ball am Fuss ist, ein wert von 90 entspricht einer Geschwindigkeit mit Ball von 85
* int reflexe gibt bei Torhütern die Fähigkeit an, auf der Linie zu halten eine Stärke von 90 entspricht einer Wahrscheinlichkeit von 75% den Ball zu halten.
* string hauptposition gibt die beste Position des Spielers an z.B. LV, IV, RV, RM, LM, DM, ZM, LA, RA, HS, MS, LIB, TW,
* string nebenposition1 gibt die Nebenposition des Spielers an analog zur Hauptposition abzüglich eines Malus von 5 bis 10% der Stärke
* string nebenposition2 gibt eine zweite Nebenposition des Spielers analog zur Hauptposition an , abzüglich eines Malus von 7 bis 15% der Stärke
* int talent gibt an, wie schnell ein Spieler neue Fertigkeiten erlernt, maximalwert ist 5, bei dem Maximalwert kann ein Spieler Fähigkeiten schneller erlangen
* boolean istFit gibt an, ob ein Spieler verletzt oder fit ist.
* int muedigkeit gibt an, wie frisch ein Spieler ist, spielt ein Spieler ein Spiel durch verliert er 5 Frischepunkte und kann durch aussetzen oder Regeneration wieder hergestellt werden
* int Gesamtstärke ist ein Koeffizient der Fähigkeiten der Spieler bezogen auf die Position:
*
* Für Stürmer wie folgt: ((Ausdauer *2) + (geschwindikeit *3) + (passgenauigkeit) + ((kopfball *2) + (muedigkeit) + (dribbling *2)  + zweikampf ) / 11
* Für Mittelfeldspieler: ((Ausdauer *3) + (geschwindigkeit *2) + (passgenauigkeit *2) + kopfball + muedigkeit + (dribbling *2) + (zweikampf *2)  / 13
* Für Abwehrspieler: ((Ausdauer *3) + (geschwindigkeit *2) + (passgenauigkeit *2) + (kopfball *2) + (muedigkeit) + (dribbling) + (zweikampf *2) / 13
* Für Torhüter: ((Ausdauer *3) + (reflexe *3) + (muedigkeit *2) + (zweikampf *2) / 10
*
*
*
*/

public class Spieler {
    private Team team;
    private String vorname;
    private String nachname;
    private int alter;
    private double marktwert;
    private int ausdauer;
    private int geschwindigkeit;
    private int passgenauigkeit;
    private int kopfball;
    private int zweikampf;
    private double gehalt;
    private int talent;
    private int dribbling;
    private int muedigkeit;
    private int gesStaerke;
    private String hauptposition;
    private boolean istFit;
    private String nebenposition1;
    private String nebenposition2;
    private int reflexe;
    boolean hatBall;
 
    //Methoden zum setzen der Attribute
    public void setVorname(String vorname){
        this.vorname = vorname;     
    }
 
    public String getVorname(){
        return vorname;     
    }

    public void setNachname(String nachname){     
        this.nachname = nachname;
    }
 
    public String getNachname(){
        return nachname;
    }
 
    public void setGeschw(int geschw){     
        this.geschwindigkeit = geschw;     
    }
 
    public int getGeschw(){     
        return geschwindigkeit;
    }
 
    public void setAusdauer(int ausdauer){
        this.ausdauer = ausdauer;
    }
    public int getAusdauer(){
        return ausdauer;
    }
    public void updateAusdauer(int updateAusdauer){     
        this.ausdauer = ausdauer + updateAusdauer;
    }
 
    public void setGesamtstaerkeHP(){ 
        if (hauptposition == "ms" | hauptposition == "la" | hauptposition == "ra" |hauptposition == "hs" ){
            gesStaerke = ((ausdauer *2) + (geschwindigkeit *3) + (passgenauigkeit) + (kopfball *2) + (muedigkeit) + (dribbling *2)  + zweikampf ) / 11;   
    }
        if (hauptposition =="dm" | hauptposition == "zm" | hauptposition == "lm" | hauptposition == "rm" | hauptposition == "om"){
        gesStaerke =     ((ausdauer *3) + (geschwindigkeit *2) + (passgenauigkeit *2) + kopfball + muedigkeit + (dribbling *2) + (zweikampf *2))  / 13 ;
        }
        if (hauptposition == "iv" | hauptposition == "lv" | hauptposition== "rv" | hauptposition == "lib"){
            gesStaerke = ((ausdauer *3) + (geschwindigkeit *2) + (passgenauigkeit *2) + (kopfball *2) + (muedigkeit) + (dribbling) + (zweikampf *2) )/ 13;
        }
        if(hauptposition == "tw"){
            gesStaerke = ((ausdauer *3) + (reflexe *3) + (muedigkeit *2) + (zweikampf *2)) / 10 ;
        }
    }
 
    public int getGesStaerke(){     
        return gesStaerke;
    }
 
    public void setMarktwert (int alter, int gesStaerke, int talent){     
        double bonusAlter = 1.0;     
        if (alter >=  16 && alter <23 ){
            bonusAlter = 8.5;         
        }     
        if(alter >= 23 && alter < 26 ){
            bonusAlter = 5.5;
        }     
        if (alter >= 26 && alter < 30){
            bonusAlter = 3.0;
        }     
        if (alter >=30 ){         
            bonusAlter = 1.0;         
        }
        this.marktwert = (((gesStaerke *3)+ (talent * 2)) * bonusAlter ) * 10000;
    }
}
```

Klasse Stürmer die von Spieler abgeleitet wird


```
public class Stuermer extends Spieler{
    private Spielfeld spielfeld;
    private int aktuellePosition;
    private int x_koordinate;
    private int y_koordinate; 
 
    private void setStartposition(){     
        x_koordinate = 82;
        y_koordinate = 34;
    }
 
    private int laufNachLinks(){     
         int Stuermergeschwindigkeit = getGeschw();
        if (y_koordinate > 1 && y_koordinate < 165){
        y_koordinate = y_koordinate - Stuermergeschwindigkeit;     
        }else{         
            laufNachRechts();
        }
        return y_koordinate;
    }
 
    private int  laufNachRechts(){     
         int Stuermergeschwindigkeit = getGeschw(); 
            if (y_koordinate > 1 && y_koordinate < 165){  
            y_koordinate = y_koordinate + Stuermergeschwindigkeit;
            }else{
                laufNachLinks();
            }
            return y_koordinate;
    }
```

Klasse Spielfeld

```
public class Spielfeld {
    public int laenge = 165;
    public int breite = 68;
    public int flaeche = breite * laenge;
}
```

Desweiteren umfasst das Programm noch andere Klassen, wie Liga, Pokal und Spiel( in der die Spielmechanik) implementiert werden soll. Wie gesagt ich bin was JAVA betrifft fast blutiger Anfänger und bin um alle sachdienlichen Hinweise dankbar.


P.S. Das ganze dient für mich als Lernprojekt. Ich denke es ist in den Grundzügen wirtschaftlich genug um reale Probleme abzubilden und thematisch interessant genug um mich lange zu fesseln.


----------



## Thallius (16. Dez 2015)

Zu 1) Ich würde mit Sqlite arbeiten

Gruß

Claus


----------



## Dukel (16. Dez 2015)

Zu 1.
Die Frage ist, was du wofür speichern willst.
Wenn es nur um die Datenhaltung geht und du keine Logik in der DB implementieren willst dann sollte das Produkt egal sein. Du solltest das dann Datenbankunabhängig schreiben (z.b. mit einem OR Mapper oder generischen Funktionen).


----------



## VirtualIndex (16. Dez 2015)

Ein paar generelle Anregungen:

a) Überarbeite deine Formatierung: Einrückungen und Abstände (Zeilen, Leerzeichen)
b) Räume deine ifs auf: du hast ifs die in jedem Fall das gleiche tun. Das dann außerhalb des ifs und nur den situationsbedingten Teil im if lassen. Erhöht den Lesefluss.
c) Vermeide _ und nutze stattdessen camelCase.
d) Brauchst du all diese Variablen an dieser Stelle? Können welche zu Methodenvariablen werden? Vielleicht umstrukturieren? So sieht das sehr klobig aus.

Grüße VirtualIndex


----------



## n00b4u (16. Dez 2015)

@Dukel 

Naja ich möchte gerne die Objekte speichern, sprich, Spieler, Mannschaften, dann im weiteren Verlauf des Projekts, natürlich Spielergebnisse, Punkte, Tordifferenz etc. Da kommt schon einiges an zu speichernden Daten zusammen. 

@claus 

Danke, gibt es auch Gründe für SQLite? Besondere Kompatibilität zu JAVA? 

@VirtualIndex

Welche IFs machen das gleiche? Gerne werde ich deinen Rat befolgen, sobald ich ihn verstehe. Ich könnte mit Sicherheit die Positionsabfrage mit switch case strukturieren. Aber ich steh auf dem Schlauch mit die machen das gleiche. 

Der Punkt mit den Variablen ist gut. Daher ja auch meine Frage ob ich eventuell Teile in Unterklassen auslagern sollte oder auf Interfaces zugreifen. Wie gesagt ich bin Anfänger und mir geht es hier eher um strukturelle Verbesserungen als knallhartes coding. Ich will ja was lernen dabei. 

Danke euch aber auf jeden Fall fürs Lesen.


----------



## VirtualIndex (16. Dez 2015)

Ich nehme mal 3 Methoden als Beispiel:

```
public void setStartkapital(double kapital){

        if (kapital < 0){

            schulden = true;
            this.startKapital = kapital;
        }

        this.startKapital = kapital;
    }

    public double getStartkapital(){
    return startKapital;
    }

    public void updateKapitalKauf(double betrag){

        if(startKapital >= betrag){

            this.startKapital = startKapital -betrag;
        }else {

            this.startKapital = startKapital - betrag;
            schulden = true;

        }


    }
```

sähe bei mir so aus:


```
public void setStartkapital(double kapital){
        if (kapital < 0){
            schulden = true;
        }
        startKapital = kapital;
    }

    public double getStartkapital(){
        return startKapital;
    }

    public void updateKapitalKauf(double betrag){
        if(startKapital < betrag){
            schulden = true;
        }
        startKapital = startKapital - betrag;
    }
```

Das Schlüsselwort this kann weg, da es bereits eindeutig ist.
Speziell die updateKapitalKauf-Methode ist kompakter, klarer und tut weniger so.


----------



## Thallius (16. Dez 2015)

Sqlite bietet eine recht ordentliche Datenbank Funktionalität auf Dateibasis. Das bedeutet dein Programm interagiert mit Sqlite wie mit jeder anderen DB über queries und dadurch kann die modelschicht später auch sehr einfach durch was größeres ausgetauscht werden wenn es mal nötig werden sollte. Weiterhin kann man es eben sehr leicht in sein Programm integrieren und muss eben nicht extra eine Datenbank installieren. Du hast dann alle deine Daten in einer Sqlite Datei die du sehr einfach schon vorgefüllt mit ausliefern kannst. Man kann auch nicht so einfach die Daten manipuliert wie bei einer XML wo sich ja jeder der einen Texteditor öffnen kann, mal eben seine eigenen Spielstände bauen kann.

Gruß

Claus


----------



## n00b4u (17. Dez 2015)

@VirtualIndex

Ok, Danke. Macht natürlich Sinn. Werde deinen Rat befolgen. 

@claus

Danke für die Erklärung. Hört sich interessant an. Habe mich zwar noch nicht wirklich mit SQLite beschäftigt, aber ich denke das könnte sich lohnen.


----------



## Joose (17. Dez 2015)

n00b4u hat gesagt.:


> Ich bastle gerade an einem Fussballmanager und habe schon einige Klassen dafür entworfen.



Nur einen Fußballmanager oder einen Fußballmanager mit einer Spielesimulation?
Wenn es wirklich nur ein Fußballmanager sein soll, dann verstehe ich nicht wozu du eine Klasse Spielfeld brauchst, bzw. der Stuermer nach links/rechts laufen kann.
Wenn du aber natürlich auch eine Spielsimulation anbieten willst (ala FIFA) dann sind diese Klasse und Methoden natürlich berechtigt.



n00b4u hat gesagt.:


> 1. Die Datenhaltung. Bisher habe ich vornehmlich Erfahrungen mit MSSQL, da ich aber Java programmieren möchte um plattformunabhängig zu sein und wie gesagt erst richtig einsteige, frage ich mich, sollte ich auf mySQL setzen oder alle Spiel- und Speicherstände sowie Objekte einfach in XML-Dateien flanschen? Schön ist das sicher nicht, aber ich denke die wenigsten Spiele (vor allem im Eigenbau, haben ne eigene DB-Engine am laufen oder?)



Hier gibt es viele Möglichkeiten. Es kommt am Ende eben auch darauf an ob es nur ein Singleplayer Spiel ist oder ob man auch gegen andere User spielen kann.
Wenn es nur lokal sein soll dann ist SQLite eine gute Wahl. Wenn es globaler sein soll, dann sollte man schon eher was anderes wählen.



n00b4u hat gesagt.:


> 2. Ich poste mal meine Klassen bisher. Da mir das Fingerspitzengefühl etwas fehlt um die Granularität gut einschätzen zu können, wäre ein Feedback hilfreich, ob ich die Klassen noch weiter aufsplitten soll oder ob ich einzelne Elemente anders lösen sollte, Stichwort Interfaces.



Zu deiner Klasse Team:
Ich finde es unpraktisch den Tabellenplatz sowie die Punkte der Meisterschaft in dem Team Objekt zu speichern.
Einerseits werden diese mit jedem Spieltag angepasst, andererseits wenn du eine neue Saison beginnst gehen diese Daten für die vorherige Saison verloren.
Schreibe stattdessen dafür lieber eine Klasse Tabelle welche sich darum kümmert, dort kannst du für jedes Team die Punkte speichern je Saison. Die Tabellenplatzierung musst du gar nicht speichern, die ergibt sich ja dann von den Punkten usw.
-> Genereller Tipp: Nicht für jeden möglichen Wert einfach Attribute anlegen damit der Wert gespeichert werden kann. Viele Werte sind abhängig von anderen und sollten lieber zur Laufzeit auf Basis dieser berechnet werden.
Sprich die Punkte werden auf Basis der "Spielergebnisse" berechnet und die Platzierung anhand der Punkte (sowie bei Punktegleichstand anhand weiterer Kriterien).

Was auch eher hinderlich sein wird is das speichern von den ganzen boolschen Werten "istMeister", "istAbsteiger", "istAufsteiger", .....
Es ist auch wieder von Saison zu Saison unterschiedlich wer Meister, Absteiger bzw. Aufsteiger ist (oder international spielt).
Zweitens ob ein Team Meister, Aufsteiger oder Absteiger ist ergibt sich eben wieder anhand der Tabelle.

Zu dem Attribut "ballbesitz": Diesen gehört nicht zur Klasse Team. Bei jedem Spiel wechselt der Ballbesitz häufig zwischen den beiden Teams. Bei der jetztigen Lösung musst du immer beide Teams bearbeiten. Bei dem einen setzt du "ballbesitz" auf false, bei dem anderen auf true.
Einfacher wäre es in einer Klasse Spiel ein Attribut vom Typ Team zu haben "aktuellerBallbesitz". So musst du nur im Spiel Objekt max 1 Attribut ändern um den Ballbesitz anzupassen. (analog dazu verhält es sich mit "hatBall" von der Klasse Spieler)

Auch die Methode "getStartaufstellung()" gehört meiner Meinung nach in die Klasse Team, diese kann von Spiel zu Spiel variieren.

Zu deiner Klasse Spieler:
Anmerkung: String werden nicht mit "==" verglichen sondern mit "equals"!
Hier kann man im großen und ganzen wenig aussetzen.
Einzig eine gewisse Vererbungshierarchie würde ich einführen. Bei einem Fußballmanager kann man neben Spielern ja noch weitere "Figuren" im Club anstellen (Arzt, alle Arten von Trainer, Platzwart, Manager, Fanbeauftragter, ...)
Jede dieser Figuren gehört zu einen "Team" hat einen "Vornamen" und "Nachnamen" und bezieht ein "Gehalt". Trainer und Spieler haben einen gewissen "Marktwert", ein Arzt eine gewisse "Berufserfahrung" ebenso wie Platzwart und Manager.

Anstatt das "alter" eines Spielers zu speichern, speichere lieber das Geburtsdatum, einerseits ist es schöner dieses anzuzeigen, andererseits kannst du dir davon immer das aktuelle Alter ausrechnen (anders müsstest du in gewissen Abständen immer das "alter" bei jedem Spieler anpassen).
Für die jeweiligen Attribute des Spielers stellt sich die Frage ob ein float/double nicht passender wäre als int.
Bei dem Marktwert und Gehalt solltest du auf jedenfall auf einen anderen Datentyp setzen (BigDecimal). double ist für sowas ungeeignet -> ungenau!
Anstatt die Position per String festzulegen solltest du dafür ein Enum verwenden. Was mir abgeht beim Spieler wäre noch ob "links", "rechts" oder "beidbeinig" 

Allgemein: Ich bin mir nicht sicher ob für ein Fußballmanager (sowie es teilweise auschaut inkl Spielsimulation) nicht etwas schwierig umzusetzen ist. Es gibt dabei so viele Aspekte zu beachten und die ganze Berechnungen zur Stärke, Wahrscheinlichkeit usw. sind kompliziert und schwierig in richtiger Balance zu halten.
Versuche nicht gleich alles auf 1x zu implementieren, sondern arbeite dich immer näher an das Ziel ran. Gleich zu Beginn bei einem Spieler neben der Position auch noch Dribbling, Geschwindigkeit, Ausdauer/Müdigkeit, Kopfballstärke, Passgenauigkeit usw. einzubeziehen macht es unnötig kompliziert.
Verwende am Anfang nur 1-3 unterschiedliche Attribute um es einfach zu halten. Wenn du dann einen Spielablauf simulieren kannst und dieser halbwegs balanciert und logisch abläuft kannst du weitere Faktoren noch hinzufügen.


----------



## n00b4u (17. Dez 2015)

@ Joose vielen Dank für deine ganzen Anmerkungen. 

Zum Thema Spielfeld - Spielmechanik. 

Eigentlich möchte ich das Spiel an sich grafisch gar nicht darstellen. Vielmehr, sollen die Aktionen Textbasiert in ner Art Ticker ausgegeben werden. Allerdings hat jeder Spieler zu jedem Zeitpunkt ja ne Position auf dem Spielfeld. Diese wird im Endeffekt verwendet um einen Spielzug zu erzeugen. 5Meter vor dem gegnerischen Tor, wird man keinen Rückpass auf den eigenen Torwart spielen, zudem soll der eigene Torwart nicht auf die Idee kommen, nen Torschuss abzugeben. Als Beispiele. 

Ist eine Mannschaft in Ballbesitz, wird der Spieler und seine Position ermittelt und abhängig davon durch einen "Würfel" der nächste Spielzug ausgewürfelt. Schlägt der Würfelwurf fehl, geht der Ballbesitz an den Gegner usw... 

Das mit dem String bei den Positionen ist mir auch aufgefallen, werden da aber wohl auf switch-case umsteigen. 

Zum Thema Alter, hätte ich die simpelste aller Lösungen verwendet, da ich ohnehin keine originalen Spieler nutzen kann, wird am Anfang jeder Spieler mit einem int alter initialisiert und nach der Saison um 1 inkrementiert. 

Wenn ich dich richtig verstehe, rätst du mir alles was mit einem Spiel zu tun hat, auch dorthin auszulagern. Sprich Startaufstellung, Auswechselspieler, etc. ?


----------



## Joose (17. Dez 2015)

n00b4u hat gesagt.:


> Eigentlich möchte ich das Spiel an sich grafisch gar nicht darstellen. Vielmehr, sollen die Aktionen Textbasiert in ner Art Ticker ausgegeben werden. Allerdings hat jeder Spieler zu jedem Zeitpunkt ja ne Position auf dem Spielfeld. Diese wird im Endeffekt verwendet um einen Spielzug zu erzeugen. 5Meter vor dem gegnerischen Tor, wird man keinen Rückpass auf den eigenen Torwart spielen, zudem soll der eigene Torwart nicht auf die Idee kommen, nen Torschuss abzugeben. Als Beispiele.


Ok aber dann muss dein Spieler ja nicht wirklich nach links/rechts laufen können. Auch brauchst du dann meiner Meinung nach keine Klasse Spielfeld mit irgendwelchen Koordinaten.
Sondern wie du schon sagt über einen Wahrscheinlichkeit (abhängig von vielen Faktoren) wird der nächste "Zug" generiert. Sprich Pass von Spieler zu Spieler, Fehlpass, Foul, Tor, ....
Eine pixel genaue Berechnung das Spieler A hier und dort hin läuft und dann ein Pass fehlschlägt ist unnötig (und kompliziert).



n00b4u hat gesagt.:


> Das mit dem String bei den Positionen ist mir auch aufgefallen, werden da aber wohl auf switch-case umsteigen.


Wie schon gesagt: Verwende ein Enum für die Positionen. Die if-Bedingungen selber sind nicht das Problem nur der Vergleich von Strings ist eben falsch.



n00b4u hat gesagt.:


> Zum Thema Alter, hätte ich die simpelste aller Lösungen verwendet, da ich ohnehin keine originalen Spieler nutzen kann, wird am Anfang jeder Spieler mit einem int alter initialisiert und nach der Saison um 1 inkrementiert.


Du musst ja keine originalen Spieler verwenden (obwohl das für ein privates Projekt kein Problem darstellen sollte). Du kannst dir ja auch einfach ein paar Werte ausdenken, oder Daten von realen Spielern nehmen und nur ein bisschen durchmischen.



n00b4u hat gesagt.:


> Wenn ich dich richtig verstehe, rätst du mir alles was mit einem Spiel zu tun hat, auch dorthin auszulagern. Sprich Startaufstellung, Auswechselspieler, etc. ?


Genau, es ist zwar die Aufstellung und die Wechselspieler von Team A oder B, aber diese sind von Spiel zu Spiel anders (Taktik Umstellung, Verletzung usw.)
Wenn du diese Daten alle im Team speicherst wirst du nie die Möglichkeit haben dir die Aufstellung von Runde X anzuschauen. Auch die Aufstellung fürs nächste Spiel könnte von den bisherigen Aufstellungen und deren Erfolg abhängen.

Aber wie schon gesagt bevor man alle großartig aufbläht (Möglichkeiten dazu gäbe es genug) einfach mal eine kleine Basisimplementierung schaffen und diese dann Stück für Stück erweitern (dadurch hast du auch Teilerfolge die motivieren und der Lerneffekt ist größer).
Mach dich auch darauf gefasst das du irgendwann mal große Codeteile wegschmeißt und neu schreiben willst/musst weil deine bishere Implementierung einfach unflexibel war etc.


----------



## n00b4u (17. Dez 2015)

Super Danke. 

Wie das halt so ist, fängt man mal an und zack ist die Klasse fast so groß wie der Quellcode von Windows ;-) 

Hast aber recht. Ich werde das ganze mal etwas eindampfen. und versuchen zwei hart-codierte Teams einmal gegeneinander spielen zu lassen und darum herum dann die Simulation aufzubauen versuchen.


----------

