Oceń dłoń skata

18

Wprowadzenie

Skat to tradycyjna niemiecka gra karciana dla 3 graczy. Talia składa się z 32 kart: as, król, królowa, walet, 10, 9, 8, 7 we wszystkich 4 kolorach (trefl, pik, kier, karo).

W każdej rundzie jeden gracz gra solo, a pozostali dwaj grają przeciwko niemu. Na początku rundy każdy gracz otrzymuje 10 kart, pozostałe 2 karty nazywane są skat i kładzie się je zakryte na środku. Gracz solo zależy od fazy licytacji. Jest to część gry, z którą będziesz musiał zmierzyć się w tym wyzwaniu, więcej szczegółów na ten temat poniżej.

Gracz, który wygra fazę licytacji, zostaje graczem solo. Podnosi skata, a następnie upuszcza dwie karty (które mogą być takie same, druga drużyna nie wie), wybiera kolor atutowy i rozpoczyna się runda.

Jedna runda składa się z dziesięciu lew. Gracz, który wygrywa lewę, prowadzi następną, dopóki wszystkie karty nie zostaną zagrane. Nie wyjaśnię tutaj zasad, ale powinieneś wiedzieć, że posiadanie wielu kart atutowych jest dobre. Jeśli chcesz poznać zasady, sprawdź artykuł w Wikipedii, który zamieściłem na początku tego postu, ale nie jest potrzebny do tego wyzwania.

Wyzwanie

Chcesz nauczyć swoich dwóch synów, jak grać w skata. Zasady nie są tak trudne, więc szybko się w to angażują. Jedyną rzeczą, która sprawia im trudność, jest licytacja, w szczególności obliczanie wartości gry ich ręki. Więc decydujesz się napisać mały program, który generuje maksymalną wartość gry, jaką mogą licytować, biorąc pod uwagę bieżącą rękę.

Obliczanie wartości gry

Każde rozdanie ma określoną wartość gry. Jest to określane przez liczbę sekwencyjnych waletów, które masz i kolor, który chcesz wybrać jako atut. Zacznijmy od pierwszego czynnika - gniazd!

The Jack Factor

Walety są zawsze kartami atutowymi i biją każdą inną kartę atutową. Kolejność siły między czterema waletami jest następująca:

  1. Jack of Clubs (najwyższy)
  2. Jack of Spades
  3. Jack of Hearts
  4. Jack of Diamonds (najniższy)

W dalszym objaśnieniu odniosę się do nich wraz z przypisanymi im numerami.

Pamiętasz, że z ręki walety masz jakiś czynnik, który jest częścią wartości gry? Świetny! Oto jak to zdobyć:

Ten współczynnik Jacka to liczba najwyższych waletów (patrz kolejność powyżej) w sekwencji plus 1. Więc jeśli masz wszystkie 4 walety, to 4 + 1 = 5. Jeśli masz tylko pierwsze 2 walety, to 2 + 1 = 3)

Ewentualnie, aby nieco skomplikować sprawę, Czynnikiem Jacka może być również liczba najwyższych Jacków w sekwencji, których brakuje , plus 1. Więc jeśli brakuje pierwszego, wynosi 1 + 1 = 2. Jeśli brakuje pierwszego 3, to jest 3 + 1 = 4. Oto kilka przykładów, używając powyższej numeracji:

[1, 4] -> 1 + 1 = 2
[1, 2, 4] -> 2 + 1 = 3
[2, 3, 4] -> 1 + 1 = 2
[1, 2, 3, 4] -> 4 + 1 = 5
[] -> 4 + 1 = 5

To był pierwszy czynnik. Oto jak zdobyć drugi:

Współczynnik koloru atutowego

Ten jest o wiele prostszy. Drugi czynnik zależy od koloru atutowego, który gracz solo wybiera przy użyciu następującego odwzorowania:

Clubs    -> 12
Spades   -> 11
Hearts   -> 10
Diamonds ->  9

To było łatwe, prawda?

Wartość gry

Wartość gry jest wypadkową dwóch czynników. Całkiem łatwe, myślisz? Źle! Podczas gdy Jack-Factor jest stały, współczynnik koloru nie jest. Kolor, który ostatecznie wybierasz jako atut, zależy od liczby atutów i wartości kart innych niż atuty w twojej ręce. Byłoby zbyt skomplikowane wyjaśnienie, jak wygląda dobra ręka, więc użyjesz następującego algorytmu:

Algorytm Which-Trump-do-I-Pick

Nie musisz brać udziału w licytacji. Jeśli uznasz, że twoja ręka jest zbyt zła, aby grać w pojedynkę, możesz po prostu spasować. Twoja ręka musi spełniać następujące kryteria, aby grać:

  • Posiadaj co najmniej 6 kart atutowych (karty wybranego koloru atutowego + liczba waletów). Jeśli jest to możliwe w przypadku więcej niż jednego koloru, wybierz ten, który dałby więcej kart atutowych. Jeśli nadal jest remis, wybierz kolor z najwyższą oceną podaną powyżej.

  • Z kart innych niż atuty masz przynajmniej 1 asa.

Jeśli Twoja ręka nie spełnia obu tych kryteriów, spasujesz. Jeśli tak, wyliczysz obliczoną wartość gry i wybrany kolor atutowy.

Krótka uwaga: Oczywiście jest to bardzo uproszczony algorytm. Osadzanie rozdań wymaga zbyt wiele strategii i doświadczenia, niż moglibyśmy kiedykolwiek podjąć w takim wyzwaniu.

Wejście

Każda karta ma unikalny identyfikator. Pierwsza część to kolor ( C lubs, S pades, H earts, D iamonds), druga część to wartość podana przez to mapowanie:

Ace -> A
King -> K
Queen -> Q
Jack -> J
10 -> 0
9 -> 9
8 -> 8
7 -> 7

Obie części razem tworzą jedną kartę. Na pierwszym miejscu jest wartość, a potem kolor. Możesz wziąć karty w dowolnym formacie, jak chcesz.

Wynik

Jeśli rozdanie jest grywalne, wypisz wartość gry i wybrany kolor atutowy (kolejność nie ma znaczenia). Jeśli nie, wypisz „pass”.

Zasady

  • Jak wspomniano, możesz wziąć dane wejściowe w najwygodniejszym dla siebie formacie. Przykłady patrz poniżej w przypadkach testowych.
  • Dane wejściowe mogą być dostarczane za pomocą argumentów wiersza poleceń, danych wejściowych użytkownika lub argumentów funkcji.
  • Dane wyjściowe można podać jako wartość zwrotną lub po prostu wydrukować na ekranie.
  • Kart na wejściu nie można w żaden sposób zamówić. Twój program musi być w stanie poradzić sobie z dowolnym losowym zamówieniem karty.
  • Wygrywa najniższa liczba bajtów!

Przypadki testowe

Dane wejściowe w przypadkach testowych to lista ciągów 2-znakowych.

1. ["JC", "JS", "JD", "AC", "KC", "9C", "AS", "7H", "QD", "8D"] -> 36 Clubs
2. ["JD", "AS", "0S", "KS", "QS", "9S", "8S", "AD", "8C", "9C"] -> 44 Spades
3. ["JH", "JD", "0S", "KS", "9C", "8C", "QH", "KH", "AD", "9D"] -> pass
4. ["JD", "AS", "KS", "QS", "0S", "9S", "8D", "7D", "0C", "QH"] -> pass

Wyjaśnienie:

  1. Dwa walety z rzędu z treflami. Wartość gry to 3 x 12 = 36
  2. Brak trzech waletów z rzędu z pikami jako atutem. Wartość gry to 4 x 11 = 44
  3. Możliwe są maksymalnie 4 karty atutowe, więc zdasz.
  4. Sześć kart atutowych z pikami, ale bez asa bez atutów, więc spasujesz.

Jeśli niektóre zasady są niejasne, śmiało i komentuj. Dorastałem w tej grze, więc trudno mi ocenić, czy opisałem wszystko wystarczająco szczegółowo.

A teraz ... Szczęśliwego kodowania!

edytuj: Jak wskazano mi w komentarzach (dzięki isaacg), istnieje zasada, która liczy następujące najwyższe atuty po 4 waletach do „współczynnika waluta”, aby mogło wzrosnąć do 11. Aby utrzymać to wyzwanie proste i aby nie mylić ludzi, zaproponowane przeze mnie zasady pozostaną takie, jakie są. Zatem maksymalny współczynnik pozostaje na poziomie 5.

