评估滑手


18

介绍

Skat是一款传统的德式纸牌游戏,可容纳3位玩家。副牌由32张牌组成:王牌,王牌,王后,杰克,10套,9套,8套,7套所有4套服(俱乐部,黑桃,心,钻石)。

在每个回合中,有一个玩家独奏,而另外两个则与他对抗。在回合开始时,每位玩家被发10张牌,剩下的2张牌称为skat,并面朝下放在中间。独奏者由投标阶段确定。这是您在此挑战中必须处理的游戏部分,有关此内容的更多信息,请参见下文。

赢得竞标阶段的玩家将成为独占玩家。他拿起小号,然后放下两张牌(可能是相同的,另一支球队不知道),拿下王牌,然后回合开始。

一轮包括十个技巧。赢得花样的玩家将领导下一张,直到玩完所有纸牌为止。我不会在这里解释这些规则,但是您应该知道拥有很多王牌是很好的。如果您想了解规则,请查看我在本文开头链接的Wikipedia文章,但对于本挑战而言并不需要。

挑战

您想教您的两个儿子如何打skat。这些规则并不难,因此很快就会被采纳。唯一给他们带来困难的是出价,特别是计算他们手牌的游戏价值。因此,您决定编写一个小程序,输出给定当前手牌可以出价的最大游戏值。

计算游戏价值

每只手都有一定的游戏价值。它由您所拥有的连续千斤顶的数量和您要选为王牌的西装决定。让我们从第一个因素开始吧!

杰克因素

千斤顶总是王牌,他们击败其他所有王牌。四个千斤顶之间的强度顺序为:

  1. 俱乐部杰克(最高)
  2. 黑桃杰克
  3. 杰克之心
  4. 钻石杰克(最低)

在进一步的说明中,我将使用此处分配给他们的编号来引用它们。

您还记得从您手中的Jacks获得的某种因素是游戏价值的一部分吗?大!这是您的获取方式:

该千斤顶系数是依次排列的最高千斤顶数(请参阅上面的顺序),再加上1。因此,如果您拥有全部4个千斤顶,则为4 +1 =5。如果只有前2个千斤顶,则为2 +1 = 3。

另外,为了使事情更复杂一点,杰克因数也可以是您所缺少的按顺序排列的最高杰克数加1。因此,如果您缺少第一个杰克,则为1 +1 = 2。缺少他的前3个,即3 + 1 =4。下面是使用上面的编号的示例:

[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

那是第一个因素。这是您获得第二个的方法:

特朗普诉讼因素

这一个简单得多。第二个因素由独奏者使用以下映射选择的王牌西装确定:

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

那很容易,不是吗?

游戏价值

游戏价值是两个因素的乘积。您觉得很容易吗?错误!千斤顶因数是固定的,而拟合因数不是固定的。您最终选择的西服套装取决于王牌数量和手中非王牌的价值。解释好手看起来太复杂了,因此您将使用以下算法:

哪个胜过我选择算法

您不必参加竞标。如果您认为自己的手牌太糟糕而不能独奏,则可以通过。您的手必须符合以下条件才能玩:

  • 至少有6张王牌(您选择的王牌套装的卡+插孔数)。如果这可能适用于不止一套衣服,请选择那套会带来更多王牌的衣服。如果仍然有领带,则选择上面给出的最高评分的西装。

  • 在非麻将卡中,至少有1个A。

如果您的手不符合这两个条件,您将通过。如果是这样,您将输出计算出的游戏值和所选的王牌套装。

简短说明:当然,这是一个非常简化的算法。判断手牌方面有太多的策略和经验,超出了我们在这种挑战中所无法涵盖的范围。

输入值

每张卡都有唯一的标识符。第一部分是西装(C lubs,S pades,H earts,D iamonds),第二部分是此映射给出的值:

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

这两部分组成一张卡。价值首先出现,然后是诉讼。您可以根据需要采取任何格式的卡。

输出量

如果这只手是可玩的,则输出游戏值和所挑选的王牌西服(顺序无关紧要)。如果不是,则输出“ pass”。

规则

  • 如前所述,您可以采用最方便的格式输入。示例参见下面的测试案例。
  • 输入可以通过命令行参数,用户输入或函数参数提供。
  • 输出可以作为返回值提供,也可以仅打印在屏幕上。
  • 不得以任何方式订购输入中的卡。您的程序必须能够处理任何随机的卡订单。
  • 最低字节数获胜!

测试用例

测试用例中的输入将是2个字符的字符串列表。

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

说明:

  1. 连续两个杰克与俱乐部作为王牌。因此游戏值为3 x 12 = 36
  2. 连续三个杰克缺少黑桃作为王牌。所以游戏值为4 x 11 = 44
  3. 最多只能有4张王牌,这样您就可以通过。
  4. 六张带黑桃王牌但无王牌的王牌,因此您将通过。

如果某些规则不清楚,请继续进行评论。我从小就玩这个游戏,所以很难判断我是否足够详细地描述了所有内容。

现在... 快乐编码!

编辑:正如我在评论中向我指出的(感谢isaacg),有一个规则可以将4个千斤顶放入“千斤顶系数”后计入以下最高得分,因此可以升至11。为了不混淆人们,我最初提出的规则将保持原样。因此,最大因数保持在5。


6
欢迎参加编程难题和代码高尔夫-出色的第一个挑战!:)
门把手

1
直式千斤顶/缺失式千斤顶的数量是否也应依次包括顶级西服王牌?维基百科在这里
-isaacg

@isaacg我必须承认,直到现在我都不知道这条规则。感谢您指出了这一点。我做了一些研究,您确实是对的。在我的家人中,我们不遵守这条规则,我也没有遇到任何遵守此规则的人。它没有那么高的相关性,因为当您拥有这样的牌时,大多数时候您都会玩Grand,而无论如何,Grand都被认为是不同的。因此,对于这一挑战,我们将保持我提出的规则。我将编辑我的帖子,以便所有人都清楚。
Denker

1
@DenkerAffe,我在德国的一家俱乐部效力过Skat多年,并且相信我,这个规则很重要,而且在某些情况下它非常相关(是的,在大多数不认真的球员中都是未知的)。尤其是缺少一面-想象您有K,D,9、8、7和三个A和两个10代表其他颜色。您的Grand肯定会死,但是您可以打出“ ohne 6”(收集一些对战)并击败他们,前提是您从竞标中知道B的位置。您可以出价直到太阳升起这张卡片。
Aganju '16

@Aganju我已经假定大多数业余玩家都不了解此规则。感谢您的确认。我毫不怀疑这很重要,但是根据我的经验,像这样的手很少见,因此该规则很少出现。
Denker

Answers:


1

Python 2,示例实现

由于尚未提交任何内容,因此我写下了Python中的示例实现。输入格式与质询中的测试用例相同。

也许这会激励你们走,这并不难:)

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"

0

Java,256个字节

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

取输入作为字符数组的格式的阵列A4,其中4俱乐部3黑桃21钻石。输出36 4为36王牌投标俱乐部p为合格。

在这里在线尝试。

非高尔夫版本:

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
}

0

C,235字节

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

我的Java 回答的端口。

在这里在线尝试。

取输入作为字符的格式的阵列A4,其中4俱乐部3黑桃21钻石。输出36 4为36王牌投标俱乐部p为合格。

非高尔夫版本:

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
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.