Diseñe las estructuras de datos (clases y objetos) para una baraja de cartas genérica

Diseñe las estructuras de datos para una baraja de cartas genérica. Explique cómo subclasificaría para implementar juegos de cartas particulares y cómo subclasificaría las estructuras de datos para implementar el blackjack.

Solución:

Primero, debemos reconocer que una baraja de cartas “genérica” puede significar muchas cosas. Genérico podría significar una baraja de cartas estándar que puede jugar un juego similar al póquer, o incluso podría extenderse a las cartas Uno o Baseball.

Para implementar juegos de cartas particulares

Supongamos que el mazo es un conjunto estándar de 52 cartas como el que podría ver en un juego de blackjack o póquer. Si es así, el diseño podría verse así:

La estructura es clara aquí: una baraja contiene cuatro palos y un palo contiene 13 cartas. Cada carta tiene un valor numérico del 1 al 13. Si piensas en un juego de cartas, los diferentes juegos difieren en la forma de repartir las cartas y volver a colocarlas. Así que podemos tener un conjunto de métodos abstractos dentro de la clase ‘Mazo’ para permitir subclase implementa su propia forma de tratar. El diagrama de clases que dibujo está aquí:


A continuación se muestra la implementación de la idea en C++.

/*1. Investigation on an individual card instead of 
   a collection of cards, focus on a card's state 
   and interface.
2. A card game has its own specific constrain and 
   requirement on cards, such that a generic card 
   cannot satisfy a blackjack card
3. Player manage multiple cards */
  
#include <bits/stdc++.h>
using namespace std;
  
namespace SUIT {
enum Enum {
    SPADE,
    HEART,
    CLUB,
    DIAMOND
};
};
  
class Card {
private:
    SUIT::Enum s;
    int v;
  
public:
    virtual SUIT::Enum suit() const
    {
        return s;
    };
  
    virtual int val() const
    {
        return v;
    };
  
    Card(int val, SUIT::Enum suit)
        : s(suit), v(val){};
};
  
class BlackJackCard : public Card {
public:
    virtual int val()
    {
        int v = Card::val();
        if (v < 10)
            return v;
        return 10;
    }
  
    BlackJackCard(int val, SUIT::Enum suit)
        : Card(val, suit){};
};
  
class player {
private:
    int id;
    int bet;
    set<int> points;
    vector<BlackJackCard*> bjcs;
    bool addPoint(set<int>& amp; points, BlackJackCard * card)
    {
        if (points.empty()) {
            points.insert(card->val());
            if (card->val() == 1)
                points.insert(11);
        } else {
  
            /* Set elements are ALWAYS CONST, they can't
               be modified once inserted. */
            set<int> tmp;
            for (auto it = points.begin(); it != points.end(); ++it) {
                tmp.insert(*it + card->val());
                if (card->val() == 1)
                    tmp.insert(*it + 11);
            }
            points = tmp;
        }
    }
  
    void getPoints()
    {
        cout << "You All Possible Points : " << endl;
        for (auto it = points.begin(); it != points.end(); ++it) {
            cout << *it << endl;
        }
    };
  
    int getMinPoints()
    {
        /* set is implemented by commonly BST, so else 
          are in order!!!
          learn to use lower_bound() and upper_bound()
          "they allow the direct iteration on subsets 
           based on their order."
          which gives us another option to find min. preferable */
  
        // return *(points.lower_bound(0));
        return *(points.begin());
    };
  
    void printCards()
    {
        cout << "You Cards : " << endl;
        for (auto it = bjcs.begin(); it != bjcs.end(); ++it) {
            cout << (*it)->val() << endl;
        }
    }
  
public:
    player(int i, int j)
        : id(i), bet(j)
    {
        bjcs.push_back(new BlackJackCard(rand() % 13 + 1, SUIT::SPADE));
        bjcs.push_back(new BlackJackCard(rand() % 13 + 1, SUIT::SPADE));
        addPoint(points, bjcs[0]);
        addPoint(points, bjcs[1]);
    };
  
    void getAnotherCard()
    {
        for (set<int>::iterator it = points.begin(); it != points.end(); ++it) {
           
            /* predefined strategy for the player    */
            if (*it <= 21 && 21 - *it <= 4) {
                printCards();
                getPoints();
                cout << "Stand" << endl;
                exit(1);
            }
        }
        bjcs.push_back(new BlackJackCard(rand() % 13 + 1, SUIT::SPADE));
        addPoint(points, bjcs.back());
        if (getMinPoints() > 21) {
            printCards();
            getPoints();
            cout << "Busted" << endl;
            exit(2);
        }
    };
  
    virtual ~player()
    {
        for (auto it = bjcs.begin(); it != bjcs.end(); ++it) {
            delete *it;
        }
    };
};
// Driver code
int main()
{
    srand(time(NULL));
    player p(1, 1000);
    p.getAnotherCard();
    p.getAnotherCard();
    p.getAnotherCard();
  
    return 0;
}

Producción:

You Cards : 
10
10
You All Possible Points : 
20
Stand

Para implementar Blackjack.

Nota: Ahora, digamos que estamos construyendo un juego de blackjack, entonces necesitamos saber el valor de las cartas. Las figuras son 10 y un as es 11 (la mayoría de las veces, pero ese es el trabajo de la clase Mano, no de la clase siguiente).

Al comienzo de un juego de blackjack, los jugadores y el crupier reciben dos cartas cada uno. Las cartas de los jugadores normalmente se reparten boca arriba, mientras que el crupier tiene una boca abajo (llamada carta oculta) y otra boca arriba.

La mejor mano de blackjack posible es un reparto inicial de un as con cualquier carta de diez puntos. Esto se llama «blackjack», o un 21 natural, y el jugador que lo tiene gana automáticamente a menos que el crupier también tenga un blackjack. Si un jugador y el crupier tienen cada uno un blackjack, el resultado es un empate para ese jugador. Si el crupier tiene un blackjack, todos los jugadores que no tengan un blackjack pierden.

Blackjack

Lógica principal del Blackjack en Java

public class BlackJackHand extends Hand<BlackJackCard> {
  
    /* There are multiple possible scores for a blackjack 
   hand, since aces have 3 * multiple values. Return 
   the highest possible score that's under 21, or the
   4 * lowest score that's over. */
  
    public int score()
    {
        Arraylist<Integer> scores = possibleScores();
        int maxUnder = Integer.MIN_VALUE;
        int minOver = Integer.MAX_VALUE;
        for (int score : scores) {
            if (score > 21 & amp; &score < minOver) {
                minOver = score;
            } else if (score <= 21 & amp; &score > maxUnder) {
                maxUnder = score;
            }
        }
        return maxUnder Integer.MIN_VALUE ? minOver maxUnder;
    }
  
    /* return a list of all possible scores this hand could have 
     (evaluating each * ace as both 1 and 11 */
    private Arraylist<Integer> possibleScores() { ... }
  
    public boolean busted() { return score() > 21; }
    public boolean is21() { return score() == 21; }
    public boolean isBlackJack() { ... }
}
  
public class BlackJackCard extends Card {
    public BlackJackCard(int c, Suit s) { super(c, s); }
    public int value()
    {
        if (isAce())
            return 1;
        else if (faceValue >= 11 & amp; &faceValue <= 13)
            return 10;
        else
            return faceValue;
    }
  
    public int minValue()
    {
        if (isAce())
            return 1;
        else
            return value();
    }
  
    public int maxValue()
    {
        if (isAce())
            return 11;
        else
            return value();
    }
  
    public boolean isAce()
    {
        return faceValue == 1;
    }
  
    public boolean isFaceCard()
    {
        return faceValue >= 11 & amp;
        &faceValue <= 13;
    }
}
  
/* This is just one way of handling aces. We could, alternatively, create a class
of type Ace that extends BlackJackCard. */

Referencias:
https://www.careercup.com/question?id=2983
http://stackoverflow.com/questions/37363008/a-singleton-class-to-design-a-generic-deck-of-card

Este artículo es una contribución del Sr. Somesh Awasthi . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo usando contribuya.geeksforgeeks.org o envíe su artículo por correo a contribuya@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *