1

カードシャッフルを書こうとしていますが、カードをシャッフルしたい方法を知っています。しかし、私はそれを書くための最良のオブジェクト指向の方法を失っています。

かなり一般的な方法は次のとおりです。

  • それぞれに 0 から 2,147,483,647 の間のランダムな数値を割り当てます
  • 重複するキー値がある場合 (ほとんどありません)、デッキを捨てて、最初からやり直してください。
  • カードをセットで収納
  • カードのキー値ごとにセットを並べ替える

私の問題は、これを記述する最善の OOP の方法にあります。Card最初に、スーツの値、数値、およびランダムなキーの値を含む というオブジェクトを思いつきました。Deck次に、 a を拡張したという名前のクラスをHashSet用意し、各カードを に格納してHashSetから、キー値で並べ替えます。私が苦労したのは、Cardそもそも 52 個のオブジェクトを「生成」する最も効率的な方法と、セットの順序付け方法です。インターフェイス「SortedSet」を実装しますか?実装する場合、コンパレータをどのように記述しますか?

OOPの設計慣行に基づいた非常に幅広い質問ですが、これが本当にスムーズでオブジェクトベースのソリューションであることを望みます。

乾杯、

ティム。

編集:

みんな助けてくれてありがとう。私の解決策は次のとおりです。

  • 4 つのスーツと 13 の可能な値を含む 2 つの Enum (CardValues、CardSuits)
  • コンストラクタ引数として CardValue と CardSuit を取る Card クラス。
  • TreeMap を拡張する Deck クラス

新しいデッキが作成されシャッフルされると、CardSuit Enum と作成されたカードをループし、そのループ内で CardValue Enum を調べます。これでカードが作成され、次にランダムなキーを生成して TreeMap に配置します。

キーが繰り返される可能性は常にわずかにあるため、最終的なデッキ サイズが 52 でない場合は、新しい InvalidDeckException をスローします。

提案をありがとう、私はこの解決策にとても満足しています.

4

7 に答える 7

1

カードごとに、を使用してTreeMap、マップに存在しない乱数を生成し、それをカードのキーとしてマップに挿入します。

マップは、生成された乱数の順に並べられます。

http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithmsも参照してください

これはシャッフルの遅延方法であることに注意してください。使用するだけCollections.shuffle()です。

于 2011-09-15T15:42:57.023 に答える
1

私はポーカー分析のものをいくつか書きました。rankとフィールドを含むすべてのカードタイプの列挙型を作成しましたvalue。次に、52枚のカード列挙型の可能性をすべて初期化しました。そうです、私は52の列挙型defを持っていました(そしてすべての可能な2カードのスターティングハンドのための別々の列挙型-時にはブルートフォースが最良のオプションです)

次に、の型を持つDeckクラスを作成しました。 ListEnum<Card>

EnumSetデッキの初期化は、列挙型のを生成し、そのセットをリストに渡すのと同じくらい簡単です。次に、shuffleメソッドをDeckクラスに配置して、デッキのリストを使用させることができます。

これの利点は、アプリに52枚のカードしかないことです。これはFlyWeightパターンのようなものです。

于 2011-09-15T15:41:27.883 に答える
1

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]

参照

于 2011-09-15T15:46:23.213 に答える
1

カードを、スイートと数値を保持するクラスとして定義します。カードには、関連付けられている乱数についての知識があってはなりません。

デッキは、カードのリストを含み、どこかに格納する必要がない可能性のある乱数を使用して、シャッフルメソッドを持つクラスです。

于 2011-09-15T15:47:06.620 に答える
1

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

java.util.Collections util クラスの shuffle メソッドについては、上記のドキュメントを参照してください。

 class Card {

private int number;
// other attributes

}

そして単に使用します:-

Collections.shuffle(listOfCards);
于 2011-09-15T16:14:06.937 に答える
0

最も簡単なのは、カードの種類に値属性を割り当て、それで並べ替えるだけです(フェイスカードJ、Q、K、A-> 11,12,13、14)。スーツを注文するには、任意の注文を選び、各スーツのセットがソートされたカードの「パック」に整理する必要があります。スーツは決して変わらないので、パックには常に各クラブ、ハート、ダイアモンド、スペードのソートされたセットがあります。

カードを生成しますか?各パックは明らかに4つのスーツを定義する必要があります。スーツが与えられた場合、各スーツのフルセットを生成して返すCardFactoryを用意します。ファクトリーは盲目的に2-10とフェイスカードを生成し、ソートされたセットを返します。

于 2011-09-15T15:43:50.173 に答える
0

Card特定のカードに固有ではないクラスデータにアクセスしないでください。特に、デッキ内の順番と乱数はカードの属性ではありません(カードはデッキのどこにあっても同じです)。

カードの属性は、その値と状態(表示/非表示)だけである必要があります。デッキはリストで実装できます。シャッフルはDeckからの単なる方法です。

シャッフルには、いくつかのオプションがあります。

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());
 }
于 2011-09-15T15:52:00.027 に答える