# Beginnercode: Pokerdealer Programm



## fk1 (14. Dez 2015)

Hallo zusammen,

da ich mittlerwile die ersten Anfängertutorials durchgearbeitet habe wurde es dann Zeit für Praxis. Ich habe leider keine Idee für ein nützliches Tool gehabt, allerdings ein Faible für Poker. Was liegt also näher als ein Pokerspiel zu programmieren? 

Naja, ich bin sicherlich weit entfernt davon einen Pokerclient zu coden, allerdings ging mir eine simple Idee dabei nicht mehr aus dem Kopf und so habe ich mich heute mal hingesetzt und ein paar Zeilen geschrieben und probiert ein paar Ideen umzusetzen bzw. Probleme zu lösen.

Ich habe eine Klasse "Dealer" geschrieben, welche die Methode "deal" beinhaltet. In der Methode "deal" definiere ich mittels Arrays, wie eine Karte sich zusammen setzt (Aus Rang und Farbe/suit).

Zusätzlich nutze ich "Random", um zufällige Indezes der Arrays zu wählen und bilde damit dann eine Karte, welche ich ausgebe.

In der main Methode gebe ich 2 Karten an einen Spieler aus. Problem hierbei ist das Austeilen doppelter Karten. Ich dachte, ich füge ausgeteilte Karten einer ArrayList hinzu und lasse für den doppelten Fall einfach erneut die for-schleife durchlaufen.

Das klappt sogar ganz gut, jedoch bekomme ich mit diesem Programm nur 24 exklusive Kombinationen ausgegeben. Da ein Kartendeck aus 52 Karten besteht müssten es allerdings 26 Kombos sein.

Vielleicht findet ja jemand den Fehler. Auch für Anregungen zur Lesbarkeit oder Umsetzung bin ich offen. Habt Nachsicht mit mir, ich bin "nur" IT-Systemelektroniker, also kein Fachinformatiker, und das ist mein erstes Java Programm zum lernen. 

Schönen Gruß

E: Frage: kann i negativ werden? Ich gucke gerade nochmal durch meine Ausgabe und kann keinen einzigen King entdecken. Der ist am Ende des ersten Arrays aber definiert.

E2: Habs gefunden, war einfach nur 13 statt 12 als Parameter bei 'int rndrank = rnd.nextInt' 



```
import java.util.ArrayList;
import java.util.Random;

public class Dealer {

    /**
     * @param args
     */
    public static void main(String[] args) {
  
        // ArrayList für ausgeteilte Karten
        ArrayList<String> dealt = new ArrayList<String>();
  
        // for-Schleife um alle möglichen Kombinationen ausgeben zu lassen
        for(int k=0; k<50; k++)    {
      
            // Kartenausteilung (2 holecards, 1 Spieler)
            for(int i=0; i<2; i++){
                String hcard = deal();
          
                // Prüfe ob Karte bereits ausgeteilt wurde
                if(dealt.contains(hcard)) {
                    i--;
                }
                else {
                    // Karte zum Array verteilter Karten hinzufügen und austeilen
                    dealt.add(hcard);
                    System.out.print(hcard);
                }
            }  
            System.out.println();
        }

    }

    public static String deal() {
        // Definition des Kartendecks mittels Arrays
        String[] rank = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"};
        String[] suit = {"c", "s", "d", "h"};
          
        // Generierung einer zufälligen Zahl für Array Indizes (Shuffle)
        Random rnd = new Random();
        int rndrank = rnd.nextInt(12);
        int rndsuit = rnd.nextInt(4);
  
        // Kombination einer Karte
        String card = rank[rndrank] + suit[rndsuit];
  
        return card;
    }
}
```


----------



## kneitzel (15. Dez 2015)

Was für ein Anfängertutorial hast Du denn durchgearbeitet? Ich frage, weil Java Objektorientiert ist und davon sehe ich halt nichts. Gerade bei so Projekten, wenn mehr als nur die 08/15 mini Programme geschrieben werden, ist dies in meinen Augen extrem wichtig.

Ich sehe nicht wirklich, wo der Lerneffekt ist, wenn man ein Poker-Spiel scriptet (Darauf läuft es ja unter dem Strich hinaus).

Ich will Dir da nicht zu nahe treten oder das, was Du machen willst, schlecht reden. Wir helfen Dir auch bei Deinem jetzigen Anliegen, wenn Du das wirklich so machen willst. Aber ich würde das doch etwas anders durchziehen an Deiner Stelle.

Zu Deinem aktuellem Code:
In einer For Schleife die Variable aus der For Schleife zu benutzen halte ich für einen extrem schlechten Coding-Stil. Wenn Du kein sauberes Durchzählen hast, dann nimm eine andere Schleife wie z.B. eine while Schleife.

Konrad


----------



## fk1 (15. Dez 2015)

Hi Konrad,

ich habe das hier angeguckt: http://panjutorials.de/tutorials/java-programmieren-fur-anfanger/
Bin allerdings auch nicht ganz fertig mit dem Tutorial, nur bis Video 30 von 40 geguckt. Hole ich natürlich nach, werde wohl auch noch in Zukunft einiges lernen müssen.

Ich hatte "Java ist eine Insel" mal angelesen bis mir aufgefallen ist dass das Buch sich besser als Nachschlagewerk als zur Einarbeitung eignet. Das Konzept "Objektorientiertes Programmieren" habe ich anscheinend noch nicht verstanden. Ich dachte es geht darum, ein Objekt mit Attributen und Werten zu erstellen, mir hängt da noch der Merksatz im Kopf: Ein Auto fährt, verbraucht Sprit und produziert Abgase.

Meine Idee etwas umzusetzen war halt: Der Dealer mischt das Deck, sammelt die Einsätze (kommt noch) und teilt Karten aus. Scheint ja noch nicht so richtig geklappt zu haben. Ich mache mir nochmal Gedanken dazu und probiere das Programm objektorientierter zu gestalten.

for Schleife Nummer Eins ist eigentlich nur zum Testen da. Trotzdem meine Frage: Warum nutze ich die gleiche Variable? ich nutze doch einmal k und einmal i?!

Kann schon sein, dass das Pokerspiel wirklich nicht geeignet ist. Allerdings habe ich gelesen: am besten ist die Praxis um zu lernen und ich habe einfach keine andere Idee. Ich habe aber viel Erfahrung in dem Spiel und vielleicht wird das Ganze spannender wenns um die KI geht 

Gruß
Flo


----------



## Jardcore (15. Dez 2015)

Hey fk1,

um das OO zu machen würde die main-Methode der Einstieg in dein Programm sein und in einer Extra Starter-Klasse liegen (z.B.: PokerApp, MainApp ...)
Dort könnte dann ein Objekt *Dealer *erzeugt werden und auf diesem dann deal() aufgerufen werden.

```
public class Dealer {
    private ArrayList<Card> cards;
  
    public void deal() {...}
}
```

Wahrscheinlich hätte man auch noch ein paar andere Objekte (Table, Player, CardShuffler).

Ich nehme mir vorher immer ein Blatt Papier und zeichne mir alle Komponenten auf und leite daraus meine Objekte ab. Dann siehst du auch auf einem Blick ob dir noch etwas fehlt.

Im Code könntest du auch sogenannte Magic Numbers vermeiden, das sind die Zahlen die man nicht auf Anhieb interpretieren kann. In deinem Beispiel die 50 und die 2, du benutzt dafür ein Kommentar über der for-Schleife, könntest aber auch einfach eine Variable für die beiden Nummern spendieren und hättest damit einen guten Lesefluss.
Allgemein benutzte einfach längere Namen, statt *dealt *für deine ArrayList, könntest du die Liste auch *playedCards*, oder wohl möglich auch *listOfPlayedCards*, dann wüsstest du auf einem Blick was gemeint ist. Sowas ist vor allem bei größeren Projekten Gold wert.

Beste Grüße,
Jar


----------



## fk1 (15. Dez 2015)

Hallo zusammen,

@kneitzel: Ich verstehe jetzt erst, was du mit gleicher Variable meinst. Ich überlege mir da mal eine Alternative. Ich glaube auch, du siehst gar nicht das Pokerprogramm skeptisch, sondern das Scripten statt OOP. Das hatte ich gestern Abend falsch verstanden.

Falls dem so ist, sehe ich das genau so. Deswegen poste ich hier, ich möchte konform sein mit der Java Idee/OOP/den Developern.

Ich komme durch ein kleines AutoIT Projekt auf die Idee, Programmieren zu lernen. Ich finde die Idee der OO Programmierung auch super, das AutoIT Projekt bestand aus 500 Anfängerlines. Hat Spaß gemacht und seinen Job getan, war aber absolut unübersichtlich 

@Jardcore: Danke für deine Tipps, auch da werde ich einiges adaptieren und mir nochmal Gedanken zum Thema OO machen. Eine Skizze mache ich auch mal, ich versuche mal mit Diagrammen zu arbeiten um das besser zu planen.

Edit: Noch ein paar Fragen: 

Gruß
Flo


----------



## CSHW89 (15. Dez 2015)

Um deine ursprüngliche Frage zu beantworten: dein Dealer wird sicherlich keinen König austeilen.

```
int rndrank = rnd.nextInt(12);
```
Da muss eine 13 stehen. Solche Fehler entstehen übrigens genau wegen Magic-Numbers, was @Jardcore bereits angesprochen hat. Besser ist dort:

```
int rndrank = rnd.nextInt(rank.length);
```
... bei suit genauso.

lg Kevin

Edit: ups hab den Edit nicht gelesen. Ich lass es aber mal trotzdem stehen


----------



## fk1 (15. Dez 2015)

Danke Kevin, wusste bis jetzt noch nicht, dass das so funktioniert.

Ich sitze hier und überlege wie ich Struktur in ein Diagramm bekomme und ich schätze, ich muss das mal ganz simpel herunterbrechen.

Allgemein gilt: Ein Objekt ist eine Instanz aus einer Klasse. Also ist z.B. eine card ein draw aus einem Deck.

Was ist dann der Dealer? Für mich ein Objekt, da er z.B. Karten austeilt (Methode) und die Regeln kennt (Eigenschaft). Bleibt die Frage: Zu welcher Klasse gehört der Dealer?

Ich dachte an die Klasse Holdem, da der Dealer Holdem Regeln befolgt. Das würde künftig eine Erweiterbarkeit liefern, da man dann andere Klassen wie z.B. Omaha (Variante mit 4 Karten) erstellen kann.

Kann eine Klasse mehrere verschiedene Objekte beinhalten? Ich würde dann in der Klasse Holdem, welche die Variante darstellt, alle variantenbezogenen Objekte packen, z.B. auch die Anzahl der holecards (2) oder die Regeln der Auswertung einer Hand.

