Создание нескольких колод карт Java

Изменить: я получаю сообщение об ошибке при попытке добавить карту в мои оригинальные Deck и dealDecks.

Я думаю, что я понял, как создать одну колоду карт [показано в методе Decks()], но моя проблема в том, что мне нужно создать несколько колод карт [n количество колод = n*52 количество карт], Я не могу понять, как использовать n, чтобы сделать несколько карт одной и той же карты. После создания нескольких колод я думаю, что смогу разобраться в shuffle() и reset(), но получение нескольких колод сейчас вызывает у меня проблемы.

Примечание: я думал о создании массива из n колод, но я даже не знаю, как это начать.

Класс карты

/** class Card : for creating playing card objects
 *  it is an immutable class.
 *  Rank - valid values are 1 to 13
 *  Suit - valid values are 0 to 3
 *  Do not modify this class!
 */
class Card {

/* constant suits and ranks */
static final String[] Suit = {"Clubs", "Diamonds", "Hearts", "Spades" };
static final String[] Rank = {"","A","2","3","4","5","6","7","8","9","10","J","Q","K"};

/* Data field of a card: rank and suit */
private int cardRank;  /* values: 1-13 (see Rank[] above) */
private int cardSuit;  /* values: 0-3  (see Suit[] above) */

/* Constructor to create a card */
/* throw PlayingCardException if rank or suit is invalid */
public Card(int rank, int suit) throws PlayingCardException { 
if ((rank < 1) || (rank > 13))
    throw new PlayingCardException("Invalid rank:"+rank);
else
        cardRank = rank;
if ((suit < 0) || (suit > 3))
    throw new PlayingCardException("Invalid suit:"+suit);
else
        cardSuit = suit;
}

/* Accessor and toString */
/* You may impelemnt equals(), but it will not be used */
public int getRank() { return cardRank; }
public int getSuit() { return cardSuit; }
public String toString() { return Rank[cardRank] + " " + Suit[cardSuit]; }


/* Few quick tests here */
public static void main(String args[])
{
try 
        {
        Card c1 = new Card(1,3);    // A Spades
        System.out.println(c1);
        c1 = new Card(10,0);    // 10 Clubs
        System.out.println(c1);
        //c1 = new Card(10,5);        // generate exception here
    }
catch (PlayingCardException e)
    {
        System.out.println("PlayingCardException: "+e.getMessage());
    }
    }
}

Класс колод

/** class Decks represents : n decks of playing cards
 *  Use class Card to construct n * 52 playing cards!
 *
 *  Do not add new data fields!
 *  Do not modify any methods
 *  You may add private methods 
 */

