スキャットハンドを評価する


18

前書き

Skatは、3人のプレイヤー向けの伝統的なドイツのカードゲームです。このデッキは32枚のカードで構成されています:エース、キング、クイーン、ジャック、10、9、8、7、4スーツすべて(クラブ、スペード、ハート、ダイアモンド)。

すべてのラウンドで、1人のプレーヤーがソロをプレイし、他の2人が彼と対戦します。ラウンドの開始時に、各プレイヤーに10枚のカードが配られ、残りの2枚のカードはスカットと呼ばれ、真ん中に裏向きに置かれます。ソロプレーヤーは、入札フェーズによって決定されます。これは、このチャレンジで対処しなければならないゲームの一部です。これについては以下で詳しく説明します。

入札フェーズで勝ったプレイヤーがソロプレイヤーになります。彼はスケートを拾い上げ、次に2枚のカード(同じかもしれませんが、他のチームは知らない)を落とし、切り札のスーツを選び、ラウンドが始まります。

1ラウンドは10のトリックで構成されています。トリックに勝ったプレイヤーは、すべてのカードがプレイされるまで次のプレイヤーをリードします。ここではルールを説明しませんが、多くの切り札を持っているのは良いことです。ルールについて学びたい場合は、この投稿の冒頭でリンクしたウィキペディアの記事を確認してください。ただし、このチャレンジには必要ありません。

チャレンジ

2人の息子にスケートの遊び方を教えたいと思います。ルールはそれほど難しくないので、すぐにそれに入ります。彼らに苦労を与える唯一のことは、特に彼らの手のゲーム価値を計算する入札です。そこで、現在のハンドでビッドできる最大のゲーム価値を出力する小さなプログラムを書くことにします。

ゲーム価値の計算

すべてのハンドには特定のゲーム価値があります。それはあなたが持っている連続したジャックの量と、あなたが切り札として選びたいスーツによって決まります。最初の要素であるジャックから始めましょう!

ジャックファクター

ジャックは常に切り札であり、他のすべての切り札よりも優れています。4つのジャックの強さの順序は次のとおりです。

  1. クラブのジャック(最高)
  2. スペードのジャック
  3. ハートのジャック
  4. ダイヤモンドのジャック(最低)

詳細な説明では、ここで割り当てた番号でそれらを参照します。

ゲームの価値の一部である、あなたの手にあるジャックから得られる何らかの種類の要因があることを覚えていますか?すごい!取得方法は次のとおりです。

このジャックファクターは、トップジャックの数(上記の順序を参照)に1を加えたものです。したがって、4つのジャックがすべてある場合は4 + 1 = 5です。最初の2つのジャックしかない場合は2 + 1 = 3。

あるいは、物事をもう少し複雑にするために、ジャックファクターは、欠落しているトップジャックの数に1を足した数に1を加えたものにすることもできます。最初の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

それが最初の要因でした。2番目のものを取得する方法は次のとおりです。

トランプスーツファクター

これは非常に簡単です。2番目の要因は、ソロプレーヤーが次のマッピングを使用して選ぶトランプスーツによって決まります。

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

それは簡単でしたね。

ゲームの価値

ゲームの価値は2つの要素の積です。とても簡単だと思いますか?違う!ジャックファクターは固定されていますが、スーツファクターは固定されていません。あなたが切り札として選んだスーツは、切り札の量と手札にある非切り札の価値に依存します。良いハンドがどのように見えるかを説明するにはあまりにも複雑すぎるため、次のアルゴリズムを使用します。

which-trump-do-i-pickアルゴリズム

入札に参加する必要はありません。あなたの手がソロをプレイするにはあまりにも悪いと判断した場合、あなたはただパスできます。あなたのハンドは次の基準に合致しなければプレイできません:

  • 少なくとも6枚のトランプカード(選択したトランプスーツのカード+ジャックの数)を用意します。これが複数のスーツで可能であれば、より多くの切り札をもたらすものを選んでください。まだネクタイがある場合は、上記の最高評価のスーツを選びます。

  • トランプ以外のカードのうち、少なくとも1つのエースがあります。

