【问题标题】:Shuffling Deck of Cards Using Card object使用卡片对象洗牌
【发布时间】:2019-11-13 19:13:27
【问题描述】:

一直在尝试创建一个名为 CardDeck 的类来洗牌在不同的类中创建的卡片对象(称为 DeckOfCard,抱歉造成混淆,没有很好的命名),但已经没有如何实现这一点的想法了。

这是我想出的,我也包含了原始类 DeckOfCards,欢迎和感谢任何帮助/建议!

//CODE FOR CARD OBJECT//
   public final static int ace = 1, two= 2,three=3, four=4, five=5, six=6, seven =7, eight=8, nine=9, ten=10, jack= 11, queen=12, king=13; 

   public final static int diamonds= 1, clubs= 2, spades= 3, hearts=4; 

   private final static int numberOfFaces = 13;
   private final static int numberOfSuits = 4;

   private int face, suit;
   private String faceValue, suitName;

   //create a random card 
   public DeckOfCards()
   {
       face= (int)(Math.random() * numberOfFaces);
       setFaceValue();

       suit= (int) (Math.random() * numberOfSuits);
       setSuitName();
    }

   //sets the string representation of each face value to its coorspdoing numeric value
    private void setFaceValue()
   {
       switch(face)
       {
           case ace:
            faceValue= "Ace";
            break;
           case two:
            faceValue= "Two";
            break;
           case three:
            faceValue= "Three";
            break;
           case four:
            faceValue= "Four";
            break;
           case five:
            faceValue = "Five";
            break;
           case six:
            faceValue = "Six";
            break;
           case seven:
            faceValue= "Seven";
            break;
           case eight:
            faceValue= "Eight";
            break;
           case nine:
            faceValue= "Nine";
            break;
           case ten:
            faceValue= "Ten";
            break;
           case jack:
            faceValue= "Jack";
            break;
           case queen:
            faceValue= "Queen";
            break;
           case king:
            faceValue= "King";
            break;
       }
   }

      //set the string representation of each suit 
private void setSuitName()
{
    switch(suit)
    {
        case diamonds:
            suitName = "Diamonds";
            break;
        case clubs:
            suitName= "Clubs";
            break;
        case spades:
            suitName = "Spades";
            break;
        case hearts:
            suitName = "Hearts";
            break;
        }
    }

public String getFaceValue()
{
    return faceValue;
}

public String getSuitName()
{
    return suitName;
}

public String toString()
{
    return faceValue+ " of " +suitName;
}
}

这是我当前的代码...虽然不多,但这是迄今为止我所能得到的最接近的:

import java.util.Random;
public class CardDeck
{
   private DeckOfCards[] cards;

   //create new deck of cards
   public CardDeck()
   {
       cards = new DeckOfCards[52];
       int index= 0;


       int[] cardTypes = {DeckOfCards.ace, DeckOfCards.diamonds, DeckOfCards.spades,      DeckOfCards.hearts};

       for(int cardType : cardTypes)
       {
           for(int i = 1; i<=13; i++)
           {
               DeckOfCards card = new DeckOfCards();
               cards[index++]= card;
            }
        }
  }

  //create shuffle method, use loop to generate random suit and random faceValue
    public void shuffle()
    {


        System.out.println("Suffuling cards");

            int loopCount = 53;

            while (loopCount > 0) {

            double index1 = Math.random();

            double index2 = Math.random();

            DeckOfCards temp = cards[index1];

            cards[index1] = cards[index2];

            cards[index2] = temp;

            loopCount--;

}

}

}

【问题讨论】:

标签: java loops shuffle


【解决方案1】:

为军衔和花色定义一个enum 类型。这提供了类型安全性,这样您就不会意外传递花色参数的等级,反之亦然。枚举值还可以作为很好的键用于地图中,以定义不同游戏的评分系统等。另请注意,枚举可以具有属性和方法,因此您可以通过这种方式为值添加用户友好的名称。

然后创建一个有等级和西装的Card 类型。

迭代等级,对于每个等级,迭代套装。为每个等级和花色组合创建一个新的Card,并将其添加到List;这是你的甲板。当你的牌组建成后,你可以shuffle it with a convenience method in Collections.

public final class Card {

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

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

    private final Rank rank;

    private final Suit suit;

    public Card(Rank rank, Suit suit) {
        this.rank = Objects.requireNonNull(rank);
        this.suit = Objects.requireNonNull(suit);
    }

    public Rank getRank() {
        return rank;
    }

    public Suit getSuit() {
        return suit;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof Card)) return false;
        Card that = (Card) obj;
        return (getRank() == that.getRank()) && (getSuit() == that.getSuit());
    }

    @Override
    public int hashCode() {
        return getRank().hashCode() * 31 + getSuit().hashCode();
    }

    @Override
    public String toString() {
        return getRank() + " of " + getSuit();
    }

}

public class Deck {

    private final List<? extends Card> cards;

    public Deck(Collection<? extends Card> cards) {
        this.cards = new ArrayList<>(cards);
    }

    public void shuffle(Random random) {
        if (random == null) random = ThreadLocalRandom.current();
        Collections.shuffle(cards, random);
    }

    public static Deck newStandardDeck() {
        List<Card> cards = new ArrayList<>();
        for (Card.Rank rank : Card.Rank.values()) {
            for (Card.Suit suit : Card.Suit.values()) {
                cards.add(new Card(rank, suit));
            }
        }
        return new Deck(cards);
    }

}

【讨论】:

    【解决方案2】:

    你的问题在这里:

    double index1 = Math.random();
    double index2 = Math.random();
    

    Math.random() 返回一个介于 0 和 1 之间的双浮点数。 试试这个:

     Random r = new Random();
    
     while(loopCount > 0) {
         int index1 = r.nextInt(cards.length);
         int index2 = r.nextInt(cards.length);
    

    【讨论】:

      【解决方案3】:

      因此,您的代码结构存在一些大问题,但我挽救了这一点。 最简单的解决方案是创建一个排序的卡片列表,每个套件和值一个,然后将每张卡片设置为随机索引。这将在“卡片”字段上执行该操作

      // create shuffle method, use loop to generate random suit and random faceValue
          public void shuffle() {
      
              System.out.println("Suffuling cards");
      
              int loopCount = 0;
      
              ArrayList<DeckOfCards> inOrder = new ArrayList<DeckOfCards>();
              for(int i = 0; i < 54; i++)
              {
                  inOrder.add(cards[i]);
              }
      
              DeckOfCards[] shuffled = new DeckOfCards[54];
      
              for(int i = 0; i < 54; i++)
              {
                  //Math.random()*size of inOrder will give you a double between 0 and size of in order. 
                  //Round this down and convert to an int and you have a random index!
                  int randCardIndex = (int) (Math.floor(Math.random()*inOrder.size()));
      
                  //Grab the card and add it to the shuffled deck in the current position
                  shuffled[i] = inOrder.get(randCardIndex);
      
                  //Remove this card so it can no longer be grabbed
                  inOrder.remove(randCardIndex);
              }
      
              cards = shuffled;
      
          }
      

      【讨论】:

        【解决方案4】:

        请将名称更改为 Card 而不是 DeckOfCardsCard 对象的列表成为一副纸牌,因此您不想将对象本身称为纸牌。

        random 函数应遵循与 DeckOfCards 的构造函数类似的方法,其中您的乘数应应用于随机数之上并转换为 int。之后,您的代码应该可以正常工作。卡片大小 52 应存储为全局私有变量。永远不要使用“幻数”而不将它们存储在变量中并调用该变量。 index1 和 index2 都应该如下:

        double index1 = Math.random()*NUM_CARDS

        在您的私有数组下方有以下变量:private final int NUM_CARDS = 52

        否则你走在正确的轨道上,洗牌机制很好。只是随机索引生成得到一个 0 到 1 之间的十进制数。

        当您必须调试时,请使用打印变量技术。在这种情况下,打印出 index1 和 index2 的每个值,并检查这些值是否按预期生成。您还可以尝试一种对初学者不太友好的方法,称为调试模式(蟑螂图标),然后双击行号以设置一个断点,您希望在该断点处暂停执行,您可以查看该点存储在内存中的所有变量代码。

        【讨论】:

          猜你喜欢
          • 2017-04-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多