e: Alternative: Ich erzeuge eine Klasse Dealer, aus der ich ein Objekt holdemdealer instanzieren kann.


----------



## kneitzel (15. Dez 2015)

Ok, also bist Du für die Objektorientierte Herangehensweise offen. Das war mir für mein Verständnis wichtig.

Die objektorientierte Entwicklung kann man recht gut mit der realen Welt vergleichen. Wenn man das Beispiel Auto nimmt, dann hat man einen groben Plan, wie das Auto aufgebaut ist. Aber man muss nicht alles bauen. Man kann auch Schnittstellen definieren und dann nutzt man ggf. vorhandene Dinge. Also ich muss, wenn ich ein Auto bauen will, nicht alles selbst bauen. Ich brauche einen Motor (der dann eine gewisse Schnittstelle hat), aber den baue ich nicht selbst, sondern dafür nehme ich mir dann halt den de.vw.sportmotor.MotorMitVielLeistung, der halt IMotor implementiert. Und wenn der mit nicht gefällt, dann tausche ich den evtl. gegen de.fiat.500erMotor und tausche den ggf. relativ einfach aus, weil alle Zugriffe über das Interface IMotor gehen.

Aber ich will Dich mit einem Beispiel Auto nicht verwirren. Nehmen wir das Poker-Spiel:
- Du brauchst ein Kartendeck. Dieses besteht aus Karten. Diese können gemischt werden.
- Du hast evtl. einen Kartenstapel - dieser bietet die Möglichkeit an, Kartendecks aufzunehmen und es können Karten entnommen werden.
- Du hast Spieler. Diese haben irgendwelche Poker-Karten (Hier kenne ich mich nicht aus. Ich habe früher mal was gespielt mit geschlossenen Karten, aber da gibt es irgendwelche Varianten mit offenen und verdeckten Karten ... das wirst Du besser wissen.) Hier würde dann die Logik rein gehören, welche Karten getauscht werden oder so.
- Die Kartenhand hat die Logik bezüglich Auswertung. Was habe ich? Full House? Zwei Pärchen? (Ich habe keine Ahnung, was es so gibt...)
- Evtl. gibt es einen Spieltisch mit gemeinsamen Karten? (Ich habe keine Ahnung, sorry.)
- Und dann hast Du evtl. ein Pokerspiel. Das Spiel hat diverse Spieler, die jeweils Ihre Karten haben. Ggf. ein Spielfeld. Hier findet sich dann auch alle Logik des Spiels. Wer darf wann welche Karten nehmen.

Wichtig ist, dass Du versuchst natürliche Grenzen zu finden. Und dass Du keinen Code an Stellen schreibst, wo dies nicht unbedingt hin gehört. Also nicht zentral im Pokerspiel das Mischen implementieren. Das gehört ja in das Kartenspiel. Das kann dann auch eine Universelle Klasse werden, die Du überall verwendest. Hier kommt dann die Wiederverwendung von Klassen zum tragen.

Ich fange immer ganz normal an - ich nutze dazu dann ein Namespace der meist de.kneitzel.<Projekt> heisst. Wenn ich dann Klassen schreibe, die ich für universell halte, dann schiebe ich die meist in ein eigenes Library Projekt de.kneitzel.lib.*. So würde ich später die Spielkarte (Hier einen möglichst Aussagekräftigen Namen verwenden. Nicht nur Karte, denn das könnte ja auch eine Straßenkarte oder so sein), Kartendeck und Kartenstapel in einen Namespace de.kneitzel.lib.gaming verschieben. Wenn ich dann ein anderes Projekt erstelle z.B. ein Skatspiel, dann habe ich die gleich parat.
Aber das ist etwas, das Du im ersten Schritt außen vor lassen kannst.

Ein weiterer Bereich, den Du Dir evtl. anschauen solltest, sind sogenannte Unit-Tests. Mit welcher IDE arbeitest Du? Evtl. kannst Du das relativ einfach anfangen. Das würde ich zuerst auch nicht zu sehr verkomplizieren. Die Kernidee kann auch erst einmal sein, dass Du eine Klasse Tests schriebst in der du dann eine main Funktion hast, die dann verschiedene Dinge testet. So könntest Du z.B. ein Kartenspiel erzeugen und die Schnittstellen prüfen. Klappt das Mischen? Oder bei einem Kartenstapel: Klappt das Hinzufügen von Kartenspielen, klappt die Entnahme von Karten? All sowas. Die Idee ist halt, dass Du einzelne kleine Komponenten zuerst fertig stellen und dann auch direkt testen kannst. Statt von so main Methoden, die Du aufrufst gibt es dann Methoden, die von einem Tool aufgerufen werden. Das geht zwar relativ weit für einen Anfänger, aber den Punkt möchte ich erwähnt haben. So es Dich wirklich interessiert könnten wir / ich Dich da ein kleines bisschen führen und unterstützen.

Damit hätten wir schon ein sehr breites Feld abgedeckt. Dabei will ich es an dieser Stelle kurz belassen und Dein Feedback abwarten (Und evtl. auch das Feedback von Dritten). Ich würde an der Stelle als Feedback vor allem erwarten, wie Du gerne weiter vorgehen möchtest (und mit welcher IDE. Ich nutze IntelliJ aber jede IDE, die auch einen Debugger und so enthält, ist sehr brauchbar. Wichtig ist, dass Du ein brauchbares Tool verwendest, denn das nimmt Dir erst einmal viel Arbeit ab) und dann würde ich evtl. im Detail weiter vorgehen. Bezüglich möglicher Aufteilung von Klassen kannst Du natürlich auch noch deutlich detailierter werden, wie Du Dir das vorstellst incl. Informationen, was da jeweils enthalten sein soll und was für Schnittstellen Du da erst einmal sehen würdest.

Hoffe das war nicht zu viel und hoffentlich bringe ich nicht viel zu viel auf einmal. Am Anfang ist die Thematik Softwareentwicklung leider extrem umfangreich.

Konrad


----------



## fk1 (15. Dez 2015)

Mega Beitrag, daher mega dankeschön 

Erschlagen fühle ich mich bisher noch nicht wirklich. Ich habe bisher noch überlegt, wo ich die main Methode unterbringe, also in welcher Klasse, aber scheint wohl am besten wirklich erstmal am besten zu sein eine Start bzw. Test Klasse zu erzeugen.

Also ich denke, damit ich konformer mit der Java Welt werde, erstelle ich nochmal ein UML konformes Klassendiagramm oder Objektdiagramm, damit man weiss, was ich so vorhabe. Fällt mir noch ein wenig schwer, sieht man ja an dem Post von mir über dir, mit der Klasse für den Dealer.

Ich denke, ich realisiere das mit Klasse: Dealer, Objekt: holdemdealer (variantenbasiert). Dann ist ein holdemdealer eine Instanz der Klasse Dealer und die OO Idee erfüllt.


----------



## Jardcore (15. Dez 2015)

Man kann auch ganz witzige Sachen mit dem Strategy Pattern machen und dem Dealer eine Strategie verpassen. Also falls du vorhast das der Dealer mehrere Spiele anbieten kann.


```
public class Dealer() {
    private Strategy strategy;

    public Dealer(Strategy strategy) {
        this.strategy = strategy;
    }

    public void deal() {
        strategy.update();
    }
}
```


```
public class Holdem extends Strategy() {
    public void update() {
        // logik hier
    }
}
```


```
public abstract class Strategy() {
    public void update();
}
```


----------



## fk1 (16. Dez 2015)

Danke  @Jardcore für den Tip. Allerdings werde ich erstmal genug mit der einen Variante zu tun haben, also wird das mit Strategy noch ein wenig dauern. Ich versuche daran zu denken, wenn sich die Frage wieder stellt.

Ich saß gestern Abend immer abwechselnd vor meinen paar Zeilen und einem Diagramm, bis ich dann mal eine Idee hatte. Es hapert aber noch an der Umsetzung. Irgendwie habe ich noch nicht richtig die Übergabe von einem Objekt einer Klasse in eine andere Klasse verstanden. Ich möchte aber erst noch mal selbst recherchieren, bevor ich euch eine konkrete Frage stelle.

Im Anhang könnt ihr mal das Objektdiagramm betrachten. Da ich hier auch nur Internetrecherche betrieben habe und dies mein erstes ist, könnt ihr auch gerne Verbesserungsvorschläge hierzu posten. Ich hoffe daraus wird wenigstens verständlich, wie ich das bisher Geschriebe umgestalten möchte.

Ich habe probiert, meinen vorhandenen Code OO zu gestalten. Hier mal der Code vom Deck:



Spoiler: Deck.class





```
import java.util.ArrayList;
import java.util.Random;

public class Deck{
 
    // Definition des Kartendecks mittels Arrays
    String[] rank = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"};
    String[] suit = {"c", "s", "d", "h"};
     
    // ArrayList für ausgeteilte Karten
    ArrayList<String> dealtCards = new ArrayList<String>();
             
    // Generierung einer zufälligen Zahl für Array Indizes (Shuffle)
    Random rnd = new Random();
    int rndrank = rnd.nextInt(13);
    int rndsuit = rnd.nextInt(4);
     
    // Kombination von Rank und Suit zu einer Karte
    String card = rank[rndrank] + suit[rndsuit];{
 
        //Neu shuffeln, falls Karte bereits verteilt
        while(dealtCards.contains(card)){
            rndrank = rnd.nextInt(13);
            rndsuit = rnd.nextInt(4);
            card = rank[rndrank] + suit[rndsuit];
        }
    }
 
    public String getCard(){
        dealtCards.add(card);
        return card;
    }
}
```




Ich habe hier das Problem mit der benutzten Variable i der for-Schleife in der for-Schleife selbst behoben. Auch die ArrayList dealtCards habe ich jetzt in der Klasse Deck selbst, also nicht mehr im eigentlichen Deal-Prozess plötzlich Script-like drin.

Ich muss heute mal das Tutorial zu Ende machen und mich dann nochmal mehr mit den setten & getten beschäftigen, irgendwie hat es gestern Abend und heute noch nicht geklappt. Liegt wohl daran, dass ich mehr probiere, als studiere 

Allerdings beschäftigt mich schon wieder eine Frage, noch bevor ich alles fertig gecodet habe:

Wenn ich später mal 2 Karten generiere, die verteilt werden und dem ArrayList dealtCards hinzugefügt werden, bleiben die dann in dealtCards überhaupt bestehen?

Ich frage, weil die Klasse Deck nicht static ist, daher meines bescheidenen Wissens, nachdem sie nicht mehr benötigt wird, aus dem Speicher gelöscht wird. Wie verhält sich das? Muss ich hier umdenken oder kann ich das wie geplant umsetzen? die Klasse lässt sich laut Eclipse auch nicht static setzen.

