【问题标题】:Sorting deck of Cards using custom sorting algorithms使用自定义排序算法对纸牌进行排序
【发布时间】:2016-10-28 23:01:28
【问题描述】:

我正在尝试在一副纸牌上实现不同的排序算法。我已经使用枚举实现了一个基卡类来构建西装和面孔。我的课程基于 Dietel 和 Dietel 的 Java Book。但是,我在将一副纸牌传递给我实现的排序算法时遇到了困难,因为我无法传递一个可以排序的数组。我不知道我的方法是否正确,我已经阅读了 stackexchange 上的许多帖子,其中一些建议使用 Comparable (Implementing a Deck of Cards in Java),但我看不到使用我的排序算法。请参阅 (How to Sort the Cards. (Is my code wrong?)) 和 (Implementing a Deck of Cards in Java) 和 (Java Sorting object in ArrayList)。通过让 DeckOfCards 返回一系列数字,例如1.1、1.2、1.3,我想我有一个可以排序的序列。我还阅读了关于序数的文章,但所有关于这些的 cmets 似乎都反对这种方法。感谢对此尝试的任何帮助。请注意,我已经以相同的方式实现了合并排序和选择排序,并且存在相同的问题 - 我显然在这里遗漏了一些东西!

下面是我的代码:

//卡片类

class Card
{    
     //public static enum Face {Ace, Deuce, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King};
     public static enum Face {Ace(1), King(2), Queen(3), Jack(4), Ten(5), Nine(6), Eight(7), Seven(8), Six(9), Five(10), Four(11), Three(12), Deuce(13);
     int rank;
     Face(int r){ rank = r;}
     int getRank() {return rank;}
}
//public static enum Suit {Clubs, Diamonds, Hearts, Spades };
public static enum Suit {Spades(1), Hearts(2), Diamonds(3), Clubs(4);
   int order;
   Suit(int o){ order = o;}
   int getOrder() {return order;}
}

private final Face face; // face of card
private final Suit suit; // suit of card

// two-argument constructor
public Card( Face cardFace, Suit cardSuit ) 
{   
    face = cardFace; // initialize face of card
    suit = cardSuit; // initialize suit of card
}

// return face of the card
public Face getFace() { return face;}

// return suit of Card
public Suit getSuit() { return suit;}

// return String representation of Card
public String toString()
{
   //return String.format( "%s.%s", suit.getOrder(), face.getRank() );
   return String.format( "%s.%s", suit, face );
}
}

 // class DeckOfCards declaration
 public class DeckOfCards 
{
   private List< Card > list; // declare List that will store Cards

   // set up deck of Cards and shuffle
   public DeckOfCards()
  {
     Card[] deck = new Card[ 52 ];
     int count = 0; // number of cards

     // populate deck with Card objects
     for ( Card.Suit suit : Card.Suit.values() )  
     {
         for ( Card.Face face : Card.Face.values() )   
        {
            deck[ count ] = new Card( face.getRank(), suit.getOrder() );
            count++;
        }
     }

     list = Arrays.asList( deck ); // get List
     //Collections.shuffle( list );  // shuffle deck
   }

   // output deck
   public void printCards()
  {
      // display 52 cards in two columns
      for ( int i = 0; i < list.size(); i++ )
      System.out.printf( "%-20s%s", list.get( i ),
          ( ( i + 1 ) % 2 == 0 ) ? "\n" : "" );
  }

  public static void main( String[] args )
 {
     DeckOfCards cards = new DeckOfCards();
     cards.printCards();
    //cards.InsertionSort();    
 }
 }

//插入排序

public static void insertionSort(DeckOfCards[] listToSort) 
{
    for (int i = 0; i < listToSort.length-1; i++) 
    {
        for (int k = i+1; k>0; k--) 
       {
           if(listToSort[k] < listToSort[k-1]) //Code breaks here
           {
                swap(listToSort, k, k-1);
            }
            else 
            {
                break;
            }
            print(listToSort);
        }
    }
}

【问题讨论】:

  • 你可以使用Collections.sort
  • @4castle “我正在尝试实现不同的排序算法”,“我的班级”。似乎使用现有的排序方法不是 OP 在这里寻找的。​​span>

标签: java sorting enums


【解决方案1】:

listToSortDeckOfCards 的数组。在//Code breaks here 指示的行上,您正在尝试比较两个DeckOfCards 对象,而这在java 中是无法做到的(其他语言中的运算符重载将允许您这样做)。

你写一个方法怎么样,比如.getSortValue()给你一个值来排序。或者,您可以编写一些内容来比较卡片中的值,例如:

