2016-07-07 23 views
1

Ich versuche das beste Potenzial von OOP in Java zu erreichen, indem ich ein Blackjack-Spiel erschaffe. Ich habe bis jetzt 5 Java-Dateien.Java Blackjack OOP

Suit.java

enum Suit { 

/* 
* Initialize suit values 
*/ 
    HEARTS, 
    SPADES, 
    CLUBS, 
    DIAMONDS; 
} 

Rank.java

enum Rank { 

    /* 
    * Initialize rank and card value 
    */ 

    TWO(2), 
    THREE(3), 
    FOUR(4), 
    FIVE(5), 
    SIX(6), 
    SEVEN(7), 
    EIGHT(8), 
    NINE(9), 
    TEN(10), 
    JACK(10), 
    QUEEN(10), 
    KING(10), 
    ACE(11); 


    // Hold card value 
    private int cardValue; 

    /* 
    * Constructor set card value 
    * @param cardValue value of card 
    */ 
    private Rank(int cardValue) { 
     this.cardValue = cardValue; 
    } 

    /* 
    * This method obtains the card value 
    * @return This returns the value of card 
    */ 
    public int getCardValue() { 
     return cardValue; 
    } 
} 

Card.java

public class Card { 

    private Suit suit; 
    private Rank rank; 


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

    public Rank getCardValue() { 
     return rank; 
    } 

    public Suit getSuitValue() { 
     return suit; 
    } 
} 

deck.java

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Random; 


public class Deck { 

    private ArrayList deck; 

    public Deck() { 

     this.deck = new ArrayList(); 

     for(Suit suit : Suit.values()) { 
      for(Rank rank: Rank.values()) { 
       Card card = new Card(rank, suit); 
       this.deck.add(card); 
      } 
     } 

     Collections.shuffle(deck); 
    } 

    public ArrayList getDeck() { 
     return deck; 
    } 
} 

Game.java

import java.util.ArrayList; 
import java.util.Iterator; 

public class Game { 

    public static void main(String[] args) { 

     Deck deck = new Deck(); 

     for(int i=0; i<deck.getDeck().size(); i++) { 

      System.out.println(((Card) deck.getDeck().get(i)).getCardValue() + " of " 
      + ((Card) deck.getDeck().get(i)).getSuitValue()); 
     } 
    } 
} 

Macht mein Entwurf bis jetzt Sinn? Auch wie kann ich (Rank.java) -> int getCardValue() statt (Card.java) -> Rank getCardValue() aufrufen? Muss ich etwas Polymorphismus machen? erweitern? Ich möchte den int-Wert nicht den Textwert.

Danke!

+1

Dies ist möglicherweise keine geeignete Frage für diese Website. Wie gehen Sie nun mit den potenziellen Doppelwerten des ACE-Rangs 1 und 11 um? –

+3

Ja, in der Tat ist ein besserer Platz für diese Frage [codereview.SE.com] (http://codereview.stackexchange.com/) – martijnn2008

+1

Um den Rang zu bekommen, benutzen Sie einfach 'getRank()' und rufen 'getValue()' auf auf das Objekt zurückgegeben .... oder welchen Namen auch immer Sie diese Methoden geben. –

Antwort

2

Ihre direkte Frage zu beantworten, alles, was Sie tun müssen, ist es, Methoden zu einfach Kette:

Card myCard = new Card(Rank.TWO, Suit.HEARTS); 
int value = myCard.getCardValue().getCardValue(); 

Der erste getCardValue() Aufruf gibt ein Rank-Objekt, und die nächsten getCardValue() get ist der Wert des Ranges. Aber das ist verwirrend für mich, zwei Methoden mit demselben Namen, die verschiedene Typen zurückgeben. Ich würde Card's getCardValue() umbenennen, um die einfacheren und logischeren getRank() und Ranks getCardValue() zu den einfacheren getValue() umzubenennen. Dann würde der Code aussehen logischer:

int value = myCard.getRank().getValue(); 

Was Ihre andere Frage, „ist das Design OK“, dass für diese Seite zu breit ist, aber ich denke, dass Sie die Vererbung in Ordnung verwenden, dass Sie don‘ Ich möchte die Vererbung überbeanspruchen und bei der Komposition bleiben, wie Sie es tun. Und ich will auch sagen, dass Sie für ACE mit zwei möglichen Werten berücksichtigen müssen, 1 und 11.

Zum Beispiel, vielleicht so etwas wie:

public enum Rank { 

    TWO(2, 0, false), 
    THREE(3, 0, false), 
    FOUR(4, 0, false), 
    FIVE(5, 0, false), 
    SIX(6, 0, false), 
    SEVEN(7, 0, false), 
    EIGHT(8, 0, false), 
    NINE(9, 0, false), 
    TEN(10, 0, false), 
    JACK(10, 0, false), 
    QUEEN(10, 0, false), 
    KING(10, 0, false), 
    ACE(11, 1, true); 

    private int value; 
    private int value2; 
    private boolean twoValues; 

    private Rank(int value, int value2, boolean twoValues) { 
     this.value = value; 
     this.value2 = value2; 
     this.twoValues = twoValues; 
    } 

    public int getValue() { 
     return value; 
    } 

    public int getValue2() { 
     // TODO: consider throwing a custom exception if twoValues is false 
     return value2; 
    } 

    public boolean hasTwoValues() { 
     return twoValues; 
    } 
} 
+0

Danke. Außerdem hatte ich getCardValue() zweimal. Ich habe gerade die Rank-Version in getRank() geändert. –

1

einfach ein paar Alternativen da draußen zu werfen: Ich würde vielleicht modelliere den Wert eines Ranges anders. Da die ace nicht wirklich einen bestimmten Wert hat. Ein Hand hat einen Wert, aber auch das hat tatsächlich einen „besten Wert“, die ein ace 11 oder 1.

zählen kann, so würde ich vielleicht den Wert eines Rang entfernen. Und die Einführung einer Hand:

public class Hand { 
    private Hand(Collection<Card> cards) { 
     ... 
    } 

    private int calculateBestValue() { 
     ... 
    } 
} 

Ich würde auch nicht die Wertberechnung öffentlich machen. Die Hand könnte sich "präsentieren", also kann sie auch sagen, ob Sie einen "weichen" Wert haben oder nicht.

Ich denke auch, dass die Deck keine getDeck() Methode haben sollte. Das verletzt die Kapselung. Stattdessen sollte es eine Methode genannt: nextCard(). Welche gibt dir die nächste Karte von der Oberseite des Decks.Es kann auch eine isEmpty() Methode benötigen, die zurückgibt, ob das Deck Karten hat oder nicht.