E:
dealtCards.add(card); hinzugefügt


----------



## Jardcore (16. Dez 2015)

Solange eine Referenz auf ein Objekt besteht wird es auch nicht aus dem Speicher entfernt.
Statische Objekte bestehen allerdings auch ohne eine Referenz.
Für den Anfang brauchst du dir da keinen Kopf machen, statische Klassen, Attribute und Methoden kann man erstmal ignorieren.

Zu deinem Diagramm: Glaube ein klassisches UML würde dir mehr helfen. Du kannst dir auch (falls du Eclipse benutzt) die Extention ObjectAid runterladen, mit dem Tool kannst du dir ein UML deines Codes anzeigen lassen. Damit kann man bisschen üben wie man was Modellieren kann.

Hab leider gerade keine Zeit dein Problem in UML dazustellen.

Edit:

```
// Kombination von Rank und Suit zu einer Karte
    String card = rank[rndrank] + suit[rndsuit];{

        //Neu shuffeln, falls Karte bereits verteilt
        while(dealtCards.contains(card)){
            rndrank = rnd.nextInt(13);
            rndsuit = rnd.nextInt(4);
            card = rank[rndrank] + suit[rndsuit];
        }
    }
```
Hier fehlt irgendwie die Methode oder? 
Und ein Getter sollte nur etwas zurück geben, aber nicht noch irgendwas machen was man anhand des Names nicht erwartet.


----------



## Jardcore (16. Dez 2015)

Ich habe mir gerade mal auch einen Code gebastelt.
3 Klassen (Card, Deck, MainApp)
2 Enums (Rank, Suit)

Meine Ausgabe:

```
Card(   NINE,    CLUB)
Card(   FIVE,   HEART)
Card(  THREE, DIAMOND)
Card(  SEVEN,   SPADE)
Card(  SEVEN, DIAMOND)
Card(    TWO,    CLUB)
Card(    TEN,   SPADE)
Card(  QUEEN,   SPADE)
Card(  QUEEN, DIAMOND)
Card(     AS,   SPADE)
Card(   FOUR,    CLUB)
Card(     AS, DIAMOND)
Card(   FOUR, DIAMOND)
Card(  JOKER,   SPADE)
Card(  SEVEN,   HEART)
Card(    SIX,   SPADE)
Card(    TEN,    CLUB)
Card(  THREE,   HEART)
Card(  QUEEN,   HEART)
Card(  EIGTH,   SPADE)
Card(  EIGTH,    CLUB)
Card(   KING, DIAMOND)
Card(   NINE,   SPADE)
Card(   FOUR,   HEART)
Card(  QUEEN,    CLUB)
Card(   FIVE,    CLUB)
Card(   KING,   SPADE)
Card(    TWO,   HEART)
Card(    TEN,   HEART)
Card(    TEN, DIAMOND)
Card(  JOKER,   HEART)
Card(    SIX, DIAMOND)
Card(   NINE, DIAMOND)
Card(  THREE,   SPADE)
Card(   KING,    CLUB)
Card(   KING,   HEART)
Card(  JOKER, DIAMOND)
Card(     AS,    CLUB)
Card(     AS,   HEART)
Card(    SIX,   HEART)
Card(  EIGTH, DIAMOND)
Card(   FIVE, DIAMOND)
Card(    TWO, DIAMOND)
Card(  JOKER,    CLUB)
Card(    SIX,    CLUB)
Card(    TWO,   SPADE)
Card(  SEVEN,    CLUB)
Card(  THREE,    CLUB)
Card(   FOUR,   SPADE)
Card(   NINE,   HEART)
Card(   FIVE,   SPADE)
Card(  EIGTH,   HEART)
```

P.S: Du kannst mit *Collections*.shuffle(List<>...) eine Liste zufällig mischen.


----------



## fk1 (16. Dez 2015)

@Jardcore: Scheint ja mit enums und Collection.shuffle effektiv zu sein wenn du das mal eben programmierst, ich sitze ja jetzt schon ein paar Tage daran, die Idee umzusetzen. ^^ 

Ich hatte auch erst überlegt eine card als extra Klasse zu erstellen, das Deck dann mit fester Reihenfolge von 52 card Objekten zu gestalten, die der Dealer dann bei Bedarf mischt (Wie in der Realität).

Ich wollte es dann aber erstmal simpel halten und meinen bisherigen Code OO gestalten.

Da fehlt bestimmt eine Methode wenn du es sagst, ich muss auch zugeben, dass ich dachte, ich hätte das Grundkonzept verstanden. Doch dann fiel mir auf, dass ich gar nicht richtig die Methoden zuornden kann:

Wenn ein Objekt eine Instanz einer Klasse ist, was ist dann eine Methode? Wie kann ich das zuordnen? Ist eine Methode eine Fähigkeit einer Klasse oder Objekt? Oder ist eine Methode die Instanz der Klasse?

Und zu meinem Code: Ich definiere da ja den String card, allerdings ist das dann noch kein Objekt, oder? Ich schätze, die Methode getCard ist nicht die Methode, die du vermisst.


----------



## Jardcore (16. Dez 2015)

Ich habe dir ja mit Absicht nicht meinen Code gezeigt, nur einen Ausblick was du erreichen kannst 

Also Objekte sind im Prinzip deine Klassen (*public class Deck {...}*)
Wenn du nun davon eine Instanz erzeugst  (*new Deck()*), hast du eine Instanz diese Objekts erzeugt.
Wenn du diese Instanz speichern willst (*Deck meinDeck = new Deck*) dann hast du eine Referenz auf deine Instanz mit dem Namen meinDeck.

Ein Objekt kann Methoden und Attribute haben. Diese können auch noch verschiedene Sichtbarkeitbereiche haben (*public*, *private*, *protected*, _*"packagePrivate"*_) Attribute bestimmen dabei den Zustand eines Objektes.
Methoden kann man wirklich als Fähigkeiten bezeichnen. Die Fähigkeiten können auch aus anderen Instanzen aufgerufen werden, solange die Methode public ist und die andere Instanz wiederrum eine Referenz auf meine Instanz hat (klingt verwirrend) Private Methoden können nur innerhalb des Objektes aufgerufen werden.

Für die Sichtbarkeiten hier mal ein Link: http://openbook.rheinwerk-verlag.de...05_002.htm#mjf5b3fff9748ae6323d1923016a906a8f
Würde sonst meinen Zeitlichenrahmen sprengen^^

getCard() war nicht die Methode 

EDIT:
Ein Enum ist übrigens so ähnlich wie eine Klasse, hilft wenn man Aufzählungstypen hat, oder etwas gruppieren möchte.


```
public enum Jahreszeiten {
FRUELING,
SOMMER,
HERBST,
WINTER;
}
```


----------



## fk1 (16. Dez 2015)

Danke für deine Antwort Jardcore. Der Verweis auf "Java ist auch eine Insel" sagt mir, dass ich mehr studieren sollte, bevor ich weiter mache. Ich lese mich mal ein paar Tage weiter ein. Ich glaube ich hab einfach noch zu wenig Basics verstanden. Allerdings musste ich wohl auch erst mal mit den ersten Zeilen beginnen um das zu verstehen  

Sobald ich neue Erkenntnisse und Ideen in Code umgesetzt habe schreibe werde ich dann hier berichten!


----------



## Jardcore (16. Dez 2015)

Sehr gut, freut mich das du da systematisch rangehst


----------



## fk1 (17. Dez 2015)

Lese mich gerade schlau und kann mir die Erkenntnisteilung nicht verkneifen 

Das ganze Haareraufen gestern basiert darauf, weil ich nicht wusste, das es 2 Arten von Methoden gibt. Natürlich bin ich gestern daran verzweifelt, wieso ich eine Klassenmethode nicht als Instanz/Objektmethode in Dealer.class aufrufen kann ^^

@Jardcore: Jetzt verstehe ich auch, wieso du nach einer Methode fragst. Da ist noch ein } übrig geblieben, als ich den Code umstrukturiert hatte.

Das bringt mich aber auf die Idee, das shuffeln als methode zu verpacken um es bei gleicher card wieder nutzen zu können


----------



## Jardcore (17. Dez 2015)

Die frage ist, wie es zu gleichen Karten kommen kann. Ich bin so vorgegangen.
Ein Deck hat 52 Karten, die Anzahl entsteht durch die Kombination aus Suit und Rank. Wenn nun der Dealer eine Karte vom Stapel nimmt sind es nurnoch 51 Karten und nur der Rest kann ausgespielt werden.
Erstmal ist egal was mit den Karten geschieht. Ob es einen Ablagestapel gibt oder nicht ist bei Holdem unwichtig.
Wenn das Spiel zuende ist wird einfach ein neues Deck erzeugt und man hat wieder 52 gemischte Karten


----------



## fk1 (17. Dez 2015)

Ich gucke mir gerade die letzten Videos des Tutorials an und bin bei Polymorphie: http://panjutorials.de/java-anfanger-tutorial-35-polymorphie/?replytocom=110#respond

Ich habe nur eine Frage zu der for-Schleife des Beispiels:


```
for(int i=0; i&lt;einAuto.length; i++){
einAuto[i].reparieren();
```

Ist das nicht wieder der schlechte Stil, den ich vermeiden soll? Wundere mich, dass der Tutor das so macht, eigentlich hat das Tutorial viele gute Rezensionen (komme ich über google-> giga drauf) und frage mich jetzt ob der schlechten Coding Stil betreibt oder ich da was falsch verstanden habe.


----------



## Jardcore (17. Dez 2015)

Man kann i schon ab und an mal als Zählvariable benutzen.
Leider muss man sagen das auch viele Fachbücher schlechten Code enthalten, darauf stößt man immer wieder.
Wenn man Code anschaut und nicht flüssig begreifen kann was dort geschieht ist es meistens ein Indiz dafür.
Dabei muss man nicht jede Zeile sofort verstehen. 
Aber wenn man z.B:

```
private void run () {
    for (int i = 0; i < 10; i++) {
        if (al.size > 0) {
            al[i].setX (al [i].getX () + 1);
        }
    }
}
```
...oder:

```
private void moveAllAgentsToRight () {
    if (agentsNotExists() {
        return;
    }
    for (int i = 0; i < numberOfAgents; i++) {
        moveRight (agents [i]);
    }
}
```
...liest, kann man dem zweiten Beispiel hoffentlich besser folgen. Was nun moveRight macht ist erstmal unwichtig. Jedoch nimmt man an, dass es wohl einen Agenten nach rechts schiebt.

Im Grunde gehts darum verständlichen Code zu schreiben.


----------



## Jardcore (18. Dez 2015)

Man hätte bei deinem Auto Beispiel auch eine foreach Schleife nehmen können. Denn der zähler war ja nicht nötig. Gleiches gilt für mein Beispiel.