class Decks {

/* this is used to keep track of original n*52 cards */
private List<Card> originalDecks;   

/* this starts with n*52 cards deck from original deck   */
/* it is used to keep track of remaining cards to deal */
/* see reset(): it resets dealDecks to a full deck      */
private List<Card> dealDecks;

/* number of decks in this object */
private int numberDecks;


/**
 * Constructor: Creates default one deck of 52 playing cards in originalDecks and
 *          copy them to dealDecks.
 *              initialize numberDecks=n
 * Note: You need to catch PlayingCardException from Card constructor
 *       Use ArrayList for both originalDecks & dealDecks
 * @throws PlayingCardException 
 */
public Decks() throws PlayingCardException
{
    // implement this method!
    int i, j;
    for (i=0;i<4;i++) 
    {
        for(j=1;j<14;j++) 
        {
            Card orcard = new Card(i,j);
            originalDecks.add(orcard);
            dealDecks.add(orcard);
        }
    }

}


/**
 * Constructor: Creates n decks (52 cards each deck) of playing cards in
 *              originalDecks and copy them to dealDecks.
 *              initialize numberDecks=n
 * Note: You need to catch PlayingCardException from Card constructor
 *       Use ArrayList for both originalDecks & dealDecks
 * @throws PlayingCardException 
 */
public Decks(int n) throws PlayingCardException
{
    // implement this method!
    int i, j;
    for (i=0;i<4;i++) 
    {
        for(j=1;j<14;j++) 
        {
            Card orcard = new Card(i,j);
            originalDecks.add(orcard);
            dealDecks.add(orcard);
        }
    }
}

4 ответа

Решение

Вы должны иметь возможность просто циклически повторять этап создания колод карт. Добавьте еще один цикл через n перед или в цикле for.

public Decks(int n) throws PlayingCardException
{
    // implement this method!
    int i, j;
    for (i=0;i<4;i++) 
    {
        for(j=1;j<14;j++) 
        {
            for(k=0;k<n;k++){
                Card orcard = new Card(i,j);
                originalDecks.add(orcard);
                dealDecks.add(orcard);
             }
        }
    }
}

ИЛИ ЖЕ

public Decks(int n) throws PlayingCardException
{
    // implement this method!
    int i, j;
    for(int k=0;k<n;k++){
        for (i=0;i<4;i++) 
        {
            for(j=1;j<14;j++) 
            {
                Card orcard = new Card(i,j);
                originalDecks.add(orcard);
                dealDecks.add(orcard);
            }
        }
    }
}

Вы на правильном пути, но вам будет намного легче держать все как можно более объектно-ориентированным.

Каждая игральная карта будет иметь Suit а также Rankи они представляют собой диапазон предопределенных значений. Имеет смысл сделать так, чтобы каждое перечисление имело следующие значения:

public enum PlayingCardSuit
{
    None(0),
    Spades(1),
    Diamonds(2),
    Hearts(3),
    Clubs(4);

    private int suit;

    private PlayingCardSuit(int suit)
    {
        this.suit = suit;
    }
}

public enum PlayingCardRank
{
    None(0),
    Ace(1),
    Two(2),
    Three(3),
    Four(4),
    Five(5),
    Size(6),
    Seven(7),
    Eight(8),
    Nine(9),
    Ten(10),
    Jack(11),
    Queen(12),
    King(13);

    private int rank;

    private PlayingCardRank(int rank)
    {
        this.rank = rank;
    }
}

Теперь вы можете иметь Card класс, который представляет Suit а также Rank все вместе. Я также использую UUID назначить каждой карте случайное уникальное значение идентификатора. Это значительно упрощает их перемешивание путем сортировки UUID вместо того, чтобы делать некоторые сложные заказы.

Вот PlayingCard учебный класс:

import java.util.*;

public final class PlayingCard
{
    private UUID id;
    private PlayingCardSuit suit;
    private PlayingCardRank rank;

    public PlayingCard(PlayingCardSuit suit, PlayingCardRank rank)
    {
        this.id = UUID.randomUUID();
        this.suit = suit;
        this.rank = rank;
    }

    public UUID id()
    {
        return this.id;
    }

    public void setId(UUID id)
    {
         this.id = id;
    }

    public PlayingCardSuit suit()
    {
        return this.suit;
    }

    public PlayingCardRank rank()
    {
        return this.rank;
    }

    public String toString()
    {
        return String.format("%s of %s", this.rank, this.suit);
    }
}

Сейчас Deck это просто модная обертка вокруг коллекции Cardс такими методами, как shuffle() а также drawCard(), Это собственный класс, а не массив - вы получаете возможность инкапсулировать все управление изнутри, и вам не нужно беспокоиться о том, "какие карты остались". Он делает все это, используя Stack коллекция.

import java.util.*;

public final class PlayingCardDeck
{
    private Stack<PlayingCard> deck;

    public PlayingCardDeck()
    {
        initializeDeck();
        shuffle();
    }

    private void initializeDeck()
    {
        deck = new Stack<PlayingCard>();

        for(final PlayingCardSuit suit : EnumSet.allOf(PlayingCardSuit.class))
        {
            // Skip the 'None' suit.
            if(suit == PlayingCardSuit.None) continue;

            for(final PlayingCardRank rank : EnumSet.allOf(PlayingCardRank.class))
            {
                // Skip the 'None' rank card.
                if(rank == PlayingCardRank.None) continue;

                PlayingCard card = new PlayingCard(suit, rank);
                deck.push(card);
            }
        }
    }