Denker
źródło
6
Witamy w Programowaniu zagadek i Code Golf - doskonałe pierwsze wyzwanie! :)
Klamka
1
Czy liczba prostych jacketów / brakujących jacków powinna obejmować kolejno atuty najwyższego koloru? Tak mówi wikipedia tutaj
isaacg
@isaacg Muszę przyznać, że do tej pory nie wiedziałem o tej zasadzie. Dzięki za zwrócenie na to uwagi. Zrobiłem trochę badań i masz rację. W mojej rodzinie nie bawimy się tą zasadą i nie spotkałem też nikogo, kto by się z nią bawił. Nie ma to tak dużego znaczenia, ponieważ mając taką rękę, przez większość czasu grasz w Grand, który i tak jest liczony inaczej. Aby sprostać temu wyzwaniu, pozostaniemy w zgodzie z zasadami, które zaproponowałem. Zedytuję swój post, aby było jasne dla wszystkich.
Denker,
1
@DenkerAffe, grałem w Skat przez wiele lat w klubie w Niemczech, i wierzcie mi, zasada jest ważna, a są przypadki, w których jest ona niezwykle istotna (i tak, nie jest znana u większości nie poważnych graczy). Zwłaszcza z brakującą stroną - wyobraź sobie, że masz atuty K, D, 9, 8, 7 i trzy A i dwa 10 w innych kolorach. Twój Grand z pewnością umiera, ale możesz zagrać w „ohne 6” (zebrać trochę kontra) i pokonać je, zakładając, że masz pojęcie, jak B siedzi z licytacji. Możesz licytować, dopóki słońce nie pojawi się z tą kartą.
Aganju
@Aganju Już założyłem, że ta zasada nie jest znana większości hobbystów. Dziękuję za potwierdzenie. Nie wątpię, że jest to ważne, ale z mojego doświadczenia wynika, że ​​takie ręce są dość rzadkie, więc reguła nie pojawia się tak często.
Denker,

Odpowiedzi:

1

Python 2, przykładowa implementacja

Ponieważ nie ma jeszcze żadnych zgłoszeń, zapisałem przykładową implementację w Pythonie. Format wejściowy jest taki sam, jak w testach w wyzwaniu.

Może to motywuje was do działania, to nie jest takie trudne :)

def gameValue(hand):
    jacks = ""
    suits = {"C" : 0, "S" : 0, "H" : 0, "D" : 0}
    # Loop through the hand, find all jacks and count the cards of each suit
    for card in hand:
        jacks += card[1] if "J" in card else ""
        suits[card[1]] += 1 if card[0] != "J" else 0

    # Map the Jacks to numbers while 1 is the highest (Clubs) then sort them ascending
    jacks =  sorted(map(lambda j: {"C" : 1, "S" : 2, "H" : 3, "D" : 4}[j], list(jacks)))

    # Sort the suits by amount. Highest amount and value is first after that
    suits = sorted(suits.items(), key = lambda suit: suit[1], reverse = True)
    trumpSuit = suits[0][0];
    # Amount of trumps is jack-count plus trumpsuit-count
    trumpCount = len(jacks) + suits[0][1];

    # Check for at least one ace that is no trump
    hasAce  = len(filter(lambda c: c[0] == "A" and c[1] != trumpSuit, hand)) >= 1

    # If the hand  is playable, calculate jack-factor and output the result, otherwise pass
    if trumpCount >= 6 and hasAce:
        # If there no jacks the factor is 5. If there are, find the first gap
        if len(jacks) > 0:
            lastJack = 0
            for jack in jacks:
                if jack - lastJack >= 2:
                    break
                lastJack = jack

            jackFactor = jacks[0] if lastJack == 0 else lastJack + 1
        else:
            jackFactor = 5

        trumpFactor = {"C" : 12, "S" : 11, "H" : 10, "D" : 9}[suits[0][0]]
        print str(trumpFactor * jackFactor) + " " + {12 : "Clubs", 11 : "Spades", 10 : "Hearts", 9 : "Diamonds"}[trumpFactor]
    else:
        print "pass"
Denker
źródło
0

Java, 256 bajtów

h->{int i,j=1,m=0,t,n=0,a[]=new int[8];for(var c:h){t=c[1]-48;if(c[0]==74){j+=1<<t;n++;}else{m+=i=c[0]==65?1:0;a[--t+4]+=i;a[t]++;}}for(i=t=0;i<4;i++)t=a[i]<a[t]?t:i;return a[t]+n<6|m-a[t+4]<1?"p":(t+++9)*(5-(int)(Math.log(j>7?~j&7:j)/Math.log(2)))+" "+t;}

Bierze wkład w postaci tablicy tablic znaków w formacie A4, w którym 4jest kluby , 3jest Spades , 2jest Miłość i 1jest Diamonds . Wyjście jest 36 4dla licytacji 36 z klubami atutowymi , pza podanie.

Wypróbuj online tutaj .

Wersja bez golfa:

