Dice Question (фулл-хаус и прямое признание) - PullRequest
5 голосов
/ 26 июня 2011

Я играю в кости.Есть 5 кубиков, в которых у меня есть все значения, и мне нужно определить, составляют ли они фулл-хаус (3 из одного и 2 из другого), небольшие прямые (1-4, 2-6 или 3-6) илибольшая прямая (1-5, 2-6).

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

Кто-нибудь знает, как бы я представлял этиправила в регулярных выражениях?

Или, если вы можете предложить лучшее решение, я был бы признателен.

Примеры:

  • Полный дом= 44422 или 11166 или 12212 и т. Д.
  • Малый прямой = 12342 или 54532 и т. Д.
  • Большой прямой = 12345 или 52643 и т. Д.

Редактировать Изменили формулировку, чтобы подчеркнуть, что это мое неопытное мнение.

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

Ответы [ 7 ]

5 голосов
/ 26 июня 2011

Не знаю насчет c #, но на языке сценариев я бы выбрал регулярное выражение. Для каждой стороны подсчитайте, сколько раз это встречается в комбинации, и объедините результаты вместе. Например, для комбинации 12342 строка счетчика будет 121100. Затем сопоставьте строку счетчика с этими образцами:

/5/         = Five of a kind
/4/         = Four of a kind
/20*3|30*2/ = Full house
/1{5}/      = Large Straight
/[12]{4}/   = Small Straight
/3/         = Three of a kind
/2[013]*2/  = Two pair
/2/         = One pair
5 голосов
/ 26 июня 2011

Я бы упорядочил все числа по убыванию, а затем выполнил бы некоторые линейные критерии, совпадающие с каждым значением, по мере его продвижения, будь то в int [] или в строке.

0 голосов
/ 25 сентября 2016

Вот мой код:

    public static int   CalculateTotalOfSingles       (int pipNumber)
    {
        //
        var myScore = 0;
        foreach (var myDie in Roll5Player.MyHand.Dice)
        {
            {   if (myDie.Pips == pipNumber)
                myScore+= pipNumber;
            }
        }
        //
        return myScore;
    }
    public static int   CalculateDicePips       ()
    {
        //
        var myScore = 0;
        foreach (var myDie in Roll5Player.MyHand.Dice)
        {
            {myScore += myDie.Pips;
            }
        }
        //
        return myScore;
    }
    //
    //
    //
    public static int   CalculateTotalOfAllSingles    (int pipNumber)
    {
        //
        var myScore = 0;
        for (int i = 1; i <= 6; i++)
        {
            myScore += pipNumber;
        }
        //
        return myScore;
    }
    public static bool  CalculateIsNOfaKind     (int count)
    {
        //
        for (var index = 1; index <= 6; index++)
        {
            var cntr = 0;
            foreach (var myDie in Roll5Player.MyHand.Dice)
            {
                if (myDie.Pips == index)
                    cntr++;
            }
            //
            if (cntr == count)
            {
                return true;
                ;
            }
        }
        //
        return false;
    }
    public static int   CalculateNOfaKind       (int count  )
    {
        //
        var myScore = 0;
        for (var index = 1; index <= 6; index++)
        {
            var cntr = 0;
            foreach (var myDie in Roll5Player.MyHand.Dice)
            {
                    if (myDie.Pips == index)
                        cntr++;
            }
            //
            if (cntr >= count)
            {   myScore = CalculateDicePips();
                return myScore;
                ;
            }
        }
        //
        return myScore;
    }
    /// 
    public static int   CaluclateFullHouse      (           )
    {
        // 
        var myScore = 0;
        var cntr    = new int[6];
        for (var index = 1; index <= 6; index++)
        {
            foreach (var myDie in Roll5Player.MyHand.Dice)
            {
                if (myDie.Pips == index)
                    cntr[index-1]++;
            }
        }

        //
        var boolCondA = false;
        var boolCondB = false;
        foreach (var i in cntr)
        {
            if (i == 3)
            {boolCondA = true;
                break;
            }
        }
        if (boolCondA)
        {
            foreach (var i in cntr)
            {
                if (i == 2)
                {boolCondB = true;
                    break;
                }
            }
        }


        //
        if (boolCondB ) 
            myScore = CalculateDicePips();



        //
        //
        //
        return myScore;
    }
    public static int   CaluclateStraights      (int straightCount, int score)
    {
        // 
        var tempPip     = 0;
        var myScore     = 0;
        var isFirstIteration = true;
        var cntr = 0;
        int[] sortedDice = new int[5];
        var sortedDiceLise = new List<int>();


        foreach (var myDie in Roll5Player.MyHand.Dice)
        {
            sortedDiceLise.Add(myDie.Pips);
        }
        sortedDiceLise.Sort();







        foreach (var myDie in sortedDiceLise)
        {
            //
            //
            if (!isFirstIteration)
            {
                if (myDie == tempPip + 1)
                    cntr++;
            }
            //
            isFirstIteration = false;
            tempPip = myDie;
        }





        if (cntr == straightCount - 1)
        {myScore = score;
        }

        //
        //
        //
        return myScore;
    }

    public static int   CalculateYahtzee        ()
    {
        //
        for (var index = 1; index <= 6; index++)
        {
            var cntr = 0;
            foreach (var myDie in Roll5Player.MyHand.Dice)
            {
                if (myDie.Pips == index)
                    cntr++;
            }
            //
            if (cntr == 5)
            {
                return 50;
                ;
            }
        }
        //
        return 0;
    }