```
for (Auto auto : autos) {
    auto.reparieren();
}
```


```
for (Agent agent : agents) {
    moveRight (agent);
    //oder: agent.moveRight ();
}
```


----------



## fk1 (19. Dez 2015)

Ich bin mit der Anfängertutorialreihe durch und beschäftige mich inzwischen wieder mit meinem ersten Code.

Gestern Abend saß ich dann mal völlig verwirrt und planlos vor dem Rechner. Heute will ich daher das Problem wieder ganz einfach angehen, also brechen wir das alles mal ganz simpel herunter:

Ich erstelle als erstes eine Klasse Card. Eine Karte besteht aus Suit und Rank, also füge ich der Klasse diese als Array hinzu. Enums lasse ich nochmal außen vor. Ich schätze, enums eignen sich viel besser für mein Vorhaben wenn @Jardcore mir das vorschlägt. Ich bleibe aber doch erstmal zwecks Lerneffekt bei Arrays.

In der Klasse Cards gibt es den Constructor Cards, der zwei int Parameter rankIndex & suitIndex benötigt, damit er eine Card zusammen setzen kann. Welche Karte man dann genau als Instanz erzeugen möchte, kann man mit den zu übergebenen Parametern dann immer selbst bestimmen.



```
public class Card {

    // Arrays für die Eigenschaften einer Karte
    String[] rank = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"};
    String[] suit = {"c", "s", "d", "h"};
    String card;

    // Konstruktor für Karte
    public Card(int rankIndex, int suitIndex){
    card = rank[rankIndex] + suit[suitIndex];

    }
}
```

Ich glaube, die Lösung zur Erstellung einer Karte ist jetzt OOer als vorher.

Jetzt widme ich mich der Klasse Deck. Diese Klasse ist nach meiner Überlegung nur ein Array bestehend aus 52 Card Objekten. Ein frisch gekauftes Deck ist sogar sortiert. Meiner Meinung nach kommt daher das Karten Mischen weder in die Klasse Cards noch Deck. Ich denke man verpackt das am besten als Dealer-method, aber eins nach dem anderen.

Ich möchte zunächst einfach nur ein Array aus 52 Cards generieren:


```
public class Deck{

    Card newDeck[] = new Card[52];

}
```

Das habe ich dann mal testweise ausgeben lassen. Da ich ja gar keine Parameter übergebe, bekomme ich null ausgegeben. Wie kann ich bei der Erstellung des arrays Parameter übergeben? Geht das überhaupt?

Der Plan ist, ein 52er Kartendeck sortiert zu erzeugen. Die Hoffnung besteht darin, das sortierte Deck-Array mischen zu können und dann Karte für Karte auszuteilen. In Java: eine methode nextCard zu erzeugen, den Index des gemischten Arrays als Karte austeilen, dann den index um Eins erhöhen. 

So würde ich mir die Liste ausgeteilter Karten sparen können.


----------



## n00b4u (19. Dez 2015)

Mhm... du hast zwar Arrays mit den Werten, aber die Arrays machen erstmal nichts. und Mit new Card[52] erzeugst du ein Array mit 52 leeren Feldern.

Am einfachsten wäre es wahrscheinlich wenn du eine Schleife durchiterierst die dir dann die Karten erzeugt.

Und natürlich sollte Card dann  ein zweidimensionales Array sein, also Card [][].

Und spätestens hier, sind dann Enums die bessere Wahl. Oder willst du die Karten im Spiel über den Index ansprechen?


----------



## n00b4u (19. Dez 2015)

Wenn du dann mit randomize arbeiten willst, und ein Array verwenden, dann würde ich für den Anfang vielleicht sogar empfehlen, alle Karten fest in einem Array zu erzeugen, so schnell werden sich die Karten ja nicht ändern und dann diesen eindimensionalen Array mit einem Random über den Index austeilen.


----------



## Jardcore (19. Dez 2015)

Meine Idee mit den Enums ist nicht non plus ultra, man kann das nach belieben machen 

Deine Card Klasse hat aber leider noch paar Macken.
Die Klasse soll ja eine Art Blaupause sein. Also wenn man mal so rangeht: Eine Karte hat immer nur EINE Farbe und Form, mehr nicht.
Deine Karte hat jedoch alle Farben und alle Formen und dann noch ein String der die eigentliche Karte repräsentieren soll.

Du könntest einen Dealer erstellen, welcher die beiden Arrays aus deiner Card Klasse enthält. Der Dealer erzeugt dir deine 52 Karten und diese kannst du dann einem Deck übergeben.
Die Card Klasse erhält dann zwei Strings, einen für Farbe, eine für Form.

Deine Deck Klasse benötigt eigentlich nicht mehr viel. Eine toString Methode einen Konstruktor der ein Liste von Karten akzeptiert und eine Methode die dir die oberste Karte ausgibt. (Vielleicht könnte auch der Dealer das Deck haben und du fragst den Dealer nach einer Karte)

Am besten du schaust dir mal Listen an (ArrayList<>) das würde die Sache an einigen Stellen vereinfachen.

@n00b4u
wäre aber nicht sehr objektorientiert...


----------



## n00b4u (19. Dez 2015)

@Jardcode

Das kommt doch drauf an. Wenn ich den Kartensatz in einer Klasse Spiel erzeuge und nicht als eigene Klasse verwende, wo ist da das Problem? Mann muss ja nicht für jedes Tischbein des Pokertischs ne eigene Klasse schreiben.

Natürlich gibt es elegantere Wege, da hast du Recht. Und ich muss gestehen, als ich mit dem programmieren anfing, waren Arrays mein Hass-Thema Nummer 1. Ich finde für Einsteiger ist das schon recht knackig, da kann man einen einfachen Entwurf zum Verständnis schonmal gutheissen oder? ;-)


----------



## Jardcore (19. Dez 2015)

Der Name einer Klasse sollte die Verantwortlichkeit beschreiben (Single-Responsibility-Prinzip).
Man sollte mit 25 Wörter beschreiben können was eine Klasse tut.

Eine Methode sollte maximal 20 Zeilen haben.
If und Else Blöcke sollten nur eine Zeile lang sein.
Und Methoden sollten nur eine Aufgabe erfüllen.

Wenn man das beherzigt dann hat man das Zeug dazu guten Code zu schreiben.

Also wenn es Sinn ergibt, dass die Beine des Pokertisches Klassen brauchen, dann werden diese auch erstellt.
Aber wir schweifen ab, hier geht es nicht darum ein Pokerspiel zu programmieren, sondern ein Pokerdealer Programm.


----------



## n00b4u (19. Dez 2015)

Ok. Dem habe ich nichts entgegenzusetzen. Klar hast du Recht. Lieber sauber als geschlampt.


----------



## Jardcore (19. Dez 2015)

Hier noch eine kleine Deckstütze zum erzeugen der 52 Karten in einem Array:

```
Card[] cards = new Card[52];
int index = 0;
for(String rank : ranks) {
     for(String suit : suits) {
         cards[index] = new Card(rank, suit);
         index++;
     }
}
```


----------



## fk1 (19. Dez 2015)

Ich bin schon wieder verwirrt. @Jardcore die ranks und suits sind doch Eigenschaften einer Karte. Warum soll ich die dann beim Dealer speichern und den Dealer Karten generieren lassen? Der reale Dealer produziert doch auch keine Karten?! Er mischt und verteilt nur.

Okay, das klingt wahrscheinlich ein wenig überspitzt und klugscheisserisch, aber evtl bringt mich das weiter. Wenn also ranks und suits Eigenschaften einer Karte sind, die Definition aller möglichen Eigenschaften aber nicht in der Klasse selbst definiert werden sollen, dann bleiben ja eigentlich nur seperate enum Listen!?

Nichts für ungut aber ich finde, beim Dealer haben ranks und suits nichts verloren, ich meine das Speichern verteilter Karten hatte da immerhin auch nichts zu suchen  Aber so sehe ich dann wenigstens einen Grund für enums ^^


----------



## fk1 (19. Dez 2015)

Gerade mal probiert enums zu erstellen:


```
public enum Ranks {
    A,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    T,
    J,
    Q,
    K;
}
```

funzt nicht, eclipse meckert bezüglich syntax errors. Enum suits klappt wunderbar. Liegt es daran, dass ich Buchstaben und Zahlen mixe?

Falls ja, sind enums für mein Vorhaben weniger zu gebrauchen. Ich möchte schon die Ausgabe in Form von "AhAc" haben. In Poker Diskussionsforen gibt es da einen gewissen Standard bei der Darstellung, den ich einhalten möchte.

Neue Möglichkeiten, neue Probleme.


E: Ah ich glaub ich habs, sec...
E2: ne, doch nicht. Dachte mit ACE("A"), ... funktioniert es, aber hilft auch nicht. Das ist das Dilemma eines Anfängers, der gar nicht wirklich weiss, was er da überhaupt macht...


----------



## Jardcore (19. Dez 2015)

fk1 hat gesagt.:


> Liegt es daran, dass ich Buchstaben und Zahlen mixe?


Jaein, man kann in Java keine "Variablen" mit einer Zahl beginnen.

Für dein Vorhaben müsstest du dein Enum etwas erweitern... aber wie ich sagte ist ein Enum nicht das non plus Ultra, deine Anforderungen lassen sich auch mit einem String Array umsetzten.

Wenn du doch ein Enum nehmen möchtest würde es so aussehen:

```
public enum Rank {
    ACE("A"),
    TWO("2"),
    THREE("3"),
    FOUR("4"),
    FIVE("5"),
    SIX("6"),
    SEVEN("7"),
    EIGHT("8"),
    NINE("9"),
    TEN("T"),
    JOKER("J"),
    QUEEN("Q"),
    KING("K");

    private String text;
 
    private Rank(String text) {
        this.text = text;
    }
 
    public String getText() {
        return text;
    }
}
```

Das ist ein erweitertes Enum, du kannst z.B mit Rank.ACE.getText() das "A" bekommen... usw.
Die Card Klasse würde dann wie folgt aussehen:

```
public class Card {
    private Suit suit;
    private Rank rank;
 
    public Card(Rank rank, Suit suit) {
        this.rank = rank;
        this.suit = suit;
    }
 
    public Rank getRank() {
        return rank;
    }
 
    public Suit getSuit() {
        return suit;
    }
 
    @Override
    public String toString() {
        return String.format("%s %s", suit, rank.getText());
    }
}
```
Beachte hier das rank.getText() in der toString Methode

Einfachhalber habe das Suit Enum gerade vereinfacht erstellt und nicht in dem Schema wie Rank.

```
public enum Suit {
    c,
    s,
    d,
    h;
}
```