h -> { // lambda taking a char[][] as argument and returning a String
    int i,                // used as a loop variable and as a temporary variable
        j = 1,            // variable storing the jacks present in the hand in its four last-to-least significant bits
        m = 0,            // number of aces in the hand
        t,                // used as a temporary variable at first, later stores the trump suit
        n = 0,            // number of jacks in the hand
        a[] = new int[8]; // in the lower 4 indices, stores the number of non-jack cards present in the hand for each suit; in the higher 4 indices, stores the number of aces present in the hand for each suit (0 or 1)

    for(var c : h) {   // loop over all the cards in the hand
        t = c[1] - 48; // determine the suit of the current card; 48 is the ASCII code for '0'
        if(c[0] == 74) { // if it's a jack; 74 is the ASCII code for 'J'
            j += 1 << t; // set the corresponding bit
            n++;         // and increment the total number of jacks
        } else {                             // if it's not a jack
            m += (i = (c[0] == 65 ? 1 : 0)); // increment the total number of aces if it's an ace (65 is the ASCII code for 'A')
            a[ --t + 4] += i;                // increment the number of aces for this suit if it's an ace
            a[t]++;                          // increment the number of non-jack cards for this suit
        }
    }

    for(i = t = 0; i < 4; i++)     // loop over the suits ...
        t = (a[i] < a[t]) ? t : i; // ... and find the one with the most cards, giving priority to higher-valued suits in case of a tie

    return (a[t] + n < 6) |                                             // if there are less than 6 trump cards
           (m - a[t + 4] < 1) ?                                         // or less than 1 non-trump ace
           "p"                                                          // return "p" to pass on the hand
           :                                                            // else return
           ((t++ + 9) *                                                 // the value of the trump suit (and increment the trump suit for output later)
           (5 - (int) (Math.log((j > 7) ? (~j & 7) : j) / Math.log(2))) // times the jack factor
           + " " + t);                                                  // followed by the trump suit
}
OOBalance
źródło
0

C, 235 bajtów

f(char*h){int i,j=1,m=0,t,n=0,a[8]={0};for(;*h;h+=2){t=h[1]-48;if(*h-74){m+=i=*h==65;a[--t+4]+=i;a[t]++;}else{j+=1<<t;n++;}}for(i=t=0;i<4;i++)t=a[i]<a[t]?t:i;printf(a[t]+n<6|m-a[t+4]<1?"p":"%d %d",(t+9)*(5-(int)log2(j>7?~j&7:j)),t+1);}

Port mojej Java odpowiedzi .

Wypróbuj online tutaj .

Zajmuje wejście jako tablica znaków w formacie A4, w którym 4jest kluby , 3jest Spades , 2jest Miłość i 1jest Diamonds . Dane wyjściowe dotyczą 36 4oferty 36 w kolorze atutowym klubami , pza podanie.

Wersja bez golfa:

f(char* h) { // function taking an array of characters as argument (and implicitly returning an unused int)
    int i,          // used as a loop variable and as a temporary variable
        j = 1,      // variable storing the jacks present in the hand in its four last-to-least significant bits
        m = 0,      // number of aces in the hand
        t,          // used as a temporary variable at first, later stores the trump suit
        n = 0,      // number of jacks in the hand
        a[8] = {0}; // in the lower 4 indices, stores the number of non-jack cards present in the hand for each suit; in the higher 4 indices, stores the number of aces present in the hand for each suit (0 or 1); partially initialized to zero, the compiler will do the rest

    for(; *h; h += 2) { // loop over all the cards in the hand
        t = h[1] - 48;  // determine the suit of the current card; 48 is the ASCII code for '0'
        if(*h - 74) {              // if it's not a jack; 74 is the ASCII code for 'J'
            m += (i = (*h == 65)); // increment the total number of aces if it's an ace (65 is the ASCII code for 'A')
            a[ --t + 4] += i;      // increment the number of aces for this suit if it's an ace
            a[t]++;                // increment the number of non-jack cards for this suit
        } else {         // if it's a jack
            j += 1 << t; // set the corresponding bit
            n++;         // and increment the total number of jacks
        }
    }

    for(i = t = 0; i < 4; i++)   // loop over the suits ...
        t = a[i] < a[t] ? t : i; // ... and find the one with the most cards, giving priority to higher-valued suits in case of a tie

    printf( (a[t] + n) < 6 |                             // if there are less than 6 trump cards
            (m - a[t + 4] < 1) ?                         // or less than 1 non-trump ace
            "p" : "%d %d",                               // print "p" to pass on the hand, else print two numbers
            (t + 9) *                                    // first the value of the trump suit ...
            (5 - (int) log2((j > 7) ? (~j & 7) : j)),    // ... times the jack factor,
            t + 1                                     ); // followed by the trump suit
}
OOBalance
źródło
226 bajtów
ceilingcat