0 голосов
/ 03 сентября 2016

Вы можете попытаться поместить свои значения в список.Это позволит вам быстро отсортировать ваши значения.И если вы добавите значения, которые дадут вам руку.111AA = 29 и 222KK = 30. Просто идея.

0 голосов
/ 26 июня 2011

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

  enum RollScoreType
  {
     HighDie,
     Pair,
     TwoPair,
     ThreeOfAKind,
     SmallStright,
     PairSmallStriaght,
     FullHouse,
     LargeStraight,
     FourOfAKind,
     FiveOfAKind
  }

  struct RollScore
  {
     public RollScoreType type;
     public byte highestDie;
     public byte nextHighestDie;
     public RollScore(RollScoreType type, byte highest, byte next)
     {
        this.type = type;
        this.highestDie = highest;
        this.nextHighestDie = next;
     }
     public override string ToString()
     {
        return string.Format("{0} {1} {2}", type, highestDie, nextHighestDie);
     }
  }

  static RollScore GetDiceScore(string input)
  {
     char[] dice = input.ToCharArray();
     byte[] diceCount = new byte[6];

     for (int i = 0; i < dice.Length; i++)
        diceCount[int.Parse(dice[i].ToString())-1]++;

     if (Array.IndexOf(diceCount, (byte)5) >= 0)
        return new RollScore(RollScoreType.FiveOfAKind, (byte)(Array.IndexOf(diceCount, (byte)5) + 1), 0);
     else if (Array.IndexOf(diceCount, (byte)4) >= 0)
        return new RollScore(RollScoreType.FourOfAKind, (byte)(Array.IndexOf(diceCount, (byte)4) + 1), (byte)(Array.IndexOf(diceCount, (byte)1) + 1));
     else if (Array.IndexOf(diceCount, (byte)3) >= 0)
     {
        byte three = (byte)(Array.IndexOf(diceCount, (byte)3) + 1);
        if (Array.IndexOf(diceCount, (byte)2) >= 0)
        {
           byte pair = (byte)(Array.IndexOf(diceCount, (byte)2) + 1);
           return new RollScore(RollScoreType.FullHouse, Math.Max(pair, three), Math.Min(pair, three));
        }
        else
           return new RollScore(RollScoreType.ThreeOfAKind, three, (byte)(Array.LastIndexOf(diceCount, (byte)1) + 1));
     }
     else if (Array.IndexOf(diceCount, (byte)2) >= 0)
     {
        byte pair = (byte)(Array.IndexOf(diceCount, (byte)2) + 1);
        byte highPair = (byte)(Array.LastIndexOf(diceCount, (byte)2) + 1);
        if (highPair != pair)
           return new RollScore(RollScoreType.TwoPair, highPair, pair);
        else
        {
           byte lowMissingDie = (byte)Array.IndexOf(diceCount, (byte)0);
           byte highMissingDie = (byte)Array.LastIndexOf(diceCount, (byte)0);
           switch (lowMissingDie)
           {
              case 0:
                 if (highMissingDie == 5)
                    return new RollScore(RollScoreType.PairSmallStriaght, 5, 4);
                 if (highMissingDie == 1)
                    return new RollScore(RollScoreType.PairSmallStriaght, 6, 5);
                 break;
              case 4:
                 return new RollScore(RollScoreType.PairSmallStriaght, 4, 3);
           }
           return new RollScore(RollScoreType.Pair, pair, (byte)(Array.LastIndexOf(diceCount, (byte)1) + 1));
        }
     }
     byte missingDie = (byte)Array.IndexOf(diceCount, (byte)0);
     switch(missingDie)
     {
        case 0:
           return new RollScore(RollScoreType.LargeStraight, 6, 5);
        case 1:
           return new RollScore(RollScoreType.SmallStright, 6, 5);
        case 4:
           return new RollScore(RollScoreType.SmallStright, 4, 3);
        case 5:
           return new RollScore(RollScoreType.LargeStraight, 5, 4);                  
        default:
           return new RollScore(RollScoreType.HighDie, 6, (byte)(Array.LastIndexOf(diceCount, (byte)1, 3) + 1));
     }
  }