    public int size()
    {
        return deck.size();    
    }

    public void shuffle()
    {
        // Generate new UUIDs to randomize.
        for(final PlayingCard card : deck)
            card.setId(UUID.randomUUID());

        // Sort the deck based on the card UUID for randomization.
        Collections.sort(deck, new Comparator<PlayingCard>()
        {
            public int compare(PlayingCard a, PlayingCard b)
            {
                UUID aID = a.id();
                UUID bID = b.id();
                return aID.compareTo(bID); 
            }  
        });
    }

    public PlayingCard drawCard()
    {
        return deck.pop();
    }
}

Он будет генерировать все 52 карты каждой масти и ранга при создании. Это также перетасует их (и может быть перетасовано позже). Когда вы берете карту через drawCard(), он удалит карту из верхней части колоды.

Это может показаться излишним, но это действительно организованный подход, который сделает вашу жизнь намного проще, когда в игру вступит несколько колод.

Вот небольшой класс драйвера, который я сделал для тестирования:

public static void main(String[] args) 
{
    Untitled program = new Untitled();
    program.run();  
}

public void run()
{
    PlayingCardDeck deck = new PlayingCardDeck();

    System.out.println(String.format("Deck has %d cards in it.", deck.size()));

    int i = 0;
    while(deck.size() > 0)
    {
        PlayingCard card = deck.drawCard();
        System.out.println(String.format("[Card %2d]: Drew the %s card.", (++i), card.toString()));
    }

    System.out.println("Deck is empty.");
}

И вывод (рандомизированный):

Deck has 52 cards in it.
[Card  1]: Drew the Queen of Diamonds card.
[Card  2]: Drew the Eight of Clubs card.
[Card  3]: Drew the King of Clubs card.
[Card  4]: Drew the Queen of Hearts card.
[Card  5]: Drew the Four of Clubs card.
[Card  6]: Drew the Three of Diamonds card.
[Card  7]: Drew the Nine of Diamonds card.
[Card  8]: Drew the Ace of Diamonds card.
[Card  9]: Drew the Seven of Spades card.
[Card 10]: Drew the Two of Hearts card.
[Card 11]: Drew the Nine of Hearts card.
[Card 12]: Drew the Size of Clubs card.
[Card 13]: Drew the Jack of Diamonds card.
[Card 14]: Drew the Size of Hearts card.
[Card 15]: Drew the Three of Clubs card.
[Card 16]: Drew the Three of Spades card.
[Card 17]: Drew the Ten of Spades card.
[Card 18]: Drew the Jack of Hearts card.
[Card 19]: Drew the Five of Clubs card.
[Card 20]: Drew the Seven of Clubs card.
[Card 21]: Drew the Size of Diamonds card.
[Card 22]: Drew the Ten of Hearts card.
[Card 23]: Drew the Three of Hearts card.
[Card 24]: Drew the Ace of Spades card.
[Card 25]: Drew the Four of Hearts card.
[Card 26]: Drew the Eight of Diamonds card.
[Card 27]: Drew the Ace of Clubs card.
[Card 28]: Drew the Two of Clubs card.
[Card 29]: Drew the Nine of Spades card.
[Card 30]: Drew the Jack of Spades card.
[Card 31]: Drew the Ace of Hearts card.
[Card 32]: Drew the Seven of Hearts card.
[Card 33]: Drew the Five of Hearts card.
[Card 34]: Drew the Eight of Spades card.
[Card 35]: Drew the King of Hearts card.
[Card 36]: Drew the Jack of Clubs card.
[Card 37]: Drew the Size of Spades card.
[Card 38]: Drew the Five of Spades card.
[Card 39]: Drew the Five of Diamonds card.
[Card 40]: Drew the King of Diamonds card.
[Card 41]: Drew the Ten of Clubs card.
[Card 42]: Drew the Queen of Spades card.
[Card 43]: Drew the King of Spades card.
[Card 44]: Drew the Seven of Diamonds card.
[Card 45]: Drew the Four of Spades card.
[Card 46]: Drew the Queen of Clubs card.
[Card 47]: Drew the Ten of Diamonds card.
[Card 48]: Drew the Eight of Hearts card.
[Card 49]: Drew the Four of Diamonds card.
[Card 50]: Drew the Two of Diamonds card.
[Card 51]: Drew the Nine of Clubs card.
[Card 52]: Drew the Two of Spades card.
Deck is empty.

Это моя реализация:

public class CardsDeck {
    private ArrayList<Card> mCards;
    private ArrayList<Card> mPulledCards;
    private Random mRandom;

public static enum Suit {
    SPADES,
    HEARTS,
    DIAMONDS,
    CLUBS;
}

public static enum Rank {
    TWO,
    THREE,
    FOUR,
    FIVE,
    SIX,
    SEVEN,
    EIGHT,
    NINE,
    TEN,
    JACK,
    QUEEN,
    KING,
    ACE;
}

public CardsDeck() {
    mRandom = new Random();
    mPulledCards = new ArrayList<Card>();
    mCards = new ArrayList<Card>(Suit.values().length * Rank.values().length);
    reset();
}

public void reset() {
    mPulledCards.clear();
    mCards.clear();
    /* Creating all possible cards... */
    for (Suit s : Suit.values()) {
        for (Rank r : Rank.values()) {
            Card c = new Card(s, r);
            mCards.add(c);
        }
    }
}


public static class Card {

