Bewerten Sie eine Skat-Hand

18

Einführung

Skat ist ein traditionelles deutsches Kartenspiel für 3 Spieler. Das Deck besteht aus 32 Karten: Ass, König, Dame, Bube, 10, 9, 8, 7 in allen 4 Farben (Kreuz, Pik, Herz, Karo).

In jeder Runde spielt ein Spieler solo, während die anderen beiden gegen ihn spielen. Zu Beginn einer Runde erhält jeder Spieler 10 Karten, die restlichen 2 Karten heißen Skat und werden verdeckt in die Mitte gelegt. Der Einzelspieler wird durch eine Angebotsphase bestimmt. Dies ist der Teil des Spiels, mit dem Sie sich in dieser Herausforderung auseinandersetzen müssen, mehr dazu weiter unten.

Der Spieler, der die Gebotsphase gewinnt, wird zum Solospieler. Er nimmt den Skat und wirft dann zwei Karten ab (die möglicherweise die gleichen sind, die das andere Team nicht kennt), zieht die Trumpffarbe und die Runde beginnt.

Eine Runde besteht aus zehn Tricks. Der Spieler, der einen Stich gewinnt, führt den nächsten, bis alle Karten gespielt sind. Ich werde die Regeln hier nicht erklären, aber Sie sollten wissen, dass es gut ist, viele Trumpfkarten zu haben. Wenn Sie mehr über die Regeln erfahren möchten, lesen Sie den Wikipedia-Artikel, den ich zu Beginn dieses Beitrags verlinkt habe, aber er wird für diese Herausforderung nicht benötigt.

Die Herausforderung

Sie möchten Ihren beiden Söhnen das Skatspielen beibringen. Die Regeln sind nicht so hart, also kommen sie schnell rein. Das einzige, was ihnen Schwierigkeiten bereitet, ist das Bieten, bei dem speziell der Spielwert ihrer Hand berechnet wird. Sie beschließen also, ein kleines Programm zu schreiben, das den maximalen Spielwert ausgibt, den sie für ihre aktuelle Hand bieten können.

Berechnung des Spielwertes

Jede Hand hat einen bestimmten Spielwert. Es wird durch die Anzahl der aufeinanderfolgenden Buben bestimmt, die Sie haben, und durch die Farbe, die Sie als Trumpf auswählen möchten. Beginnen wir mit dem ersten Faktor, den Buchsen!

Der Jack-Faktor

Buben sind immer Trumpfkarten und schlagen jede andere Trumpfkarte. Die Reihenfolge der Stärke zwischen den vier Buben ist:

  1. Jack of Clubs (höchste)
  2. Jack of Spades
  3. Jack of Hearts
  4. Jack of Diamonds (niedrigste)

In der weiteren Erläuterung beziehe ich mich mit den Nummern, die ich ihnen hier zugewiesen habe.

Erinnern Sie sich, dass die Buben in Ihrer Hand eine Art Faktor enthalten, der zum Spielwert beiträgt? Groß! So bekommen Sie es:

Dieser Jack-Faktor ist die Anzahl der Top-Jacks (siehe Reihenfolge oben) in Folge plus 1. Wenn Sie also alle 4 Jacks haben, ist dies 4 + 1 = 5. Wenn Sie nur die ersten 2 Jacks haben, ist dies 2 + 1 = 3.

Um die Sache etwas komplizierter zu machen, kann der Jack-Faktor auch die Anzahl der Top-Jacks in der Reihenfolge sein, die Sie vermissen , plus 1. Wenn Sie also den ersten vermissen, ist es 1 + 1 = 2. Wenn Sie Fehlt die erste 3, so ist es 3 + 1 = 4. Hier einige Beispiele unter Verwendung der obigen Nummerierung:

[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

Das war der erste Faktor. Hier ist, wie Sie die 2. bekommen:

Der Trumpffaktor

Dieser ist viel einfacher. Der 2. Faktor wird durch die Trumpffarbe bestimmt, die der Solospieler mit der folgenden Zuordnung auswählt:

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

Das war doch einfach, oder?

Der Spielwert

Der Spielwert ist das Produkt der beiden Faktoren. Ziemlich einfach, denkst du? Falsch! Während der Jack-Faktor festgelegt ist, ist der Suit-Faktor nicht festgelegt. Welche Farbe du als Trumpf auswählst, hängt von der Anzahl der Trümpfe und dem Wert deiner Nicht-Trumpfkarten in deiner Hand ab. Es wäre viel zu kompliziert zu erklären, wie eine gute Hand aussieht, daher werden Sie den folgenden Algorithmus verwenden:

Der Which-Trump-do-I-Pick-Algorithmus

Sie müssen nicht an der Ausschreibung teilnehmen. Wenn Sie feststellen, dass Ihre Hand zu schlecht ist, um alleine zu spielen, können Sie einfach passen. Ihre Hand muss die folgenden Kriterien erfüllen, um spielbar zu sein:

  • Haben Sie mindestens 6 Trumpfkarten (Karten der ausgewählten Trumpffarbe + die Anzahl der Buben). Wenn dies für mehr als eine Farbe möglich ist, wählen Sie die Farbe aus, die zu mehr Trumpfkarten führen würde. Wenn es immer noch ein Unentschieden gibt, wählen Sie den Anzug mit der höchsten oben angegebenen Bewertung.

  • Haben Sie von den Nicht-Trumpfkarten mindestens 1 Ass.

Wenn Ihre Hand nicht beide Kriterien erfüllt, haben Sie bestanden. In diesem Fall geben Sie den berechneten Spielwert und die gewählte Trumpffarbe aus.

Kurzer Hinweis: Dies ist natürlich ein sehr vereinfachter Algorithmus. Es steckt viel zu viel Strategie und Erfahrung in der Beurteilung einer Hand, als dass wir jemals in einer solchen Herausforderung bestehen könnten.

Eingang

Jede Karte hat eine eindeutige Kennung. Der erste Teil ist der Anzug ( C Lubs, S PAdES, H eARTS, D iamonds), der zweite Teil ist der Wert, der durch diese Zuordnung gegeben ist:

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

Beide Teile bilden zusammen eine Karte. Der Wert steht an erster Stelle, dann kommt der Anzug. Sie können die Karten in jedem gewünschten Format nehmen.

Ausgabe

Wenn die Hand spielbar ist, geben Sie den Spielwert und die gewählte Trumpffarbe aus (Reihenfolge spielt keine Rolle). Ist dies nicht der Fall, geben Sie "pass" aus.

Regeln

  • Wie bereits erwähnt, können Sie die Eingabe im für Sie bequemsten Format vornehmen. Beispiele siehe unten in den Testfällen.
  • Die Eingabe kann über Befehlszeilenargumente, Benutzereingaben oder Funktionsargumente erfolgen.
  • Die Ausgabe kann als Rückgabewert erfolgen oder nur auf dem Bildschirm ausgedruckt werden.
  • Die Karten im Eingang dürfen in keiner Weise bestellt werden. Ihr Programm muss in der Lage sein, zufällige Kartenbestellungen zu verarbeiten.
  • Die niedrigste Anzahl an Bytes gewinnt!

Testfälle

In den Testfällen wird eine Liste von Zeichenfolgen mit zwei Zeichen eingegeben.

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

Erläuterung:

  1. Zwei Buben hintereinander mit Clubs als Trumpf. Der Spielwert beträgt also 3 x 12 = 36
  2. Drei Buben in einer Reihe fehlen mit Pik als Trumpf. Der Spielwert beträgt also 4 x 11 = 44
  3. Es sind nur maximal 4 Trumpfkarten möglich, Sie werden also passen.
  4. Sechs Trumpfkarten mit Pik, aber ohne Non-Trump-Ass, Sie werden passen.

Wenn einige Regeln unklar sind, kommentieren Sie sie. Ich bin mit diesem Spiel aufgewachsen, daher fällt es mir schwer zu beurteilen, ob ich alles ausführlich genug beschrieben habe.

Und jetzt ... Happy Coding!

edit: Wie ich in den Kommentaren (danke an isaacg) bemerkt habe, gibt es eine Regel, die die folgenden Top-Trümpfe nach den 4 Buben in den "Buben-Faktor" einrechnet, sodass es bis zu 11 gehen kann. Um diese Herausforderung einfach zu halten und um die leute nicht zu verwirren, werden die regeln, die ich ursprünglich vorgeschlagen habe, so bleiben, wie sie sind. Der maximale Faktor bleibt also bei 5.

Denker
quelle
6
Willkommen bei Programming Puzzles & Code Golf - ausgezeichnete erste Herausforderung! :)
Türklinke
1
Sollte die Anzahl der Straight Jacks / Fehlenden Jacks auch die Trümpfe der oberen Farbe der Reihe nach enthalten? Das sagt Wikipedia hier
isaacg
@isaacg Ich muss zugeben, dass ich bis jetzt nichts von dieser Regel wusste. Vielen Dank für den Hinweis. Ich habe ein paar Nachforschungen angestellt und Sie haben in der Tat Recht. In meiner Familie spielen wir nicht mit dieser Regel und ich habe auch niemanden getroffen, der damit spielt. Es ist nicht so wichtig, denn wenn Sie eine solche Hand haben, spielen Sie meistens Grand, was ohnehin anders ist. Für diese Herausforderung werden wir einfach die von mir vorgeschlagenen Regeln einhalten. Ich werde meinen Beitrag bearbeiten, damit es allen klar ist.
Denker
1
@DenkerAffe, ich habe viele Jahre in einem Verein in Deutschland Skat gespielt und vertraue mir, die Regel ist wichtig, und es gibt Fälle, in denen sie äußerst relevant ist (und ja, bei den meisten nicht ernsthaften Spielern ist sie unbekannt). Vor allem mit der fehlenden Seite - stellen Sie sich vor, Sie haben Trumpf K, D, 9, 8, 7 und drei A und zwei 10 in den anderen Farben. Dein Grand stirbt auf jeden Fall, aber du kannst 'ohne 6' spielen (Kontra einsammeln) und sie besiegen, vorausgesetzt du hast eine Idee, wie die B vom Bieten her sitzen. Und Sie können bieten, bis die Sonne mit dieser Karte kommt.
Aganju
@Aganju Ich bin schon davon ausgegangen, dass diese Regel den meisten Hobby-Spielern nicht bekannt ist. Danke für die Bestätigung. Ich bezweifle nicht, dass es wichtig ist, aber meiner Erfahrung nach sind solche Hände ziemlich selten, so dass die Regel nicht so oft ins Spiel kommt.
Denker

Antworten:

1

Python 2, Beispielimplementierung

Da es noch keine Einreichungen gibt, habe ich eine Beispielimplementierung in Python aufgeschrieben. Das Eingabeformat ist dasselbe wie in den Testfällen in der Challenge.

Vielleicht motiviert das euch, loszulegen, es ist nicht so schwer :)

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
quelle
0

Java, 256 Bytes

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

Nimmt die Eingabe als ein Array von Zeichenfeldern in dem Format A4, in dem 4ist , Clubs , 3ist Pik , 2ist Herzen und 1ist Diamanten . Die Ausgabe ist 36 4für ein Gebot von 36 mit Trumpffarbe Clubs , pfür nebenbei.

Probieren Sie es hier online aus .

Ungolfed-Version:

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
quelle
0

C 235 Bytes

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 meiner Java- Antwort .

Probieren Sie es hier online aus .

Nimmt die Eingabe als ein Array von Zeichen in dem Format A4, in dem 4ist Clubs , 3ist Pik , 2ist Herz und 1ist Diamanten . Die Ausgabe ist 36 4für ein Gebot von 36 mit Trumpffarbe Clubs , pfür nebenbei.

Ungolfed-Version:

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
quelle
226 Bytes
Ceilingcat