Создание нескольких колод карт 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, чтобы иметь возможность сравнивать покерные комбинации.