К моему удивлению, я обнаружил, что вероятность выпадения малого стрита и большого стрита равны в 5-ти бросках. Это правда!?

РЕДАКТИРОВАТЬ: Исправлено; Я вижу, что, когда я включаю маленькие прямые, которые включают пару, вероятность маленькой прямой значительно возрастает.

Когда я думаю об этом, пара и маленький стрит, вероятно, должны использовать пару в качестве старшего кубика и наибольшее число в стрите в качестве следующего старшего (для того, чтобы [правильно сравнить два броска, которые являются парой с маленькая прямая). Если это так, я бы заменил блок кода для обработки PairSmallStraight следующим:

           switch (lowMissingDie)
           {
              case 0:
                 if (highMissingDie == 5)
                    return new RollScore(RollScoreType.PairSmallStriaght, pair, 5);
                 if (highMissingDie == 1)
                    return new RollScore(RollScoreType.PairSmallStriaght, pair, 6);
                 break;
              case 4:
                 return new RollScore(RollScoreType.PairSmallStriaght, pair, 4);
           }
0 голосов
/ 26 июня 2011

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

Поскольку у вас есть только 46656 возможных комбинаций и один байт может хранить полученную силу руки,эта проблема намного проще, чем проблема покерной руки.

У вас может быть таблица поиска, состоящая из рук в качестве индексов и связанных с результатами (у некоторых рук может быть несколько результатов) этой руки.Каждый байт может хранить все типы рук в двоичном представлении (надеюсь, если не использовать короткий).

Каждое полученное вами число (например, 66655 - фулл-хаус) - это число в базовой шестой (1-6)преобразуйте его в число 10, чтобы получить индекс в таблице поиска.

Потребуется около 46656 байт (+ выравнивание ЦП), и он может поместиться в кэш L2 ЦП.Скорость была бы огромной, поскольку единственная операция, которую вам нужно было бы выполнить, - это преобразование числовой базы и двоичная операция ИЛИ для извлечения прочности руки.

Что вы пропустите, так это реальную силу руки.Например.66655 лучше, чем 66644. Вы можете легко понять это - вам понадобится больший тип, чтобы сохранить результат в:)

0 голосов
/ 26 июня 2011

Вы всегда можете выполнить совокупный запрос LINQ и подсчитать количество одинаковых карт. Это было бы что-то похожее (не могу проверить это):

var query =  from card in hand
             group card by card into groupedCards
             select new { Card = groupedCards.Key, Count = groupedCards.Count() };

Таким образом, вы легко узнаете, имеете ли вы дело с возможным стритом (или ничем вообще), парой, тройкой и т. Д.

Я не LINQ эксперт, и я не могу сейчас протестировать этот бит кода, поэтому я не уверен, будет ли он компилироваться, как есть, но это может помочь вам или дать представление о том, как подойти проблема под рукой.

Например:

  1. if count query = 5: Мы имеем дело с пустой рукой, флешем или стритом => Запустить определенную логику флеша / стрита.

  2. если запрос количества = 4: мы имеем дело с одной парой.

  3. если запрос количества = 3: мы имеем дело с двойной парой или тройкой => если максимальное число = 3, то тройной

  4. if count query = 2: Мы имеем дело с фулл хаусом / покером. Если максимальное количество = 4, то покер

...