if(listToSort[k].getSuit().getOrder()*13+listToSort[k].getFace().getOrder() < listToSort[k- 1].getSuit().getOrder()*13+listToSort[k-1].getFace().getOrder())

...这有点长,但我会假设你想要什么。

注意*13 表示西装和脸型的每种组合都是独一无二的

TLDR: 如果您想以任何其他顺序对其进行排序,则必须从每张卡片中得出一个可以正确比较的值

【讨论】:

  • 这不是说我必须继承getSuit() & getFace() 方法吗?并调用 DeckOfCards 类中的另一个构造函数?由于 getSuit 和 getFace 方法是在 Card 类中实现的 - 抱歉,我对 Java 没有太多经验。
  • 不,一点也不。 listToSort[k] 为您提供来自数组 listToSort 的“DeckOfCards”的“第 k 个”实例。这意味着您可以从排序代码所在的任何位置调用它的任何公共方法。构造函数将用于创建new DeckOfCards。我假设DeckOfCards obhect 是为了代表一张卡片,所以也许应该重命名
【解决方案2】:

正确的方法是将整个套牌分成几套,然后分别对每套进行分类。您的插入排序版本不起作用,因为排序是使用面值完成的,即 ace, 2,3,4 ... 而且我不会将其视为对甲板进行排序。

private HashMap&lt;Suite,ArrayList&lt;Cards&gt;&gt; deck ;

//scan through the whole deck

for(int i = 0;i &lt; 52; ++i) {

    `switch(cards[i]) {`

      `case Aces :`
        deck.put(Suite.Aces,cards[i]) ;
        break;
    .....
}

}

//Now sort

sort(deck.get(Suite.Aces)) ;

sort(deck.get(Suite.Diamond)) ;

【讨论】:

  • 感谢您的评论!我将在哪里实现 Hashmap,它会在 deckOfCards 类中吗?
  • @parthibd "您的插入排序版本不起作用,因为排序是使用面值完成的,即 ace、2、3、4 ... 我不会把这算作排序甲板“……这不是整理套牌的重点吗?对套牌进行排序包括对花色和面值进行排序——这两者可以同时完成。
  • @avojak:当然可以。我的方法稍微简单一些。我的方法是只对面值进行排序。首先将套牌分成 4 个不同的套件,然后将这些套件单独分类。不过比你的效率低​​一点。
【解决方案3】:

问题在于listToSort[k] &lt; listToSort[k-1] 正在尝试使用&lt; 运算符比较两个 DeckOfCards 对象,这在 Java 中是不允许的 - 请参阅:Compare two objects with or operators in Java


正如该帖子指出的那样,您应该使用 Comparator 作为 Card 对象。

public class CardComparator implements Comparator<Card> {
    @Override
    public int compare(Card o1, Card o2) {
        // ...
        // Use Card.getFace().getRank() and Card.getSuit().getOrder()
        // ...
    }
}

在您的 DeckOfCards 类中,我还建议添加一个方法,例如:

public List<Card> getCards() { ... }

返回牌组中的牌列表。然后,在您的insertionSort 方法中,您将拥有listToSort.getCards().get(k),而不是listToSort[k]。此外,您可以使用CardComparator 的新实例来确定是否交换卡片,而不是使用&lt;

public static void insertionSort(DeckOfCards cardsToSort) {
    final Comparator cardComparator = new CardComparator();
    for (int i = 0; i < cardsToSort.size() - 1; i++) {
        for (int k = i + 1; k > 0; k--) {
            final Card card1 = cardsToSort.getCards().get(k);
            final Card card2 = cardsToSort.getCards().get(k - 1);
            if(cardComparator.compare(card1, card2) < 0) {
                swap(cardsToSort, k, k-1);
            } else {
                break;
            }
        }
    }
} 

【讨论】:

  • 嗨@avojak,感谢您的回答,这非常有用!我只是不清楚 compare 方法应该做什么——我看到了一些例子,如果你有一个枚举,那么你会返回不同的值,但在我的情况下,如果有两个枚举,它应该返回什么。另一个问题是 compareTo 方法应该做什么,或者返回 0 是否足够?感谢您的帮助!
  • @Cola4ever 抱歉,我添加的第一个链接有点令人困惑,因为它提到了几种方法。如果您查看 Comparator.compare(T o1, T o2) 的 Javadoc,您会看到它说“返回负整数、零或正整数,因为第一个参数小于、等于或大于第二个参数。”所以compare() 中的逻辑应该做到这一点!如果 first 对象是 greater 并且您想按升序排序,那么您将返回一个 负整数。等
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-21
  • 2015-11-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多