Разработка программ на Java - Card Shuffler - PullRequest
1 голос
/ 15 сентября 2011

Я пытаюсь написать shuffler для карт , и я знаю способ, которым я хочу перетасовать карты.Однако я не могу найти лучший объектно-ориентированный способ его написания.

Этот довольно распространенный метод выглядит следующим образом:

  • Назначьте каждому aслучайное числовое значение, от 0 до 2 147 483 647
  • Если имеется дублированное значение ключа (очень маловероятно), выбросьте колоду и начните снова.
  • Храните карты в наборе
  • Порядок установки значения ключа каждой карточки

Моя проблема заключается в лучшем способе ООП написать это.Сначала я придумал объект с именем Card, содержащий значение масти, числовое значение и значение случайного ключа.Тогда у меня был бы класс с именем Deck, который расширил бы HashSet, и я бы сохранил каждую карту в HashSet, а затем отсортировал ее по значению ключа.В чем я боролся, так это в том, какой самый эффективный способ «сгенерировать» 52 Card объектов в первую очередь и как упорядочить набор.Буду ли я реализовывать интерфейс «SortedSet», если да, как мне написать компараторы?

Довольно широкий вопрос, в большей степени основанный на методах проектирования ООП, но я бы хотел, чтобы это было действительногладкое и решение на основе объектов .

Приветствия,

Тим.

РЕДАКТИРОВАТЬ:

Спасибо за помощь всем.Мое решение было следующим:

  • 2 Перечисления (CardValues, CardSuits), содержащие 4 масти и 13 возможных значений
  • Класс Card, который принимает в качестве аргументов конструктора CardValue и CardSuit.
  • Класс колоды, который расширяет TreeMap

Когда создается и перетасовывается новая колода, я перебираю CardSuit Enum и создаю карты, затем внутри этого цикла я прохожуCardValue Enum.Это создает карты, затем я генерирую случайный ключ и помещаю их в TreeMap.

Поскольку всегда существует небольшая вероятность повторения ключа, если конечный размер колоды не равен 52, я выбрасываю новое исключение InvalidDeckException.

Спасибо за предложения, я намного счастливее с этим решением.

Ответы [ 7 ]

1 голос
/ 15 сентября 2011

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

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

1 голос
/ 15 сентября 2011

http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#shuffle(java.util.List)

См. Выше документ о методе перемешивания в java.util. Класс утилит.1009 *

Collections.shuffle(listOfCards);
1 голос
/ 15 сентября 2011

Card.java :

import java.util.*;

public class Card {
    public enum Rank { DEUCE, THREE, FOUR, FIVE, SIX,
        SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE }

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

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

    public Rank rank() { return rank; }
    public Suit suit() { return suit; }
    public String toString() { return rank + " of " + suit; }

    private static final List<Card> protoDeck = new ArrayList<Card>();

    // Initialize prototype deck
    static {
        for (Suit suit : Suit.values())
            for (Rank rank : Rank.values())
                protoDeck.add(new Card(rank, suit));
    }

    public static ArrayList<Card> newDeck() {
        return new ArrayList<Card>(protoDeck); // Return copy of prototype deck
    }
}

Deal.java :

import java.util.*;

public class Deal {
    public static void main(String args[]) {
        int numHands = Integer.parseInt(args[0]);
        int cardsPerHand = Integer.parseInt(args[1]);
        List<Card> deck  = Card.newDeck();
        Collections.shuffle(deck);
        for (int i=0; i < numHands; i++)
            System.out.println(deal(deck, cardsPerHand));
    }

    public static ArrayList<Card> deal(List<Card> deck, int n) {
         int deckSize = deck.size();
         List<Card> handView = deck.subList(deckSize-n, deckSize);
         ArrayList<Card> hand = new ArrayList<Card>(handView);
         handView.clear();
         return hand;
     }
}

Выход:

 $ java Deal 4 5
    [FOUR of HEARTS, NINE of DIAMONDS, QUEEN of SPADES, ACE of SPADES, NINE of SPADES]
    [DEUCE of HEARTS, EIGHT of SPADES, JACK of DIAMONDS, TEN of CLUBS, SEVEN of SPADES]
    [FIVE of HEARTS, FOUR of DIAMONDS, SIX of DIAMONDS, NINE of CLUBS, JACK of CLUBS]
    [SEVEN of HEARTS, SIX of CLUBS, DEUCE of DIAMONDS, THREE of SPADES, EIGHT of CLUBS]

Ссылка :

1 голос
/ 15 сентября 2011

Используйте TreeMap, для каждой карты создайте случайное число, которого нет на карте, и вставьте его в карту в качестве ключа для карты, готово.

Карта теперьупорядочено по случайным числам.

См. также http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms

Обратите внимание, что это запаздывающий способ перемешать, просто используйте Collections.shuffle().

1 голос
/ 15 сентября 2011

Я написал кое-что для анализа покера.Я создал Enum для всех типов карт с полями rank и value.Затем я инициализировал все 52 возможности перечисления карт.Так что да, у меня было 52 enum defs (и отдельное enum для всех возможных стартовых рук из двух карт - иногда грубая сила - лучший вариант)

Затем я создал класс Deck, который имел List из Enum<Card> типов.

Инициализация колоды так же проста, как генерация Enum EnumSet и передача этого набора в List.Затем вы можете поместить свой метод shuffle в класс Deck и использовать его в списке для колоды.

Преимущество этого заключается в том, что в вашем приложении только 52 карты - это похоже наШаблон FlyWeight.

0 голосов
/ 15 сентября 2011

Вы не должны попадать в данные класса Card, которые не относятся к конкретной карте. В частности, порядок внутри колоды и случайное число не являются атрибутом карты (карта одна и та же, независимо от того, где она находится в колоде).

Атрибуты карты должны быть только ее значением и состоянием (показано / скрыто). Колода может быть реализована с помощью списка. Тасование будет просто методом из колоды.

Для перетасовки есть несколько вариантов:

1) вы сами перечисляете случайные числа и упорядочиваете их; каждое изменение в списке случайных чисел воспроизводится в списке карт. Проблема в том, что вы не можете использовать методы сортировки, уже доступные для List ()

2) Вы добавляете промежуточный класс (назовем его ShufCard), который содержит и карту, и случайное число, а также:

a) Колода - это список этих промежуточных объектов.

b) Для перемешивания вы создаете временный список с содержимым колод, перемешиваете, а затем извлекаете карты из временного списка, поддерживающего его порядок. Что-то вроде:

 List<ShufCard> list = new ArrayList<ShufCard>();
 for (Card card : Deck.cards) {
   list.add(new ShufCard(Card, Random.getNumber());
 }

 list.sort();
 Deck.cards.clear();

 for (ShufCard shCard : list) {
   Deck.cards.add(shCard.getCard());
 }
0 голосов
/ 15 сентября 2011

Самое простое - просто присвоить атрибуту значения типы карт и отсортировать по ним (лицевые карты J, Q, K, A-> 11,12,13, 14).При заказе костюмов вам нужно выбрать произвольный порядок и организовать в «колоду» карточек, в которой есть отсортированный набор каждой масти.Так как костюмы никогда не меняются, в пакете всегда есть отсортированный набор из каждого Клуба, Сердца, Алмаза и Пики.

Создание карт?В каждой пачке должно быть 4 масти.Имейте CardFactory, которая генерирует и возвращает полный набор для каждой масти, учитывая Костюм.Фабрика просто слепо сгенерирует карты 2-10 и лицевых карт и вернет отсортированный набор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...