Edit:
Rank hat übrigens einen privaten Konstruktor... das Enum verknüpft vereinfacht gesagt automatisch deine Variable mit dem EnumWert (der EnumWert ist dabei ACE, TWO... und die Variable, dass was in der Klammer dahinter steht. Dort kann man auch Integer oder sogar Objekte reinpacken.


----------



## fk1 (19. Dez 2015)

Erstmal Danke für deine Vorlagen. Lass uns doch nochmal über Suits und Ranks im Allgemeinen sprechen: Eigentlich haben diese Attribute ja nichts mit einem Dealer zu tun. Gibt es vielleicht andere Klassen, die du erstellen würdest, wenn du an ein komplettes Spiel denkst?

Ich möchte jetzt ungerne deine Lösungen copy/pasten. Ich lerne da jetzt für die Zukunft von aber wenn ich jetzt alles vorgekaut bekomme, komme ich ja nicht weiter.

Da ich bis jetzt keine Idee habe, wo ich alle möglichen Suits/Ranks hinpacke: Wie ist folgende Idee?


```
public class Ranks {
    private String[] rank = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"};
  
    public String getRank(int rankIndex){
        return rank[rankIndex];
    }
}
```

Kann man das so machen oder ist das "schlechter Code/Stil"? Wir machen quasi aus Ranks und Suits auch noch seperate Klassen bzw. erzeugen Objekte, aus denen wir die Karten generieren.


----------



## Jardcore (19. Dez 2015)

Das kann man so machen... mit einem Zusatz... der dich jetzt nicht freuen wird  (weil du das vielleicht in deinen Übungen noch nicht hattest, wenn doch... HURA  )

Du müsstest der Klasse Ranks den Modifier *abstract* geben, also:

```
public abstract class Ranks {
}
```
Dein Array *rank* und die Methode *getRank*(int ...) musst du dann den *static* Modifier verpassen.

Und warum das ganze?
Weil du sonst immer eine Instanz der Ranks Klasse erstellen müsstest. Ranks ranks = new Ranks und dann ranks.getRank(...) das ist ziemlich umstäntlich.
Mit der Umstellung würdest du nur Ranks.getRank(...) aufrufen.

Und nein das ist kein schlechter Stil, das kann man so machen, eigentlich ist alles erlaubt, erst wenn es drauf ankommt auf Erweiterbarkeit, Einfachheit und Performance müsste man nochmal gucken.



fk1 hat gesagt.:


> Gibt es vielleicht andere Klassen, die du erstellen würdest, wenn du an ein komplettes Spiel denkst?


Ich würde wie schon erwähnt mich hinsetzten überlegen wie so ein Spiel abläuft und mir auf Papier aufschreiben was für Klassen ich so bräuchte. Also was gehört alles zum Spiel: Wahrscheinlich die Spieler, Tisch, Dealer, WieAuchImmerGeradeDieChipsHeißen, Pot, ... (ich bin gerade in Gedanken an einem Pokertisch... kenne mich aber nicht so wahnsinnig mit Poker aus ^^) Vielleicht noch paar Tischbeine


----------



## fk1 (19. Dez 2015)

Ich meinte andere Klassen, in die du dann die Definition aller Suits und Ranks packen würdest. Aber wenn das so i.O. ist, dann orientiere ich mich jetzt mal an diesen Start und arbeite damit mal weiter.

abstract hatte ich kurz angeschnitten aber schon wieder vergessen. Von daher ist das ja gut, denn so muss ich nochmal nachlesen.  Ich sage mal danke und probiere daraus dann demnächst ein Deck zu formen und in einer Test.class auszugeben.

Jetzt muss ich mich fertig machen, heute Abend steht der neue Star Wars Streifen auf dem Programm. Möge die Macht mit euch sein


----------



## fk1 (21. Dez 2015)

Guten Abend,

Star Wars war ok... irgendwie alles schon mal gesehen. Eventuell muss ich ihn ein zweites Mal sehen.

Heute Drei Zeilen Code geschrieben. Dann 3 Stunden Fehler Recherche betrieben 

Erst mal der Code:


```
public abstract class Suits {
    private String[] suits = {"c", "h", "s", "d"};

    public String getSuit(int suitIndex){
        return suits[suitIndex];
    }
}
```


```
public abstract class Ranks {
    private String[] ranks = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"};

    public String getRank(int rankIndex){
        return ranks[rankIndex];
    }
}
```

Möchte nun in der Card.class lediglich alles zusammen setzen:


```
public class Card {

    String card;
     
    public Card(int rankIndex, int suitIndex){
        card = Ranks.getRank(rankIndex) + Suits.getSuit(suitIndex);
    }
}
```

Wird quittiert mit



> Cannot make a static reference to the non-static method getSuit/getRank from the type getSuit/getRank



Google befragt. Scheint allgemein Anfänger zu überfordern. Jetzt mein Versuch das zu verstehen:

Ich kann in der Card.class die methode nicht als solche vollenden, da sie sich auf eine nicht-statische Methode bezieht. Also instanziere ich zuvor ein Objekt, damit ich etwas statisches kreirt habe, auf das ich mich beziehen kann.

Aber hey, die Suits/Ranks sind ja abstract und somit nicht instanzierbar, wenn ich das richtig verstanden habe (nachgelesen in Java ist auch eine Insel).

Jetzt sitze ich wieder hier, probiere herum. Aber alles durch die Reihe static setzen bringts irgendwie auch nicht. Es kommen nur Folgefehler, außerdem habe ich einen Artikel zum Thema gefunden in dem es auch heisst, dass alles static setzen auch nichts mehr mit OOP zu tun. Wie gesagt, das erschien mir eh nicht als das Gelbe vom Ei.

Leider finde ich immer nur die Lösung, ein neues Objekt a la Suits suit = new Suits; zu erstellen. Blöd ist es dann, wenn das bei abstract ja nicht funktioniert?!

Fühlt sich an wie 2 Wochen recherchiert aber nix wirklich verstanden.


----------



## fk1 (21. Dez 2015)

Ich habe noch eine Stunde gegoogled und probiert. Zwei Erkenntnisse:

Ohne abstrakte Klassen Suits & Ranks scheint folgende Card.class realisierbar:


```
public class Card {

    String card;
    int suitIndex;
    int rankIndex;

    public Card(int rankIndex, int suitIndex){
        Ranks cardRank = new Ranks();
        Suits cardSuit = new Suits();
        card = cardRank.getRank(rankIndex) + cardSuit.getSuit(suitIndex);
 
    }
}
```

Zumindest meckert Eclipse jetzt nicht mehr.

Ansonsten habe ich noch in einem englischen Forum gelesen das ich die abstrakten Methoden einer Klasse nutzen kann, wenn ich die Klasse Cards extende. Dann wäre noch die Frage: Kann ich die Klasse um zwei Klassen extenden?

Ich habs 


```
public class Suits {
    private String[] suits = {"c", "h", "s", "d"};

    public String getSuit(int suitIndex){
        return suits[suitIndex];
    }
}
```


```
public class Ranks extends Suits {
    private String[] ranks = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"};
 
    public String getRank(int rankIndex){
        return ranks[rankIndex];
    }
}
```


```
public class Card extends Ranks{
 
    String card;
    int suitIndex;
    int rankIndex;
 
    public Card(int rankIndex, int suitIndex){
        Ranks cardRank = new Ranks();
        Suits cardSuit = new Suits();
        card = cardRank.getRank(rankIndex) + cardSuit.getSuit(suitIndex);
     
    }
}
```

Klasse Ranks extends Suits und Card extends Ranks und dann meckert Eclipse auch nicht mehr. Jetzt ist für mich das letzte Rätsel, dass @Jardcore meinte, die neuen Objekte/Instanzen muss ich bei Nutzung von abstract nicht erstellen. Lasse ich die im Konstrukto weg,  bekomme ich leider immer noch den Fehler bezüglich static/non-static.

Ich probiere morgen ein Deck zu erzeugen.


----------



## fk1 (22. Dez 2015)

Ich stelle gerade fest, dass die classes doch nicht abstract gesetzt sind und die Vererbung anscheinend nichts gebracht hat, da die Instanzierung dann nicht mehr funzt, sobald man Suits&Ranks abstract setzt.


----------



## Jardcore (22. Dez 2015)

Du musst nochmal gucken was du da jetzt eigentlich gemacht hast...
Deine Card Klasse ist jetzt ein spezielleres Konzept von Ranks... das ist aber nicht so.
Genauso ist Ranks kein spezielleres Konzept von Suits.

Spezielleres Konzept heißt soviel wie ein VW ist ein spezielleres Konzept von Auto. Eine Katze ist ein spezielleres Konzept eines Säugetieres, was wiederum ein spezielleres Konzept eines Tieres ist.

In deinem Fall würde man ja nicht sagen das eine Karte ein spezielleres Konzept einer Farbe ist... usw.

Wieso möchtest du denn eigentlich über den Index auf die Ranks und Suits zugreifen. Eigentlich willst du doch nur 52 Karten erstellen also alle Kombinationen aus Ranks und Suits. Der Index müsste eigentlich egal sein. Die Kombinationen sollen dann in einem Deck landen und man soll dann wahrscheinlich immer eine Karte aus dem Deck ziehen können.


```
public abstract class DeckBuilder {
     private static final String[] RANKS = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"};
     private static final String[] SUITS = {"c", "h", "s", "d"};

     /**
      * Erstellt ein Deck und fügt 52 geordnete Karten hinzu.
      * Dabei werden die Kombinationen aus RANKS und SUITS gebildet.
      * @return Deck mit 52 geordneten Karten.
      */
     public static Deck createDeck() {
         // neues Deck erzeugen
         Deck deck = new Deck();
         // Alle Suits einmal durchgehen
         for(String suit : SUITS) {
             // Alle Ranks einmal durchgehen
             for(String ranks : RANKS) {
                 // Neue Karte erzeugen und Suit und Rank übergeben, anschließend zum Deck hinzuzufügen
                 deck.add(new Card(suit, rank));
             }
         }
         // das neue Deck mit allen Karten zurückgeben.
         return deck;
     }
}
```
Ich hab hier mal einfach einen "DeckBuilder" erstellt, der macht nichts weiter als ein Deck zusammen zu stellen. Dafür muss deine Deck Klasse eine *add* Methode haben die eine Karte zu der Liste der vorhandenen Karten hinzufügt.
Diesmal voll kommentiert, glaube das hilft dir mehr.

Die Extra Klassen für Rank bzw Ranks würde nur Sinn ergeben wenn du deiner Card Klasse beibringen würdest damit auch ordentlich umzugehen. Also als Attribute ala private Suit suit, private Rank rank.

P.S: Die Klasse ist eine abstrakte Klasse und du kannst createDeck wie folgt benutzten.
*Deck* deck = *DeckBuilder*.createDeck();


----------



## fk1 (22. Dez 2015)

Extenden wollte ich, weil die von dir beschriebene Variante, eine abstrakte Methode aufzurufen, bei mir nicht funktioniert hat. Ich lösche den ganzen extends Unsinn und setze die Suits/Ranks wieder abstract. Jetzt sieht meine Card.class so aus:


```
public class Card {

    String card;
    int suitIndex;
    int rankIndex;

    public Card(int rankIndex, int suitIndex){
        Ranks cardRank = new Ranks.getRank(rankIndex);
        Suits cardSuit = new Suits.getRank(suitIndex);
        card = cardRank + cardSuit;
    }
}
```

Das geht so nicht. eclipse: "can not instantiate the type Suits/Ranks". Auch außerhalb des Konstruktors geht das nicht. Zumindest bei mir nicht. Daher war ich auf Abhilfe im Netz unterwegs und fand extend, damit es geht. Aber wie du schon sagst, das ist rein logisch Unsinn und funktioniert davon abgesehen auch gar nicht, also vergessen wir das mit extend mal wieder.

Ich will eigentlich einfach zunächst am Ende nur ein SimpleDeck:


```
public class SimpleDeck {

    String[] deck = {
            "Ac", "Ah", "As", "Ad",
            "2c", "2h", "2s", "2d",
            "3c", "3h", "3s", "3d",
            "4c", "4h", "4s", "4d",
            "5c", "5h", "5s", "5d",
            "6c", "6h", "6s", "6d",
            "7c", "7h", "7s", "7d",
            "8c", "8h", "8s", "8d",
            "9c", "9h", "9s", "9d",
            "Tc", "Th", "Ts", "Td",
            "Jc", "Jh", "Js", "Jd",
            "Qc", "Qh", "Qs", "Qd",
            "Kc", "Kh", "Ks", "Kd"
    };
}
```

Am Anfang wollte ich einfach nur eine intelligentere Lösung für das Deck, als es stumpf von Karte 1 bis 52 herunterzuschreiben. Das ist quasi deine Klasse DeckBuilder.

Danke übrigens für die DeckBuilder.class und comments. Du hattest eine ähnliche Lösung ja bereits vorher gepostet. Ich hatte die sogar ohne comments verstanden und wollte die auch nutzen. Aber so weit bin ich ja gar nicht erst gekommen.

Ich habs nochmal weiter mit meiner Variante ohne abstract & extends bei Suits&Ranks probiert:


```
public class Card {
    String card;
    int suitIndex;
    int rankIndex;
    public Card(int rankIndex, int suitIndex){
        Ranks cardRank = new Ranks();
        Suits cardSuit = new Suits();
        card = cardRank.getRank(rankIndex) + cardSuit.getSuit(suitIndex);
    }
}
```

Dann mal eine Karte testweise ausgeben lassen:


```
public class Test {

    public static void main(String[] args) {
        Card card0 = new Card(0,0);
        System.out.println(card0);
    }

}
```

Spuckt die Konsole mir folgendes aus: "Card@4edf9252"

War also bisher ein voller Misserfolg.  Aber es ging ja auch darum, ein wenig OO zu denken und da hab ich jetzt auf jeden Fall schon ein wenig mehr gelernt. Klar, man kann es mit dem DeckBuilder lösen, man kann es simpel herunterschreiben, oder halt OOer und sogar die Karten als eigene Klasse definieren.

Kann ja mal sein, dass man später MauMau spielen will und dann keine 52 Karten mehr braucht. Oder man spielt ein Spiel, in dem Joker benötigt werden. Der Satz "Denk ich an Java, denk ich an Wiederverwertbarkeit" hängt mir da im Kopf.

Lange Rede, kurzer Sinn: Ich wollte jetzt erst mal vernünftig ein Objekt der Klasse Card erzeugen und nicht mal das haut richtig hin. Irgendwas hab ich da immer noch nicht verstanden.

Ein Card ist ein Objekt der Klasse Cards. Es hat die Attribute rank & suit. Wie soll das idealerweise aussehen?


----------



## CSHW89 (22. Dez 2015)

Die Ausgabe mit dem @ und den Zahlen ist die Standardausgabe eines jeden Objekts. Java kann ja nicht wissen, dass du den Inhalt der Variablen 'String card' ausgeben willst. Um es Java begreiflich zu machen, überschreibt man die toString-Methode in der Klasse Card:

```
public class Card
    ...
    public String toString() {
        return card;
    }
    ...
}
```
Allerdings ist es etwas schlechter Stil, die toString-Repräsentation in einem Attribut zu speichern. Man könnte die Erstellung des Strings in die toString-Methode auslagern. Die beiden Attribute 'suitIndex' und 'rankIndex' solltest du aber auch noch befüllen. Dann würde es so aussehen:

```
public class Card {
    int suitIndex;
    int rankIndex;
    public Card(int rankIndex, int suitIndex){
        this.rankIndex = rankIndex;
        this.suitIndex = suitIndex;
    }
    
    public String toString() {
        Ranks cardRank = new Ranks();
        Suits cardSuit = new Suits();
        return cardRank.getRank(rankIndex) + cardSuit.getSuit(suitIndex);
    }
}
```
Nun erstellt man in der toString-Methode immer zwei neue Objekte vom Typ Ranks und Suits. Das kann man so machen, man könnte aber auch wieder die abstract-static-Variante wählen. Man sagt Anfängern oft, alles static machen wäre schlechter Stil. Das stimmt zwar in vielen Fällen, aber definitiv nicht in allen, sonst würde es static ja gar nicht geben. In diesem Fall wäre es durchaus angemessen, die beiden Klassen Ranks und Suit abstract, und die Methoden getXXX bzw die Arrays auf static zu setzen.
Es gäbe noch eine weitere Möglichkeit, Stichwort Singleton. Das kannst du ja mal googlen. Es ist etwas OOPiger, verhindert aber, dass du ständig neue Objekte von Typ Ranks und Suits erstellst. Ist aber wie ich finde, nur eine etwas aufgeblasene abstract-static-Variante.

lg Kevin


----------



## Jardcore (22. Dez 2015)

fk1 hat gesagt.:


> Das geht so nicht. eclipse: "can not instantiate the type Suits/Ranks".


Das liegt daran das du das falsch Aufrufst, wenn du mal zurückblätterst siehst du wie man eine Methode in einer abstrakten Klasse aufruft.
Statt:
*Ranks* cardRank = new *Ranks*.getRank(rankIndex);
Musst du nämlich nur
*?String?* cardRank = *Ranks*.getRank(rankIndex);
aufrufen ohne "new" du willst ja eben KEINE Instanz erzeugen.

Die Methode getRank gibt übrigens (meins Wissens) einen String zurück. Und du hattest vor kurzen Suit und Rank auch noch als String in Card gespeichert. Die Ranks bzw. Suits Klasse sind nur Hilfscontainer die das Wissen aller möglichen Kartentypen enthalten.

Klar ist es später wahrscheinlich einfacher eine Rank und eine Suit Klasse zu haben, nur glaube ich das du noch nicht genau verstanden hast was eine Klasse bzw. ein Objekt ist und was eine Instanz eines Objekts ist. Deswegen sind deine Ranks, Suits und deine Card auch nicht ganz sauber.

Vielleicht nochmal der Versuch. Deine Card.class ist die Repräsentation EINER einzigen Karte. Und eine Karte hat nur EIN Bild und EINEN Wert.

```
public class Card {
    String suit;
    String rank;

    public Card(String suit, String rank) {
        this.suit = suit;
        this.rank = rank;
    }

    @Override
    public String toString() {
        return "Card " + suit + " " + rank;
    }
}
```
Man kann sich das auch gut merken indem man überlegt... Was HAT eine Karte, und das alles sind Attribute der Klasse. Also HAT eine Karte eine card? Ich glaube nicht.

Wie man hier sieht gibt es deshalb auch kein Attribut Namens card (String card...), denn die Instanz von Card selbst ist eben deine Repräsentation einer Karte.

Den ganzen Kram mit dem Index müsstest du, wenn überhaupt, machen bevor du die Karte erzeugst und das Ergebnis dann an den Konstruktor der Card beim Erzeugen übergeben.

P.S: Guck dir mal Listen in Java an (ArrayList ...) das würde dir... immernoch sehr viel Arbeit ersparen


----------



## Luecx (23. Dez 2015)

Heyho,

Ich hab grad mal auf die schnelle versucht mich in dein Programm reinzuarbeiten und muss dir sagen, dass das so funktioniert, aber ÜBERHAUPT nicht schön ist... Du arbeitest schließlich Objektorientiert und es wäre am einfachsten alles als ein Objekt anzusehen. Mach eine Klasse Karte, eine Klasse Deck und dann die Klasse Dealer, dann brauchst du ne klasse chips, ne klasse Spieler... Bau dir für alles eine Klasse. Du kannst dann einfach die Klasse Deck haben, ne Methode programmieren, die dann intern deiner ARRAYLIST<Karte> jeweils 52 unterschiedliche Karten hinzufügt und so weiter, dann ne Methode shuffle zum mischen und dann nimmst du immer die obersten karten und gibst sie den Spielern weiter. Der Code wird viel einfacher, und Vllt auch kürzer  

Mit freundlichen Grüßen,
Luecx


----------



## InfectedBytes (23. Dez 2015)

fk1 hat gesagt.:


> ```
> public class SimpleDeck {
> 
> String[] deck = {
> ...


Die verschiedenen Karten würde ich auch nicht als String kodieren. Mach lieber eine enum für die Farbe und einen int für den Wert (oder auch eine enum):

```
public enum Color {
  CLUBS, SPADES, HEARTS, DIAMONDS
}
public class Card {
  Color color;
  int value; // 1 = Ass , 2=2 , .... 11=Bube, 12=Dame, 13=König
}
```
Anstatt dem int kannst du natürlich auch hier eine Enum benutzen:

```
public enum Value {
  AS, D2, D3, D4, D5, D6, D7, D8, D9, D10, JACK, QUEEN, KING
}
```


----------



## fk1 (23. Dez 2015)

@Jardcore: Danke für die Tips und deine Geduld. Du hast recht, da ist inzwischen einiges durcheinander gekommen und das ist wohl auch der Grund, wieso ich das noch nicht richtig verstanden habe. Ich dachte immer, um einen Wert auszugeben, muss man ihn auch zuvor definieren. Daher hat Card bei mir bisher eine card  Ein String Wert, der sich aus Rank + Suit zusammen setzt.

Wenn ich von deinem Card Beispiel nun ein Objekt erzeuge, macht das doch gar nix, außer die Werte Suit & Rank setzen (Nur Konstruktor betrachtet)!? Verstehe nicht, wie ich damit weiterarbeiten soll. getString() ist ja dann wieder nur dazu da, mir die Karte als Text zu übergeben. Wieso dann nicht auch als String speichern? Warum statt dessen als methode "holen"?

Bzgl: ArrayLists: Ich glaube ich weiss was das ist, Listen halt. Dynamische/flexible Arrays. Wieso mir das jetzt mehr Arbeit erspart, scheine ich nicht zu sehen.

@Luecx Habe ich auf den letzten Seiten schon zu hören bekommen, aufgenommen und arbeite seitdem daran es zu verstehen, zu verinnerlichen und umzusetzen.

@InfectedBytes Eine Erläuterung, warum Enums einem String Array vorzuziehen sind, wären hilfreich. Die Enums hat @Jardcore schon eine Seite zuvor vorgeschlagen. Ich wollte nur nicht alles vorgekaut bekommen und habe es deswegen mit meiner Idee mittels Arrays/Strings probiert.


----------



## DieKeksmaffia (23. Dez 2015)

wurde bereits in der Zeit beantwortet //überspringen


----------



## fk1 (25. Dez 2015)

Frohes fest zusammen! 

Ich gebs auf! 

Besser gesagt: Ich möchte einen Strich ziehen. Das, was bisher besprochen wurde, als Lehrmaterial nutzen und einfach mal weiter machen. 

Ich habe mich der Enum Lösung nochmal angenommen und die Basis von @Jardcore übernommen:


```
public enum Suits {
        c,
        s,
        d,
        h;
}
```


```
public enum Ranks {
    ACE("A"),
    TWO("2"),
    THREE("3"),
    FOUR("4"),
    FIVE("5"),
    SIX("6"),
    SEVEN("7"),
    EIGHT("8"),
    NINE("9"),
    TEN("T"),
    JOKER("J"),
    QUEEN("Q"),
    KING("K");

    private String text;
    private Ranks(String text) {
        this.text = text;
    }
    public String getText() {
        return text;
    }
}
```


```
public class Card {
    private Suits suit;
    private Ranks rank;
    public Card(Ranks rank, Suits suit) {
        this.rank = rank;
        this.suit = suit;
    }
    public Ranks getRank() {
        return rank;
    }
    public Suits getSuit() {
        return suit;
    }
    @Override
    public String toString() {
        return String.format("%s%s", rank.getText(), suit);
    }
}
```

Hier meine Frage zu den Methoden getSuit & getRank: Da die bisher nicht verwendet werden, sind die rein provisorisch angelegt?

Weiter mit dem Deck in Form einer ArrayList:


```
import java.util.*;

public class Deck{
   
    ArrayList<Card> deck = new ArrayList<Card>();
   
    public void createDeck(){
        for(Ranks rank : Ranks.values()){
            for (Suits suit : Suits.values()){
                deck.add(new Card(rank, suit));
            }
        }
    }   
}
```

Hier mal eine Verständnisfrage: in den erweiterten for-Schleifen beginnen wir mit "Ranks rank". Ist das ein neu erzeugter Wert der Klasse bzw. Enums rank? Wie muss ich das verstehen?

Ranks.values erzeugt ein Array aller Ranks Enums und die foreach Schleife durchläuft das dann. Soweit, so gut. Nur woher kommt Ranks rank bzw. wie setzt sich das zusammen?

Dann zwecks Ausgabe eine Test class:


```
public class Test {
   
    public static void main(String[] args) {
        Deck blueDeck = new Deck();
        blueDeck.createDeck();
        System.out.print(blueDeck.toString());
    }

}
```

Ich erzeuge in der test class mal ein neues Deck blueDeck (gibt ja in einer Packung meist 2 Decks, ein rotes und ein blaues, rein der Übersicht wegen. Deck deck = new Deck(); ist dann schwer nach zu vollziehen für mich als Anfänger)

Jetzt bekomme ich wieder diese Zeichenkette ausgegeben: Deck@70c787d7

Habe ja dank @CSHW89 schon gelernt dass das die Java Ausgabe ist und noch nicht als String konvertiert. Ich dachte jetzt, das habe ich dank blueDeck.toString(), konvertiert aber anscheinend doch nicht?! Irgendwas mache ich anscheinend falsch...


----------



## Jardcore (26. Dez 2015)

Die Zeichenkette zeigt zur Adresse im Speicher, also wo das Deck liegt.
Damit du dein Deck als String ausgeben kannst musst du deiner Deck Klasse eine toString Methode definieren und dort wiederrum festlegen wie dein Deck als String aussehen soll.

Die Verwirrung um Deck deck = new Deck kann man schnell auflösen. Jedes Objekt hat einen Standardkonstruktor, dieser ist der Name der Klasse ohne Parameter. Das heißt wenn du keinen eigenen Standartkonstruktor definkerst wird einfach der schon vorhandene genommen. Der Standartkonstruktor macht meist einfach nichts 


fk1 hat gesagt.:


> Soweit, so gut. Nur woher kommt Ranks rank bzw. wie setzt sich das zusammen?


Du bekommst mit Ranks.values ALLE möglichen Werte die du in Ranks definiert hast. Dann gehst du in der for(each) jeden Wert nacheinander durch, und der Wert bei dem die Schleife aktuell ist wird vorrübergehend in Ranks rank gespeichert. Du könntest das Enum auch nur Rank nennen dann könnte das vllt Verwirrungen vermeiden.

Beste Grüße und frohe Weinachten


----------



## Jardcore (26. Dez 2015)

Man man, soviele Rechtschreibfehler.... sind alles Geschenke meines Tablets XD


----------



## fk1 (26. Dez 2015)

Wurde da jemand etwa mit einem Tablet beschert? Welches tablet nutzt du denn?

Ich hatte gedacht, dass die blueDeck.toString(); Methode fester Bestandteil durch die ArrayList ist. Als ich ausgeschlafen heute morgen deinen Post gelesen hatte, wusste ich, das war Quatsch  Ich habe gestern anscheinend einfach wieder zu lange vor dem Rechner gesessen.


```
import java.util.*;

public class Deck{
 
    ArrayList<Card> deck = new ArrayList<Card>();
 
    public void createDeck(){
        for(Ranks rank : Ranks.values()){
            for (Suits suit : Suits.values()){
                deck.add(new Card(rank, suit));
            }
        }
    }
 
    public String toString(){
        return String.format("%s", deck);
     
    }
}
```

Jetzt liefert die test.class folgendes:



> [Ac, As, Ad, Ah, 2c, 2s, 2d, 2h, 3c, 3s, 3d, 3h, 4c, 4s, 4d, 4h, 5c, 5s, 5d, 5h, 6c, 6s, 6d, 6h, 7c, 7s, 7d, 7h, 8c, 8s, 8d, 8h, 9c, 9s, 9d, 9h, Tc, Ts, Td, Th, Jc, Js, Jd, Jh, Qc, Qs, Qd, Qh, Kc, Ks, Kd, Kh]


----------



## fk1 (26. Dez 2015)

Wäre es besser, die methode createDeck() als Konstruktor für die Klasse Deck zu nutzen? Bzw. ergibt es mehr Sinn in Anbetracht von OOP? zumindest spare ich mir dann in der Test class die createDeck line und die Deck.class hat dann einen Konstruktor:


```
import java.util.*;

public class Deck{
   
    ArrayList<Card> deck = new ArrayList<Card>();
   
    public Deck(){
        for(Ranks rank : Ranks.values()){
            for (Suits suit : Suits.values()){
                deck.add(new Card(rank, suit));
            }
        }
    }
   
    public String toString(){
        return String.format("%s", deck);
       
    }
}
```


```
public class Test {
   
    public static void main(String[] args) {
        Deck blueDeck = new Deck();
        System.out.print(blueDeck.toString());
    }

}
```


----------



## Jardcore (26. Dez 2015)

Ja, das kannst du machen. Und du kannst dir den Aufruf bei blueDeck.toString() sparen, die toString() Methode wird explizit aufgerufen wenn du ein Objekt als String ausgeben willst. Also System.out.println(blueDeck); reicht.

Du kannst übrigens noch einen ziemlich advanced Trick anwenden. Und zwar die "deck" variable aus Deck löschen und dafür dein Deck von ArrayList<Card> extenden. Dann bräuchtest du vllt noch einen DeckBuilder bzw den Dealer und der bekommt dann Methoden wie createDeck() oder getCard(). 

Achja der Vorteil übrigens der ArrayList ist das du durch den Aufruf Collections.shuffle(deck) dein Deck mischen kannst. Da dein Deck nun eine Liste ist die von Collections erbt kannst du auch die Hilfsklasse Collections benutzen um einige Operationen auszuführen.


fk1 hat gesagt.:


> Wurde da jemand etwa mit einem Tablet beschert? Welches tablet nutzt du denn?


Ne das hab ich schon seit 2013, Samsung Galaxy 10.1 Tablet


----------



## fk1 (26. Dez 2015)

Auf die Möglichkeit, auf .toString(); zu verzichten, bin ich gerade eben zufälligerweise selbst gekommen, als ich mich mit Collection.shuffle herumgetestet habe. ^^ 

Zu deinem Vorschlag: Meinst du das so? Ich nutze erstmal Test, bis ich mir Gedanken um eine neue Klasse Dealer/DeckCreator o.Ä. gemacht habe:


```
public class Deck extends Test{
   

   
    public Deck(){
        for(Ranks rank : Ranks.values()){
            for (Suits suit : Suits.values()){
                deck.add(new Card(rank, suit));
            }
        }
    }
   
    public String toString(){
        return String.format("%s", deck);
       
    }
}
```


```
import java.util.ArrayList;
import java.util.Collections;

public class Test{
   
    ArrayList<Card> deck = new ArrayList<Card>();
   
    public static void main(String[] args) {
        Deck blueDeck = new Deck();
        Collections.shuffle(blueDeck.deck);
        System.out.println(blueDeck);
    }
}
```


----------



## Jardcore (26. Dez 2015)

```
public class Deck extends ArrayList<Card> {

    private static final int FIRST_CARD = 0;

    public Deck(){
        for(Ranks rank : Ranks.values()){
            for (Suits suit : Suits.values()){
                this.add(new Card(rank, suit));
            }
        }
    }

    public Card getCard() {
        return remove(FIRST_CARD);
    }

    public void shuffle() {
        Collections.shuffle(this);
    }
}
```

Alles ausm Kopf geschrieben, aber so sollte das funktionieren.
Man müsste bei getCard() noch gucken ob es überhaupt noch Karten gibt.

P.S: So braucht man auch nicht unbedingt ein Dealer, außer man braucht mehr Funktionalität, z.B.: Karten verteilen usw.


----------



## fk1 (26. Dez 2015)

OK, dann muss ich jetzt nochmal nachlesen bzgl ArrayLists extenden, dachte es geht nur mit Klassen EDIT: Achja lol, ArrayLists sind ja definiert als Klassen wenn ich mich recht erinnere.

return remove(0); muss ich auch noch überdenken. Verstehe es jetzt so, dass das erste Objekt mit dem index 0 aus der ArrayList returned wird und dann auch direkt aus dem Array entfernt(remove) ?!

Mal wieder allgemein gefragt:

Sind die Methoden shuffle() und getCard() Fähigkeiten, die ich später besser in der Dealer class definiere? Passen imho besser dahin, denn der Dealer mischt ja die Karten oder zieht eine Karte, die er verteilt.


----------



## fk1 (26. Dez 2015)

Ich glaube ich habe noch den Code gesehen, bevor du ihn editiert hast:

Hast du die int FIRST_CARD editiert um eine magicnumber zu vermeiden? 

Eclipse hat noch wegen einer UID gemeckert daher habe ich eine generieren lassen. So sieht die extra line aus:


```
private static final long serialVersionUID = 4287793858292977743L;
```


----------



## fk1 (26. Dez 2015)

Ich habe mir Gedanken um die Problematik gemacht, wenn alle Karten ausgeteilt sind. Ich habe mal testweise 53 karten ausgeben lassen und Eclipse wirft auch, wie von @Jardcore erwartet, Fehler.

Dann habe ich mir überlegt, die getCard() Methode mit einer if Bedingung zu beschränken. Ich habe die Idee dann wieder verworfen, weil ich meine mich zu erinnern, dass in solche get-Methoden lediglich eine return Zeile stehen soll, sonst nichts.

Dann habe ich mir überlegt: Ich erstelle eine zusätzlich Methode die prüft, ob Karten übrig sind. Wenn ich später dann eine Karte ziehen will bzw. Deck.getCard() benutze, prüfe ich vorher, ob überhaupt Karten übrig sind.

Zusätzliche Methode in der Deck.class:


```
public boolean checkIfDeckEmpty(){
        if(this.get(FIRST_CARD)==null){
            return true;
        }else{
            return false;
        }
    }
```

Hiermit wollte ich folgendes realisieren: Prüfen ob Deck leer -> falls leer, kein neues Objekt erzeugen. Klappt aber trotzdem nicht so wirklich, ich kriege weiterhin Errors

Test.class:


```
public class Test{
   
    public static void main(String[] args) {
        Deck blueDeck = new Deck();
        Card blueCard;
       
        for(int i=0; i<53; i++){
           
            if(blueDeck.checkIfDeckEmpty() == true){
                blueCard = null;
            }else{
                blueCard = blueDeck.getCard();
            }   
       
        System.out.println(blueCard);
        }
    }
}
```

Ich habe die Vermutung das die Prüfung der Bedingung if(this.get(FIRST_CARD)==null) nicht das macht, was ich glaube. Ich weiss aber auch nicht, wie ich das überprüfe. Vielleicht weiss ich es ja morgen.  Hänge anscheinend wieder viel zu lange vor dem Rechner...


----------



## Jardcore (26. Dez 2015)

fk1 hat gesagt.:


> Hast du die int FIRST_CARD editiert um eine magicnumber zu vermeiden?


Jep 


fk1 hat gesagt.:


> Dann habe ich mir überlegt, die getCard() Methode mit einer if Bedingung zu beschränken


Also das ist grundsätzlich löblich, aber an dieser Stelle ist das kein richtiger Getter, weil du nicht auf ein Attribut von Deck.class zugreifst. Hier ist nur das get im Name weil ich dachte... könnte passen  Also kannst du die Abfrage dort machen. Da du hier von ArrayList erbst hast du übrigens schon die Methode isEmpty() mitgeerbt. Benutze mal den shortcut Strg+Leertaste außerhalb einer Methode, dann siehst du was für mögliche Methoden du noch alles hast. Für dein Problem könntest du nun sowas machen:

```
public Card getCard() {
    if(isEmpty()) { 
        return null;
    }
    return remove(FIRST_CARD);
}
```
Und später kannst du dann in deinem Programm darauf reagieren, dass bei null keine Karte mehr gegeben werden konnte.
Aufjedenfall kannst du jetzt auch von 0-1000 zählen bekommst dann halt nur 52 Karten 
und dann nur noch null als Ausgabe 



fk1 hat gesagt.:


> Hiermit wollte ich folgendes realisieren: Prüfen ob Deck leer -> falls leer, kein neues Objekt erzeugen. Klappt aber trotzdem nicht so wirklich, ich kriege weiterhin Errors


Finds cool das du schreibst was du realisieren wolltest, das hilft mir zu verstehen was du vorhast... mehr davon 



fk1 hat gesagt.:


> Hänge anscheinend wieder viel zu lange vor dem Rechner...


<--- deshalb Tablet XD Eclipse wäre noch super, aber man kann nicht alles haben


----------



## fk1 (26. Dez 2015)

Wenn das kein richtiger Getter ist, schlage ich vor die Methode in drawCard umzubenennen. Bzgl. Tablet: ich selber finde man ist am laptop produktiver, allein schon wegen dem Keyboard. Aber wenn du Eclipse auf dem Tablet haben willst: Teamviewer funzt super! Laptop an, Teamviewer starten und am Tablet coden


----------



## fk1 (27. Dez 2015)

Sooo... vor zwei Wochen kam ich hier mit meinem ersten eigenen Java "Script" hier her. Jetzt haben wir die gleiche Funktion OO gestaltet. Außerdem kommt ein wenig Neues hinzu, aber immer der Reihe nach. 

Ich habe zur Übersicht mal ein neues Diagramm mit ObjectAid erstellt:







Jetzt zur Erklärung: Ich habe eine Klasse Dealer erstellt um ein paar Sachen zu ordnen. Der Dealer hat folgendes:

- Er kennt die Anzahl der auszuteilenden holecards (die versteckten Karten eines Spielers)
- er hat ein aktives Deck Karten
- er hat eine aktuell gezogene Karte currentCard, die er verteilen soll

Zusätzlich bekommt er zwei Methoden. Wer schonmal ein Turnier gespielt hat, kennt vielleicht den berühmten Satz, den Turnierveranstalter zum eröffnen des Turniers bekannt geben: "Shuffle up and deal!"

Also soll unser Dealer folgendes können: Ein Deck in die Hand nehmen und mischen (shuffle up) und dann Karten austeilen (deal). In unserem Fall soll er pro Spieler zwei Karten austeilen. 

Da wir zunächst der einzige Spieler sind, reicht die for-schleife, die ich nutze. Wenn da mehr Spieler hinzukommen, muss man die nochmal überdenken. Um da hin zu kommen, wo ich vor zwei Wochen war, reicht das erstmal.



Spoiler: Dealer.class





```
public class Dealer {
   
    private static final int numHolecardsHoldem = 2; //Anzahl holecards pro Spieler
    private Deck activeDeck; 
    private Card currentCard;
   
    public void shuffleUp(){
        activeDeck = new Deck();
        activeDeck.shuffle();
    }
   
    public void dealHoldem(Holecards seatNum){
        for(int i=0; i<numHolecardsHoldem; i++){
            currentCard = activeDeck.drawCard();
            seatNum.addHolecard(currentCard); // seatNum erkläre ich im Beitrag noch
        }
    }
}
```




die Methode dealHoldem bekommt Holecards seatNum übergeben. Dazu kommen wir daher als nächstes.

Für die holecards nutze ich im Grunde die gleiche Idee, wie für das Deck. wholecards sind im Grunde auch nur ein Stapel aus Karten, die der Spieler bekommt. In diesem Fall ein Stapel aus zwei Karten. Also eine extended class Holecards:



Spoiler: Holecards.class





```
import java.util.ArrayList;

public class Holecards extends ArrayList<Card> {

    private static final long serialVersionUID = -2278901932251803755L; //Wird von Eclipse gewünscht bzw. generiert
   
    public void addHolecard(Card holecard){
        this.add(holecard);
    }
}
```




Vorteil in Form einer ArrayList ist wohl die flexible Größe: Denke ich an die Variante Omaha mit vier statt zwei holecards, muss ich dem Dealer nur die Anzahl für Omaha bei bringen und dementsprechend eine andere Methode.

Bezüglich dem Übergabewert seatNum: Ich plane später eine Klasse Seat zu erzeugen. Zu einem Seat gehören dann z.B. die holecards, relative Spielpositionen, Chipstacks, etc. 

Da das aber noch Zukunftsmusik ist und ich die holecards eines Spielers nicht der Dealer.class zuweisen möchte, bediene ich mich bisher noch folgender Lösung:



Spoiler: Test.class





```
public class Test{
   
    private static Dealer dealer1 = new Dealer(); 
    private static Holecards hcseat1 = new Holecards();

    public static void main(String[] args) {
        dealer1.shuffleUp();
        dealer1.dealHoldem(hcseat1);
       
        System.out.println("Preflop: Your holecards: " + hcseat1);
```




Führe ich das alles aus, bekomme ich nun immer zwei Karten in der Konsole ausgeteilt. Also wie vor zwei Wochen, dank eurer Hilfe nun aber OO. 

Mein nächstes Ziel: Flop, Turn & River austeilen. Anschließend die Regeln für Pokerhände deklarieren und dementsprechend eine Pokerhand aus den ausgeteilten Karten bestimmen.

Also z.B. die Konsole spuckt aus:

Preflop: Your holecards: AcAh
Flop: AsKc2d
Turn: 3h
River: 7s

Your Hand: AcAhAsKc7s (Three of a kind, Aces)

Ideen, das umzusetzen, habe ich auch schon  Ein paar Ideen werde ich mal kurz anschneiden:

- Für Flop, Turn und River erzeuge ich eine neue ArrayList namens CommunityCards

- Die Test.class muss ja mal irgendwie, irgendwann so etwas wie eine main class werden. Ich denke, das realisiert man am besten mit einer class Table. Wer schon mal online gepokert hat, weiss, das jede Runde an einem Tisch realisiert wird. ich denke daher auch das die programmierer der online Casinos ähnlich vorgehen, also das ganze Spiel mit allem drum und dran unter einem Tisch ablaufen lassen

- Wie bereits erwähnt eine Klasse Seat mit Stacksizes, holecards für jeden Spieler und relativer Spielposition. eine Table.class ruft dann dementsprechend z.B. max 9 seats für 9 Spieler auf

Aber das sind erstmal nur Ideen. Ich konzentriere mich als nächstes auf  das Bestimmen von Pokerhands, das wird erstmal seine zeit dauern.

Bis hierhin nochmal danke an eure Hilfe, besonders @Jardcore! Wenn ich mich euch auch mal irgendwie helfen kann, helf ich gerne


----------