    private Suit mSuit;
    private Rank mRank;

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

    public Suit getSuit() {
        return mSuit;
    }

    public Rank getRank() {
        return mRank;
    }

    public int getValue() {
        return mRank.ordinal() + 2;
    }

    @Override
    public boolean equals(Object o) {
        return (o != null && o instanceof Card && ((Card) o).mRank == mRank && ((Card) o).mSuit == mSuit);
    }


}

/**
 * get a random card, removing it from the pack
 * @return
 */
public Card pullRandom() {
    if (mCards.isEmpty())
        return null;

    Card res = mCards.remove(randInt(0, mCards.size() - 1));
    if (res != null)
        mPulledCards.add(res);
    return res;
}

/**
 * Get a random cards, leaves it inside the pack 
 * @return
 */
public Card getRandom() {
    if (mCards.isEmpty())
        return null;

    Card res = mCards.get(randInt(0, mCards.size() - 1));
    return res;
}

/**
 * Returns a pseudo-random number between min and max, inclusive.
 * The difference between min and max can be at most
 * <code>Integer.MAX_VALUE - 1</code>.
 *
 * @param min Minimum value
 * @param max Maximum value.  Must be greater than min.
 * @return Integer between min and max, inclusive.
 * @see java.util.Random#nextInt(int)
 */
public int randInt(int min, int max) {
    // nextInt is normally exclusive of the top value,
    // so add 1 to make it inclusive
    int randomNum = mRandom.nextInt((max - min) + 1) + min;
    return randomNum;
}


public boolean isEmpty(){
    return mCards.isEmpty();
}
}

Если вы просто хотите колоды карт, вы знаете, что каждая колода имеет 52 карты. Так почему бы не создать массив карт, кратный 52, внутри класса Deck?

public class Deck {
    private Card[] cards;
    private int dealIndex; // position of next card to deal

    public Deck(int n) { // n number of decks
        cards = new Card[52*n];
        dealIndex = 0;
        // Initialize cards here by creating instances of cards.
        // Maybe write a function to initialize 1 deck of cards and call this n times with appropriate index to cards array.
    }
}

Другая вещь, которую стоит рассмотреть, - это использовать перечисление внутри вашей классовой карты для представления КОСТЮМА и ранга.

Наконец, реализуйте Comparable, чтобы иметь возможность сравнивать карты. Возможно, вы захотите создать класс Hand, а также реализовать Comparable, чтобы иметь возможность сравнивать покерные комбинации.

Другие вопросы по тегам