简体   繁体   English

使用自定义排序算法对卡片组进行排序

[英]Sorting deck of Cards using custom sorting algorithms

I am trying to implement different sorting algorithms on a deck of cards. 我试图在一副牌上实现不同的排序算法。 I've implemented a base card class using enums to build the suits and faces. 我已经使用枚举实现了一个基卡类来构建套装和面孔。 My class is based on Dietel's & Dietel's Java Book. 我的班级基于Dietel和Dietel的Java Book。 However, I am struggling in passing the deck of cards into the sorting algorithms I implemented as I am not able to pass in an array which I can sort. 但是,我正在努力将卡片传递到我实现的排序算法中,因为我无法传递一个我可以排序的数组。 I don't know if my approach is correct, I've read many of the posts on stackexchange where some recommend using Comparable ( Implementing a Deck of Cards in Java ) which I can't see working with my sorting algorithms. 我不知道我的方法是否正确,我已经阅读了stackexchange上的许多帖子,其中一些人建议使用Comparable( 在Java中实现一个卡片组 ),我看不到使用我的排序算法。 See ( How to Sort the Cards. (Is my code wrong?) ) and ( Implementing a Deck of Cards in Java ) and ( Java Sorting object in ArrayList ). 请参阅( 如何对卡片进行排序。(我的代码是否错误?) )和( 在Java中实现卡片组 )和( ArrayList中的Java排序对象 )。 By having the DeckOfCards return a sequence of numbers eg 1.1, 1.2, 1.3, I think I have a sequence which can be sorted. 通过让DeckOfCards返回一系列数字,例如1.1,1.2,1.3,我想我有一个可以排序的序列。 I also read about ordinals but all the comments on those seemed to oppose the approach. 我也读过关于序数的文章,但对这些文章的所有评论似乎都反对这种方法。 Appreciate any help on this attempt. 感谢您对此尝试的任何帮助。 Kindly note, that I've implemented merge sort and selection sort in the same way and its the same problem - I am clearly missing something here! 请注意,我已经以相同的方式实现了合并排序和选择排序以及同样的问题 - 我在这里显然遗漏了一些东西!

Below is my code: 以下是我的代码:

//Card class //卡类

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();    
 }
 }

//Insertion Sort //插入排序

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);
        }
    }
}

The issue is that listToSort[k] < listToSort[k-1] is attempting to compare two DeckOfCards objects using the < operator, which is not allowed in Java - See: Compare two objects with or operators in Java . 问题是listToSort[k] < listToSort[k-1]正在尝试使用<运算符比较两个DeckOfCards对象,这在Java中是不允许的 - 请参阅: 将两个对象与Java中的运算符进行比较


As that post points out, you should instead be using a Comparator for the Card objects. 正如该帖子指出的那样,你应该使用Comparator作为Card对象。

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

In your DeckOfCards class, I'd also recommend adding a method such as: 在你的DeckOfCards类中,我还建议添加一个方法,例如:

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

which returns a List of the cards in the deck. 它返回卡片组中的卡片列表。 Then, in your insertionSort method, instead of listToSort[k] , you would have listToSort.getCards().get(k) . 然后,在你insertionSort方法,而不是listToSort[k]你就必须listToSort.getCards().get(k) Also, instead of using < you can use a new instance of your CardComparator to determine whether or not to swap the cards. 此外,不是使用<您可以使用CardComparator的新实例来确定是否交换卡。

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;
            }
        }
    }
} 

listToSort is an array of DeckOfCards . listToSort是阵列DeckOfCards On the line indicated with //Code breaks here you're trying to compare two DeckOfCards objects, which you just can't do in java (Operator overloading in other languages would allow you do do this). //Code breaks here所示的行上,您试图比较两个DeckOfCards对象,这些对象在java中是无法做到的(其他语言中的运算符重载将允许您执行此操作)。

How about you write a method, such as .getSortValue() to give you a value to sort it by. 你怎么写一个方法,比如.getSortValue()给你一个值来排序。 Alternatively you could write something to compare the values within the card like: 或者你可以写一些东西比较卡内的值,如:

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

...which is a bit long, but I would assume does what you want. ...这有点长,但我会假设做你想要的。

Note the *13 means that each combination of suit and face is unique 注意*13表示西装和面部的每个组合都是独一无二的

TLDR: If you want to sort it in any other order, you'll have to come up with a value from each card that you can compare properly TLDR:如果您想以任何其他顺序对其进行排序,您必须从每张卡中提取一个值,以便您可以正确比较

The proper approach would be to split the whole deck into suits and then sort each suite individually. 正确的方法是将整个套牌拆分成套装,然后单独对每个套件进行分类。 Your version of insertion sort is not working because the sorting is done using the face values ie aces, 2,3,4 ... And I wouldn't count this as sorting a deck . 您的插入排序版本无法正常工作,因为排序是使用面值进行的,即aces,2,3,4 ......我不会将其视为排序。

private HashMap<Suite,ArrayList<Cards>> deck ;

//scan through the whole deck

for(int i = 0;i < 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)) ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM