Как мне отсортировать 13 случайных игральных карт по порядку (последовательности) в Java?

Я хочу заказать 13 игральных карт с порядком треф, бубен, червей и пик, последовательность 2,3,4,5,6,7,8,9,10,J,Q,K,A. Например, 4C означает «Клуб 4».

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

4H 5H 8C 8D 9H 9D AC 6S 5D 6D KD 10C AD

результат

8C AC 10C 5D 6D 8D 9D AD KD 4H 5H 9H 6S

Я ожидал результата

8C 10C AC 5D 6D 8D 9D KD AD 4H 5H 9H 6S

Вот код


import java.util.ArrayList;

public class Test {

    public static void main(String[] args) {
        String[] sTest = {"4H", "5H", "8C", "8D", "9H", "9D", "AC", "6S", "5D", "6D", "KD", "10C", "AD" };
        
        for (int i=0;i<13;i++) {
            System.out.print(sTest[i]+" ");
        }
        System.out.println();
        System.out.println("Sorting");
        ArrayList<String> tmp = sortEnd2Begin(sTest);
        tmp.forEach((String myCard) ->{
            System.out.print(myCard+" ");
        });
        System.out.println();
    }
    
    private static ArrayList<String> sortEnd2Begin(String[] myCards) {
        ArrayList<String> myNewCards = new ArrayList<>();
        myNewCards.add(myCards[0]);
        for (int i=1;i<myCards.length;i++) {
            // loop for unordered myCards
            String card2Sort = myCards[i];
            for (int j=0;j<myNewCards.size();j++) {
                // loop for ordered myNewCards
                // find until card2Sort equal or bigger then existing list
                String cardIterate = myNewCards.get(j);
                int iterMax = card2Sort.length();
                if (card2Sort.length() > cardIterate.length()) {
                    iterMax = cardIterate.length();
                }
                int posCard = beforeOrAfter(card2Sort, cardIterate, 0, iterMax);
                if (posCard==0 || posCard<0) {
                    myNewCards.add(j, card2Sort);
                    break;
                } else {
                    // TODO 
                    //System.out.println(j); // debug
                    if (j+1==myNewCards.size()) {
                        // end of list
                        myNewCards.add(card2Sort);
                        break;
                    }
                }
            }

        }
        return myNewCards;
    }
    
    // -1 wordA before wordB
    // 0 wordA equal wordB
    // 1 wordA after wordB
    private static int beforeOrAfter(String wordA, String wordB, int iterX, int iterMax) {
        //System.out.println(wordA+" "+wordB+" "+iterX+" "+iterMax);
        int inA = wordA.length()-1-iterX;
        int inB = wordB.length()-1-iterX;
        char cA = wordA.charAt(inA);
        char cB = wordB.charAt(inB);
        int retValue = 0;
        if (iterX+1==iterMax) {
            // we reach max recursive {
            //System.out.println(iterX+" "+iterMax+" "+cA+" "+cB); // debug
            if (cA==cB) {
                //System.out.println("Debug"); // debug
                if (wordA.length()<wordB.length())  {
                    retValue = -1;
                } else if (wordA.length()>wordB.length())  {
                    retValue = 1;
                } else {
                    retValue = 0; // equal letters and length
                }
            } else if (cA<cB) {
                //retValue = -1;  // ori
                if (wordA.length()>wordB.length()) {
                    retValue = 1;
                } else {
                    retValue = -1;
                }
            } else if (cA>cB) {
                retValue = 1; // ori
            }
        } else {
            if (cA<cB) {
                //System.out.println(cA+" < "+cB+" "+(cA < cB)); // debug
                retValue = -1; // ori
            } else if (cA>cB) {
                //System.out.println(cA+" > "+cB+" "+(cA > cB)); // debug
                retValue = 1; // ori

            } else {
                //System.out.println(cA+" = "+cB+" "+(cA == cB)); // debug
                retValue = beforeOrAfter(wordA, wordB, iterX+1, iterMax);
            }
        }
        return retValue;
    }
}

Отредактировано 20240708

Функция sortEnd2Begin используется для сортировки массива строк и возврата ArrayList в виде отсортированного массива. функция sortEnd2Begin будет перебирать массив myCards и помещать его в новый список массивов в правильном порядке.

чтобы получить правильный порядок вставки или добавления списка массивов, я использую функцию beforeOrAfter, чтобы сравнить, что ниже, равно или выше. если он меньше или равен, он будет вставлен в начало или середину массива. если достигнут конец списка массивов, значение будет добавлено.

Функция beforeOrAfter будет сравнивать символы с конца слова, чтобы определить слово, равное, более низкое или более высокое, на основе таблицы ASCII. Функция beforeOrAfter будет рекурсивно работать до тех пор, пока не будет достигнута минимальная длина слова, и определит (возвращаемое значение) -1 (меньше), 0 (равно) или 1 (больше).

Функции sortEnd2Begin и beforeOrAfter работают аналогично сортировке имени файла в файловом менеджере, но в обратном порядке.

Обычно для раздачи карт лучше использовать рандомайзер. Затем вы можете выбрать как костюм, так и номинал на основе возвращенного числа из случайного значения в диапазоне [0..51].

OldBoy 06.07.2024 10:40

Мне трудно понять, что вы вообще пытаетесь здесь сделать. Хорошо, sortEnd2Begin это Arrays.sort. beforeOrAfter — это Comparator. Но зачем вам там использовать рекурсию? Не было бы намного проще сначала разделить карту на ранг и масть, а затем действовать только на основе этих значений?

Sören 06.07.2024 11:19

в основном Arrays.sort(sTest, Comparator.comparing(Cards::suit).thenComparing(Cards::value‌​)), где String suit(String card) возвращает масть, а Integer value(String card) возвращает значение карты (например, с помощью помощника Map<String, Integer> values = Map.ofEntries(entry("2", 2), entry("3", 3),..., entry("10", 10), entry("J", 11), entry("Q", 12), entry("K", 13), entry("A", 14)))

user85421 06.07.2024 11:42

несмотря на то, что было бы лучше (IMO), если бы у нас были классы/записи для представления карт, мастей и значений.

user85421 06.07.2024 11:53

Измените свои карты со слабо типизированных (небезопасных и подверженных ошибкам) ​​на строго типизированные, и вы сможете легко повышать рейтинг по ходу дела. Фактически, игральные карты, iirc, являются шаблоном, используемым в руководстве по Java enum.

g00se 06.07.2024 13:10

Это руководство здесь

g00se 06.07.2024 14:41

Я добавил объяснение того, как работают функции. Я использую Collections.shuffle(cards, rand) и Random rand = new Random().

Dedetok 08.07.2024 03:25
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
7
128
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Поскольку последняя буква обозначает масть, вы можете использовать ее для сортировки карт по мастям. Чтобы отсортировать по значениям, создайте список с допустимым порядком и сравните индекс ваших строк без последней буквы. Используйте интерфейс Компаратор, который упрощает цепочку сортировки и делает ваш код более читабельным.

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class Example {

    public static void main(String[] args) {
        List<String> order = List.of("2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A");

        String[] sTest = {"4H", "5H", "8C", "8D", "9H", "9D", "AC", "6S", "5D", "6D", "KD", "10C", "AD" };

        // compare by last char
        Comparator<String> bySuits = Comparator.comparingInt(s -> s.charAt(s.length()-1));

        //compare by the index of substring as they appear in the list
        Comparator<String> byValue = Comparator.comparingInt(s -> order.indexOf(s.substring(0, s.length()-1)));


        System.out.println("Before sorting: " + Arrays.toString(sTest));

        // compare by chaining the two comparators
        Arrays.sort(sTest, bySuits.thenComparing(byValue));

        System.out.println("After sorting: " + Arrays.toString(sTest));
    }
}

Используйте enum, чтобы определить колоду карт:

public final enum Card
{
  TWO_OF_CLUBS( "2C" ),
  THREE_OF_CLUBS( "3C" ),
  …
  ACE_OF_CLUBS( "AC" ),
  TWO_OF_DIAMONDS( "2D" ),
  …
  TWO_OF_HEARTS( "2H" ),
  …
  ACE_OF_SPADES( "AS" );

  private final String m_Code;

  private Card( final String code )
  {
    m_Code = code;
  }

  public static final Card forCode( final String code ) throws IllegalArgumentException
  {
     final var retValue = stream( values() )
       .filter( v -> v.m_Code.equals( code ) )
       .findFirst()
       .orElseThrow( () -> new IllegalArgumentException( Objects.toString( code ) );
      return retValue();
  }
  
  public final String getCode() { return m_Code; }
  
  @Override
  public final String toString() { return getCode(); }
}

Сортировка теперь работает так:

final String[] sTest = {"4H", "5H", "8C", "8D", "9H", "9D", "AC", "6S", "5D", "6D", "KD", "10C", "AD" };
final var result = stream( sTest )
  .map( Card::forCode )
  .sorted()
  .map( Card::getCode )
  .toArray( String []::new );

Порядок сортировки определяется последовательностью, в которой вы определяете значения перечисления в Card.

Забавным расширением может быть добавление кода Unicode в качестве символа к определению enum:

public final enum Card
{
  TWO_OF_CLUBS( "2C", "\u1F0D2" ),
  THREE_OF_CLUBS( "3C", "\u1F0D2" ),
  …
  ACE_OF_CLUBS( "AC", "\uF0D1" ),
  TWO_OF_DIAMONDS( "2D", "\uF0C2" ),
  …
  TWO_OF_HEARTS( "2H", "\uF0B2" ),
  …
  ACE_OF_SPADES( "AS", "\uF0A1" );

  private final String m_Code;
  private final String m_Symbol;

  private Card( final String code )
  {
    m_Code = code;
    m_Symbol = symbol;
  }

  public static final Card forCode( final String code ) throws IllegalArgumentException
  {
     final var retValue = stream( values() )
       .filter( v -> v.m_Code.equals( code ) )
       .findFirst()
       .orElseThrow( () -> new IllegalArgumentException( Objects.toString( code ) );
      return retValue();
  }
  
  public static final Card forSymbol( final String symbol ) throws IllegalArgumentException
  {
     final var retValue = stream( values() )
       .filter( v -> v.m_Symbol.equals( symbol ) )
       .findFirst()
       .orElseThrow( () -> new IllegalArgumentException( Objects.toString( symbol ) );
      return retValue();
  }
  
  public final String getCode() { return m_Code; }
  public final String getSymbol() { return m_Symbol; }
  
  @Override
  public final String toString() { return getCode(); }
}

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

final String[] sTest = {"🂴", "🂵", "🃘", "🃈", "🂹", "🃉", "🃑", "🂦", "🃅", "🃆", "🃎", "🃚", "🃁" };
final var result = stream( sTest )
  .map( Card::forSymbol )
  .sorted()
  .map( Card::getSymbol )
  .toArray( String []::new );

Есть много способов сделать это. По моему мнению, самое простое — просто определить отсортированную колоду карт в виде строки и отсортировать ее по индексу, находящемуся в этой строке.

String[] sTest = {"4H", "5H", "8C", "8D", "9H", "9D", "AC",
                   "6S", "5D", "6D", "KD", "10C", "AD" };

String sortedDeck = """
     2C3C4C5C6C7C8C9C10CJCQCKCAC\
     2D3D4D5D6D7D8D9D10DJDQDKDAD\
     2H3H4H5H6H7H8H9H10HJHQHKHAH\
     2S3S4S5S6S7S8S9S10SJSQSKSAS\
     """;
System.out.println(Arrays.toString(sTest)); // before sorting

Arrays.sort(sTest, Comparator.comparingInt(sortedDeck::indexOf));

System.out.println(Arrays.toString(sTest)); // after sorting

принты

[4H, 5H, 8C, 8D, 9H, 9D, AC, 6S, 5D, 6D, KD, 10C, AD]
[8C, 10C, AC, 5D, 6D, 8D, 9D, KD, AD, 4H, 5H, 9H, 6S]

Вышесказанное предполагает, что какой-то неизвестный элемент не проникнет в вашу колоду. Таким образом, предполагается, что индекс -1 не будет возвращен во время сортировки.

Вот колода, из которой вы получаете случайную комбинацию.

    static String suit[] = {"C", "D", "H", "S"};
    static String sym[] = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
    
    static String card_suit(byte c)
    {
        return suit[c / 13];
    }
    
    static String card_sym(byte c)
    {
        return sym[c % 13];
    }
    
    static void shuffle(byte deck[])
    {
        ArrayList<Byte> list = new ArrayList<Byte>();
        for (int i = 0; i < deck.length; i++) list.add(deck[i]);
        Collections.shuffle(list);
        for (int i = 0; i < deck.length; i++) deck[i] = list.get(i);
    }
    
    static void print(byte hand[])
    {
        for (int i = 0; i < hand.length; i++)
        {
            byte c = hand[i];
            String card = card_sym(c) + card_suit(c);
            System.out.print(card + " ");
        }
        System.out.println();
    }

    public static void main(String[] args)
    {
        byte deck[] = new byte[52];
        for (int i = 0; i < deck.length; i++) deck[i] = (byte)i;
        
        print(deck);
        shuffle(deck);
        print(deck);
        Arrays.sort(deck);
        print(deck);
    }
Ответ принят как подходящий

Наборы C, D, H и S указаны в порядке ASCII.

Значение сюиты 2 – 10, J, Q, K и A – нет. Я переназначаю 10 на A, J на ​​B, Q на C, K на D и A на E, чтобы обеспечить правильный порядок ASCII.

Полный исходный код для перетасовки и раздачи карт https://dedetoknotes.blogspot.com/2024/07/java-17-shuffle-52-playing-cards-and.html

код

...
            //int posCard = beforeOrAfter(card2Sort, cardIterate, 0, iterMax);
            int posCard = beforeOrAfter2(card2Sort, cardIterate);

...
/* -1 wordA before wordB
 * 0 wordA equal wordB
 * 1 wordA after wordB
 * suite order less C D H S higher
 * value suit  less 0 1 2 3 4 5 6 7 8 9 A J K Q
 * map 10 to A
 *      J to B
 *      Q to C
 *      K to D
 *      A to E
 */
private static int beforeOrAfter2(String wordA, String wordB) {
    //System.out.print("word "+wordA+" "+wordB+" "); // debug
    char charA = wordA.charAt(wordA.length()-1);
    char charB = wordB.charAt(wordB.length()-1);
    //System.out.println(wordA+" "+wordB+" End "+charA+" "+charB+" "); // debug
    if (charA<charB) {
        return -1;
    } else if (charA>charB) {
        return 1;
    } else {
        // equal
        charA = wordA.charAt(wordA.length()-2);
        charB = wordB.charAt(wordB.length()-2);
        // mapping charA to correct order
        if (charA=='0') {
            charA='A';
        } else if (charA=='J') {
            charA='B';
        } else if (charA=='Q') {
            charA='C';
        } else if (charA=='K') {
            charA='D';
        } else if (charA=='A') {
            charA='E';
        }
        // mapping charB to correct order
        if (charB=='0') {
            charB='A';
        } else if (charB=='J') {
            charB='B';
        } else if (charB=='Q') {
            charB='C';
        } else if (charB=='K') {
            charB='D';
        } else if (charB=='A') {
            charB='E';
        }
        
        //System.out.println(" First "+charA+" "+charB); // debug
        if (charA<charB) {
            return -1;
        } else if (charA>charB) {
            return 1;
        }
    }
    
    return 0;
}

Ключевое слово — "mapping". Так что пропустите конструкции if/else и используйте одну. Map<Character,Integer> map = Map.of('0', 1, 'J', 2, 'Q', 3, 'A', 4); return map.get(charA).compareTo(map.get(charB)); Обратите внимание, что вы можете определить карту вне метода.

WJS 10.07.2024 15:03

Другие вопросы по теме