2012-02-06 11 views
5

¿Cuál sería el mejor enfoque al diseñar las siguientes clases aplicando patrones de diseño?OOP Design for Card Game Classes

  • cubierta-addCard, trato, shuffle, getTopCard, removeTopCard, removeAllCards
  • mano-addCard, eliminarCarta, getCard, removeAllCards
  • DiscardPile-addCard, getTopCard , eliminarTopCard, eliminar TodasCartas
  • MeldPile-addCard, removeAllCards

(El MeldPile tiene todos los melds en la mesa.)

Para mí, creo que el getTopCard y removeTopCard son sólo un envoltorio de getCard y removeCard, como simplemente obtiene la posición superior de una tarjeta y luego la pasa a getCard o removeCard.

¿Debo usar composición? patrón de estrategia? o simplemente crea otra clase llamada CardPile y úsala como la clase base de la clase anterior? Realmente aprecio si pudieras proporcionar un código de muestra sobre esto.

+3

El mejor enfoque es simplemente comenzar a escribir el reglas del juego y deja que tu diseño evolucione de forma natural. Si tiene una pregunta específica, p. "Estoy tratando de implementar una regla en la que si un jugador juega una carta la otra jugada debe descartarse, ¿qué patrón debo usar aquí?" eso podría ser responsable. –

+1

+1 para "dejar que su diseño evolucione de forma natural" – radarbob

+0

Tenga cuidado al delegar las clases de "origen natural" en las clases base de partículas subatómicas. Las jerarquías de clases pueden llegar a ser demasiado profundas con el procesamiento innecesario genérico y gratuito. Siempre puede refactorizarse más adelante si su * evolución de diseño natural * requiere una base más general a partir de la cual derivar una nueva funcionalidad. – radarbob

Respuesta

6

Creo que puede lograr lo que quiere con una sola clase de cubierta como la que se muestra a continuación, que es esencialmente una envoltura alrededor de Stack, no veo por qué una determinada baraja/pila/mano no querría la mayoría si no todas las mismas métodos.

class Deck { 
    private Stack<Card> cards = new Stack<Card>(); 

    public Deck() { } 

    public Deck(int numberOfCards) { 
     for (int i=0; i<numberOfCards; i++) { 
      cards.push(CardFactory.createCard(i)); 
     } 
    } 

    private void shuffle() { 
     Collections.shuffle(this.cards); 
    } 

    public void sort() { 
     Collections.sort(this.cards); 
    } 

    public void removeAllCards() { 
     this.cards.removeAllElements(); 
    } 

    public void removeCard(Card c) { 
     int i = this.cards.search(c); 
     this.cards.remove(i);    
    } 

    public Card getCard(Card c) { 
     int i = this.cards.search(c); 
     return this.cards.get(i); 
    } 

    public Card getTopCard() { 
     return this.cards.pop(); 
    } 

    public Card getNthCard(int i) { 
     return this.cards.get(i); 
    } 

    public Card addCard(Card c) { 
     this.cards.push(c); 
    } 

} 

El único problema real que veo es con el método deal() y si esta debe ser la responsabilidad de una cubierta? Personalmente no lo creo, esto me lleva a pensar que tal vez tendría una clase de jugador y una clase de distribuidores que se extiende jugador e implementa la lógica de tratar una cubierta

class Player() { 
    protected String name; 
    protected Deck hand = new Deck(); 

    public void addCard(Card c) { 
     this.hand.addCard(c); 
    } 

    // ..... 
} 

class Dealer() extends Player { 
    private Deck deck; 

    public Dealer(int deckSize) { 
     this.deck = new Deck(deckSize); 
    } 

    public void deal(Player[] players, int numberOfCards) { 
     for (player in players) { 
      for (int i=0; i<numberOfCards; i++) { 
       player.addCard(this.deck.getTopCard()); 
      } 
     } 
    } 

    // ..... 
} 
+0

No entendí realmente qué era una pila de fusión o si sonaba un poco MtG ¿le pertenece a un jugador? Por ejemplo, un juego de estilo MtG (a partir de mi breve experiencia jugando) el jugador tendría un mazo, una mano, el poder del elemento jugaba cartas, y el monstruo jugó todo lo que creo que podría ser un "mazo", aunque es posible que desees crear una clase base de 'Deck' que no implemente métodos como 'shuffle()' y usar eso como 'pilas menores de cartas' –

+0

Estoy de acuerdo con usted con respecto al método de reparto, no debería ser parte de un mazo como tratar es el comportamiento del distribuidor Un montón de fusión es un conjunto de cartas (Tres de una clase, Cuatro de una clase y Derecho) pertenecen a un jugador que publicó en la mesa.Simplemente no puedo decidir qué implementar porque la mayoría de los juegos de cartas de código abierto usan diferentes clases para Deck, Hand and Discard Pile y mientras que el otro acaba de crear un CardPile y lo usa como una clase base. – Zack

+0

Sugiero comenzar usando una sola clase base de CardPile que encapsularía la adición y eliminación de tarjetas de allí puedes heredarlo donde podrías tener un 'Deck' que se puede barajar y 'mágicamente creado', un' MeldPile' que tiene sus propias reglas para las cartas que puede contener, una "Mano" que puede establecer un número máximo de cartas permitidas y reglas para descartar. Más importante aún, creo que sería mejor comenzar algo, evitar 'patternitis' y refactorizar/optimizar tu código si es necesario. –