5

私は C# で小さなブラック ジャックゲームを実装していますが、プレイヤーの手の値を計算する際に次の問題があります。エースは、プレイヤーの手札に応じて 1 または 11 の値になります。プレイヤーが 3 枚のカードと 1 つのエースを持っている場合、カードの合計が 10 以下の場合、エースの値は 11 になり、それ以外の場合は 1 になります。

ここで、プレーヤーがエースをいくつ持っているかわからず、ディーラーが複数のカード デッキを使用できるようにゲームが実装されていると仮定します。ユーザーは片手で 5、6、7、8... のエースを持っている場合もあります。

(他のカードに加えて) 21 に最も近い組み合わせを得るためにプレーヤーが持っているすべてのエースを評価するための最良の方法 (おそらく Linq を使用) は何ですか?

私はプレイヤーのカードを知っており、エースを使用して 21 に最も近い値に達するようにそれらの値を計算したいと考えています。

4

5 に答える 5

5

エース以外のすべての値を合計し、エースの数を追加します: 2、Q、A、A = 2 + 10 + (2) = 14

次に、21 からそれを引きます: 21 - 14 = 7

この数字は 10 未満ですか (エースが 1 つだけ == 11 の場合)? 20 未満 (両方のエース == 11 の場合)?

これは宿題のように感じるので、これは意図的に完全な答えではありませんが、ガイドとなるはずです。

于 2010-03-08T15:50:17.117 に答える
4

見た目はそれほど複雑ではありませんが、

  • 他のすべてのカードを追加して、ハンドの低い価値を見つけます。
  • これで、次の 2 つのケースができました。
    • sum <= 10: したがって、1 つのエースを次のように 11 と見なすことができると仮定して、2 つの結果がどのようになるかを確認します: sum + 11 + (numAces-1)*1 <= 21、これは 21 に最も近い値ですsum + numAces*1
    • sum > 10: エースを 1 とみなすことができるので、最終的な値はsum + numAces*1

C#を使用したことがないため、この回答はメタコードです)

于 2010-03-08T15:48:55.460 に答える
0

私の見解では、プレーヤーが 1 つ以上のエースを持っている場合、いつでも 2 つの可能なスコアを持っているという事実を説明する必要があります。21 に最も近い単一の値を計算しようとすることは、ブラックジャックでエースを保持することの意味を誤って抽象化したものです。

プレーヤーとして、私はエースと 5 を持っているときに 16 を持っているとプログラムに言われたくありません。なぜなら、16 でヒットしないかもしれないからです。 . 概念的には、私は実際に 6つまたは16 を持っています。

ハンドの値は、1 つまたは 2 つの値として表現できるべきだと思います。明らかに、エースがない場合、値は 1 つだけになります。同様に、ace-as-eleven がバステッド ハンドを意味する場合、そのエースは 1 としてカウントされる必要があるため、そのハンドには 1 つの値しかありません。また、任意のエース + 10 の組み合わせには 1 つの値しかないとも言えます。これはインスタントであるためです。ブラックジャック。

これは部分的な実装です。この猫の皮を剥ぐための非常に多くの方法の 1 つです。このように書いたのは、あなたに特定の方法で考えてもらうためです。ただし、複数の値を持つことができるのはエースだけであり、与えられたハンドは最大 2 つの可能な値を持つことができるため、これはもっと簡潔に行うことができます。

public interface Hand
{
   IEnumerable<int> PossibleValues { get; set; }
}
public interface Card
{
   CardValues PossibleValues { get; set; }
}
public interface CardValues
{
    int Value1 { get; }
    int Value2 { get; }
}

public class BlackjackHand : Hand
{
    IList<Card> cards;

   public IEnumerable<int> PossibleValues
   {
        IList<int> possible_values = new List<int>();

        int initial_hand_value = cards.Sum(c => c.Value1);
        if(initial_hand_value <= 21)
        {
            possible_values.Add(initial_hand_value);
            yield return initial_hand_value;
        }

        foreach(Card card in cards.Where(c => c.Value2 > 0))
        {
            IList<int> new_possible_values = new List<int>();
            foreach(int value in possible_values)
            {
                var alternate_value = value + card.Value2;
                if(alternate_value <= 21) 
                {
                    new_possible_values.Add(alternate_value);
                    yield return alternate_value;
                }
            }
            possible_values.AddRange(new_possible_values);
        }

        yield break;
   }
}
于 2010-03-08T17:15:39.207 に答える
0

説明したように、 Aggregate拡張メソッドを使用してこれを実装できるはずです。

アルゴリズムを実装して使用する関数を作成します。

IEnumerable<int> cards = // card values
var f = (int i1, int i2) => // implement algorithm here
var result = cards.Aggregate(f);
于 2010-03-08T15:49:54.090 に答える
0

このように考えるのが最も簡単かもしれません - 各カードが配られると、カードの値を合計カウント エースに 11 として追加します。カードがエースで、プレイヤーがバーストした場合、10 を引きます。例:

int total = 0;
...
int hit = GetHit();
total = total + hit;

if (total > 21 && hit == 11)
{
  total = total - 10
}
// check if player busted, etc

最初のディールでは、GetHit() を使用してカードを「ディール」するか、Ace-Ace (カードが 2 枚の問題の場合のみ) のハンドを自分で処理することができます。これにより、常に最高のハンドが得られます。プレイヤーはエースが 1 または 11 になる可能性があることを知っていると仮定しても問題ないと思います。そのため、エース 5 をヒットしてもプレイヤーがバストすることは決してありません。

于 2010-03-08T17:27:57.627 に答える