Расчет стоимости рук в блэкджеке - PullRequest
3 голосов
/ 08 марта 2010

Я реализую небольшую игру Black Jack на C #, и у меня возникла следующая проблема с вычислением значения руки игрока. Тузы могут иметь значение 1 или 11 в зависимости от руки игрока. Если у игрока три карты и один туз, то если сумма карт <= 10, то туз будет иметь значение 11, в противном случае он будет иметь значение 1. </p>

Теперь давайте предположим, что я не знаю, сколько тузов у ​​игрока, и игра реализована, давая возможность дилеру использовать более одной колоды карт. Пользователь может иметь в одной руке даже 5, 6, 7, 8 ... тузов.

Каков наилучший способ (возможно, с использованием Linq) для оценки всех тузов, которые игрок получил, чтобы получить ближайшую комбинацию до 21 (в дополнение к другим картам)?

Я знаю карты игроков и хочу рассчитать их значения, используя тузов, чтобы приблизиться к 21.

Ответы [ 5 ]

3 голосов
/ 08 марта 2010

Это не кажется таким сложным,

  • Вы просто добавляете все остальные карты и находите меньшее значение, которое имеет рука
  • теперь у вас есть два случая:
    • sum <= 10: таким образом, вы проверяете, как два результата, предполагая, что один туз может рассматриваться как 11, таким образом: sum + 11 + (numAces-1)*1 <= 21, тогда это самое близкое значение к 21, в противном случае sum + numAces*1 (потому что при использовании туза как 11 переполнится)
    • sum > 10: вы можете просто считать тузов 1, поэтому окончательное значение равно sum + numAces*1

(никогда не использовал C # , поэтому этот ответ является метакодом)

2 голосов
/ 08 марта 2010

Сложите значение всех не-тузов и добавьте количество тузов: 2, Q, A, A = 2 + 10 + (2) = 14

Затем вычтите это из 21: 21 - 14 = 7

.

Это число меньше 10 (если только 1 туз == 11)? Менее 20 (если оба туза == 11)?

Поскольку это похоже на домашнюю работу, это намеренно не полный ответ, но оно должно вас сопровождать.

0 голосов
/ 08 марта 2010

Проще всего думать об этом так - с каждой раздаемой картой добавьте ценность карты к общему количеству туза, равному 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 никогда не вызовет банкротства игрока.

0 голосов
/ 08 марта 2010

С моей точки зрения, вы должны учитывать тот факт, что, когда у игрока есть один или несколько тузов, он или она имеет два возможных результата в любой момент времени. Попытка вычислить единственное значение, наиболее близкое к 21 - ошибочная абстракция того, что значит держать туза в блэкджеке.

Как игрок, я не хочу, чтобы программа говорила мне, что у меня 16, когда у меня туз и 5, потому что я не могу получить удар с 16, но если у меня туз и 5, я абсолютно принять этот удар. Концептуально у меня действительно 6 или 16.

Я думаю, что ценность руки должна быть представлена ​​как одно или два значения. Очевидно, что при отсутствии туза будет только одно значение. Точно так же, когда туз-как-одиннадцать означает раздаченную руку, для этой руки есть только одно значение, потому что туз должен считаться равным 1. Вы также можете сказать, что любая комбинация туз + 10 имеет только одну значение, потому что это мгновенный блэкджек.

Вот частичная реализация - один из многих, многих способов снять шкуру с этой кошки. Я написал это таким образом, чтобы заставить вас думать определенным образом; учитывая, что только тузы могут иметь более одного значения, а данная рука может иметь не более двух возможных значений, однако это можно сделать более кратко.

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;
   }
}
0 голосов
/ 08 марта 2010

Как описано, вы сможете реализовать это с помощью метода расширения Aggregate .

Напишите функцию, которая реализует ваш алгоритм, и используйте ее:

IEnumerable<int> cards = // card values
var f = (int i1, int i2) => // implement algorithm here
var result = cards.Aggregate(f);
...