あなたの手がこの両方の基準に一致しない場合、合格します。もしそうなら、計算されたゲーム値と選択された切り札を出力します。

短いメモ:もちろんこれは非常に単純化されたアルゴリズムです。このようなチャレンジでカバーすることができないほど、多くの戦略と経験が手を判断することになります。

入力

すべてのカードには一意の識別子があります。最初の部分はスーツ(C lubs、S pades、H earts、D iamonds)、2番目の部分はこのマッピングで与えられる値です:

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

両方の部分を組み合わせて1つのカードを形成します。値が最初に来て、次にスーツが来ます。あなたが望むように、あなたはどんな形式ででもカードを取るかもしれません。

出力

ハンドがプレイ可能な場合、ゲームの値と選択したトランプスーツを出力します(順序は関係ありません)。そうでない場合は、「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. クラブを切り札とする2つのジャック。したがって、ゲームの価値は3 x 12 = 36です
  2. トランプとしてスペードで行方不明の3つのジャック。したがって、ゲームの価値は4 x 11 = 44です
  3. 最大4枚の切り札しか使用できないため、合格します。
  4. スペードを使用し、非トランプエースを使用しない6枚の切り札。

一部のルールが不明確な場合は、先に進んでコメントしてください。私はこのゲームで育ったので、すべてを十分に詳しく説明したかどうかを判断するのは難しいです。

そして今... ハッピーコーディング!

編集:コメントで指摘したように(isaacgに感謝)、4つのジャックを「ジャックファクター」に入れた後、次のトップトランプをカウントするルールがあります。そして、人々を混乱させないために、私が最初に提案したルールはそのままです。したがって、最大係数は5のままです。


6
プログラミングパズルとコードゴルフへようこそ-優れた最初の挑戦!:)
ドアノブ

1
ストレートジャック/ミッシングジャックの数には、トップスーツトランプも順番に含める必要がありますか?これがウィキペディアがここで
-isaacg

@isaacg私は今までこのルールを知らなかったことを認めなければなりません。それを指摘してくれてありがとう。私はいくつかの研究をしました、そしてあなたは確かに正しいです。私の家族では、このルールで遊んでいませんし、それで遊んでいる人に会ったこともありません。あなたはそのようなハンドを持っているとき、とにかく異なってカウントされる大部分の時間をプレイするので、それはそれほど高い関連性トーを持っていません。そのため、この課題については、私が提案した規則に従うだけです。投稿がすべて編集できるように編集します。
デンカー

1
@DenkerAffe、私はドイツのクラブで長年スカットをプレイしました、そして私を信じてください、ルールは重要です、そして、それが非常に関連する場合があります(そして、はい、それはほとんどの非深刻なプレーヤーでは不明です)。特に行方不明の場合-他の色のトランプK、D、9、8、7、3つのAと2つの10があるとします。グランドは確実に死にますが、Bが入札でどのように座っているかを知っていれば、「オーネ6」(いくつかのコントラを収集)をプレイし、それらを打つことができます。そして、太陽がそのカードで現れるまで、あなたは値をつけることができます。
アガンジュ

@Aganjuこのルールはほとんどの趣味プレーヤーには知られていないとすでに仮定しました。確認してくださってありがとうございます。私はそれが重要であることを疑いませんが、私の経験から、このような手は非常にまれなので、ルールはそれほど頻繁には出てきません。
デンカー

回答:


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

形式の文字列の配列として入力を受け取りA44あるクラブ3あるスペードは2あるハート1なるダイヤモンド。出力は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 回答のポート。

こちらからオンラインでお試しください。

形式での文字の配列として入力を受け取りA44あるクラブは3あるスペード2あるハート1あるダイヤモンド。出力は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
}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.