コード例 #1
0
        //private void anon(object target)
        //{
        //    Dictionary<string, int> handTypeCount = new Dictionary<string, int>() { { "High Card", 0 }, { "Pair", 0 }, { "Two Pair", 0 }, { "Three of a Kind", 0 }, { "Straight", 0 }, { "Flush", 0 }, { "Full House", 0 }, { "Four of a Kind", 0 }, { "Straight Flush", 0 }, { "Royal Flush", 0 } };

        //    Tuple<List<int>, List<int>, int[], Hashtable> param = (Tuple<List<int>, List<int>, int[], Hashtable>)target;

        //    foreach (string hand in CardUtilities.enumeratePossibleHands(param.Item1,param.Item2,param.Item3))
        //        {
        //            handTypeCount[hand]++;
        //        }
        //    lock (param.Item4)
        //    {
        //        param.Item4.Add(param.Item3, handTypeCount);
        //    }
        //}

        private void anon(object target)
        {
            Dictionary <string, int> handTypeCount;
            Tuple <List <int>, List <int>, int[], Hashtable> param;

            //Loop until the concurrent stack has been removed
            while (workerThreadQueue != null)
            {
                //try to pop from the stack
                if (workerThreadQueue.TryDequeue(out param))
                {
                    handTypeCount = new Dictionary <string, int>()
                    {
                        { "High Card", 0 }, { "Pair", 0 }, { "Jacks or Better", 0 }, { "Two Pair", 0 }, { "Three of a Kind", 0 }, { "Straight", 0 }, { "Flush", 0 }, { "Full House", 0 }, { "Four of a Kind", 0 }, { "Straight Flush", 0 }, { "Royal Flush", 0 }
                    };

                    if (param == null)
                    {
                        break;
                    }

                    //if you suceed in poping then calculate all the hand details
                    foreach (string hand in CardUtilities.enumeratePossibleHands(param.Item1, param.Item2, param.Item3))
                    {
                        handTypeCount[hand]++;
                    }
                    lock (param.Item4)
                    {
                        param.Item4.Add(param.Item3, handTypeCount);
                    }
                }
            }
        }
コード例 #2
0
        private void initialiseHandTypeLabels()
        {
            //if one is null they both should be
            if (handTypeLabels == null)
            {
                handTypeLabels = new Dictionary <string, Label>()
                {
                    { CardUtilities.getHandValueName(0), lbl_HighCards }, { CardUtilities.getHandValueName(1), lbl_Pairs }, { CardUtilities.getHandValueName(2), lbl_jacksOrBetter }, { CardUtilities.getHandValueName(3), lbl_TwoPairs }, { CardUtilities.getHandValueName(4), lbl_Triple }, { CardUtilities.getHandValueName(5), lbl_Straight }, { CardUtilities.getHandValueName(6), lbl_Flush }, { CardUtilities.getHandValueName(7), lbl_FullHouse }, { CardUtilities.getHandValueName(8), lbl_FourOfAKind }, { CardUtilities.getHandValueName(9), lbl_StraightFlush }, { CardUtilities.getHandValueName(10), lbl_RoyalFlush }
                };
                handTypeCountLabels = new Dictionary <string, Label>()
                {
                    { CardUtilities.getHandValueName(0), lbl_HighCardsCount }, { CardUtilities.getHandValueName(1), lbl_PairsCount }, { CardUtilities.getHandValueName(2), lbl_jacksOrBetterCount }, { CardUtilities.getHandValueName(3), lbl_TwoPairsCount }, { CardUtilities.getHandValueName(4), lbl_TripleCount }, { CardUtilities.getHandValueName(5), lbl_StraightCount }, { CardUtilities.getHandValueName(6), lbl_FlushCount }, { CardUtilities.getHandValueName(7), lbl_FullHouseCount }, { CardUtilities.getHandValueName(8), lbl_FourOfAKindCount }, { CardUtilities.getHandValueName(9), lbl_StraightFlushCount }, { CardUtilities.getHandValueName(10), lbl_RoyalFlushCount }
                };
            }
            //high card,lowpair,jack+ pair,2pair
            int[]  initialProbabilities = new int[] { 1302540, 760320, 337920, 123552, 54912, 10200, 5108, 3744, 624, 36, 4 };
            double total = initialProbabilities.Sum();

            int i = 0;

            foreach (var pair in handTypeLabels)
            {
                handTypeLabels[pair.Key].Content         = CardUtilities.getHandValueName(i);// +(CardUtilities.getHandValueName(i).Contains("Flush") ? "es" : "s"); //If you want to pluralise
                handTypeCountLabels[pair.Key].Content    = handTypeCountLabels[pair.Key].Content = string.Format("%{0:0.00}", ((initialProbabilities[i]) / total * 100));
                handTypeCountLabels[pair.Key].Foreground = new SolidColorBrush(Colors.Black);
                handTypeLabels[pair.Key].Foreground      = new SolidColorBrush(Colors.Black);
                i++;
            }
        }
コード例 #3
0
 private void resetDeckContent(int totalDecks = 1)
 {
     deckContent = new List <string>();
     for (int deck = 0; deck < totalDecks; deck++)
     {
         for (int card = 0; card < 52; card++)
         {
             deckContent.Add(CardUtilities.convertToStringCard(card));
         }
     }
 }
コード例 #4
0
 private bool checkAssendingPayoffs()
 {
     for (int i = 1; i < payoffTable.Count; i++)
     {
         if (payoffTable[CardUtilities.getHandValueName(i)] < payoffTable[CardUtilities.getHandValueName(i - 1)])
         {
             MessageBoxResult output = MessageBox.Show("Your payoff table is not in ascending order, \nyou can continue and potentially get some \nbizzarre results, or stop now and fix it.\n\nContinue?", "Non-ascending payoffs", MessageBoxButton.YesNo);
             return(output == MessageBoxResult.Yes);
         }
     }
     return(true);
 }
コード例 #5
0
        /// <summary>
        /// This method sorts the clone of the deck based on the Face value rather than the integer value of the cards.
        /// This means that the decks clones order (which always starts as something like 1..2...5...14..33..51) will altered to
        /// Go from least valuable card (2) to most valuable card (A). This is usefull as if one wants to perform multiple
        /// operations based on variable sorted hands it odoesn't make sense to have to sort each hand individually.
        /// In short, this is a method for effiency of operation.
        /// </summary>
        /// <returns>Returns an integer valued list</returns>
        public static List <int> createSortedCloneOfDeck(List <string> deckContent)
        {
            var clone = new List <int>();

            //populate new list with the converted string cards
            foreach (var stringCard in deckContent)
            {
                clone.Add(CardUtilities.convertFromStringCard(stringCard));
            }

            clone.Sort(CardUtilities.NumberCardComparer);
            return(clone);
        }
コード例 #6
0
        /// <summary>
        /// Does exactly what the name implies: it updates the apperance of the 5 hand card labels to reflect what the user is holding
        /// </summary>
        private void updateHandDisplay()
        {
            //a safety check
            if (handCards == null)
            {
                handCards = new List <int> {
                    -1, -1, -1, -1, -1
                }
            }
            ;

            for (int i = 0; i < handLabels.Count; i++)
            {
                handLabels[i].Content    = CardUtilities.convertToStringCard(handCards[i]);
                handLabels[i].Foreground = new SolidColorBrush(getCardColour(handCards[i]));
            }
        }
コード例 #7
0
        private void initializePayoffTable()
        {
            for (int i = 0; i < payoffTableBoxes.Count; i++)
            {
                if (payoffTableBoxes[i].Text == "")
                {
                    payoffTableBoxes[i].Text = "0";
                }

                double temp;
                if (double.TryParse(payoffTableBoxes[i].Text, out temp))
                {
                    payoffTable[CardUtilities.getHandValueName(i)] = temp;
                }
                else
                {
                    payoffTableBoxes[i].Text = "0";
                    payoffTable[CardUtilities.getHandValueName(i)] = 0;
                }
            }
        }
コード例 #8
0
        private void initialiseHandLabels()
        {
            handLabels = new List <Label>()
            {
                lbl_Hand1, lbl_Hand2, lbl_Hand3, lbl_Hand4, lbl_Hand5
            };
            foreach (Label lbl in handLabels)
            {
                lbl.MouseUp += new MouseButtonEventHandler((object sender, MouseButtonEventArgs e) =>
                {
                    if (e.ChangedButton == MouseButton.Left || e.ChangedButton == MouseButton.Right)
                    {
                        int x = CardUtilities.convertFromStringCard(((Label)sender).Content.ToString());
                        if (handCards.Contains(x))
                        {
                            Label deckLabel = getLabel(((Label)sender).Content.ToString());
                            if (deckLabel == null)
                            {
                                return;
                            }

                            // if (deckLabel.Content.ToString()[1] == '♥' || deckLabel.Content.ToString()[1] == '♦')
                            //     deckLabel.Foreground = new SolidColorBrush(Colors.Red);
                            // else
                            //     deckLabel.Foreground = new SolidColorBrush(Colors.Black);

                            handCards.Remove(x);
                            handCards.Add(-1);
                            //deckContent.Add(((Label)sender).Content.ToString());

                            updateHandDisplay();

                            setForHandState(false);
                        }
                        return;
                    }
                });
            }
        }
コード例 #9
0
        /// <summary>
        /// Sets the states of the various GUI components based on whether the hand is full or not.
        /// For example it disabled all the buttons until the hand is full.
        /// </summary>
        /// <param name="isCompleteHand"></param>
        private void setForHandState(bool isCompleteHand)
        {
            Button[] buttons = new Button[] { btn_Calculate, btn_SpecificMask, btn_Card1Holding, btn_Card2Holding, btn_Card3Holding, btn_Card4Holding, btn_Card5Holding };
            foreach (var btn in buttons)
            {
                btn.IsEnabled = isCompleteHand;
            }

            lbl_HandType.Content = isCompleteHand ? CardUtilities.getHandValueName(CardUtilities.getSortedHandValue(handCards)) : "";

            lbl_Instructions.Content = isCompleteHand ? "Click other cards you want removed from the deck." : "Click the cards you want to draw.";

            lbl_decrease.Content    = "Uncalulated chance of value decreasing";
            lbl_increase.Content    = "Uncalulated chance of value increasing";
            lbl_betterStart.Content = "Uncalulated chance of better starting hand";
            lbl_returnRate.Content  = "Uncalulated estimated return rate";


            if (!isCompleteHand)
            {
                initialiseHandTypeLabels();
            }
        }
コード例 #10
0
        /// <summary>
        /// Adds a new card to the hand, sorts the hand, and updates the display to reflects the hands new state
        /// </summary>
        /// <param name="card"></param>
        private void passCardToHand(string card)
        {
            if (handCards == null)
            {
                handCards = new List <int> {
                    -1, -1, -1, -1, -1
                }
            }
            ;                                              //fill it will illegal card values


            for (int i = 0; i < handCards.Count; i++)
            {
                if (handCards[i] == -1)
                {
                    handCards[i] = CardUtilities.convertFromStringCard(card);
                    break;
                }
            }

            handCards.Sort(CardUtilities.NumberCardComparer);

            updateHandDisplay();
        }
コード例 #11
0
        private void cardLabelClicked(object sender, MouseButtonEventArgs e)
        {
            //This code will be executed when the new label is clicked - we want it to remove a card from the deck upon left cliking, right click will replace removed ones
            if (e.ChangedButton == MouseButton.Left)
            {
                //check if there are any still to be removed
                if (deckContent.Contains(((Label)sender).Content.ToString()))
                {
                    deckContent.Remove(((Label)sender).Content.ToString()); //and remove one if there is
                    passCardToHand(((Label)sender).Content.ToString());
                }

                //check if there none left and grey out if there are
                if (!deckContent.Contains(((Label)sender).Content.ToString()))
                {
                    ((Label)sender).Foreground = new SolidColorBrush(Colors.Gray);
                }

                if (handCards[4] != -1)
                {
                    lbl_HandType.Content = CardUtilities.getHandValueName(CardUtilities.getSortedHandValue(handCards));
                    setForHandState(true);
                }
                else
                {
                    setForHandState(false);
                }

                return;
            }

            //Put the card back in the deck if it was missing
            if (e.ChangedButton == MouseButton.Right)
            {
                //change the colour back to normal
                if (((Label)sender).Content.ToString()[1] == '♥' || ((Label)sender).Content.ToString()[1] == '♦')
                {
                    ((Label)sender).Foreground = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    ((Label)sender).Foreground = new SolidColorBrush(Colors.Black);
                }

                //Check if the hand is holding a given card, and remove it from the hand if it is
                int x = CardUtilities.convertFromStringCard(((Label)sender).Content.ToString());
                if (handCards.Contains(x))
                {
                    handCards.Remove(x);
                    handCards.Add(-1);
                    deckContent.Add(((Label)sender).Content.ToString());
                    updateHandDisplay();
                }

                //if the card is missing from the deck replace it
                if (!deckContent.Contains(((Label)sender).Content.ToString()))
                {
                    deckContent.Add(((Label)sender).Content.ToString());
                }
                btn_Calculate.IsEnabled    = false;
                btn_SpecificMask.IsEnabled = false;
                lbl_HandType.Content       = "";
            }
        }
コード例 #12
0
        /// <summary>
        /// Calculates all the odds for the current state. If you leave chosenMask as null the optimal strategy will be calculated and used
        /// </summary>
        /// <param name="chosenMask"></param>
        private void calculateAndDisplayProbabilities(int[] chosenMask = null)
        {
            //http://www.durangobill.com/VideoPoker.html

            //calculate the value of the hand ONCE so that we don't have to redo it for each comparison;
            string currentHandType = CardUtilities.getHandName(handCards);

            //Go through (and count the types of) every set of drawable cards, given the current discard values

            DateTime start = DateTime.Now;

            List <int> sortedDeckClone = CardUtilities.createSortedCloneOfDeck(deckContent);
            Hashtable  hashedResults   = new Hashtable();

            Thread[] workers = new Thread[4];

            if (chosenMask == null)
            {
                workerThreadQueue = new ConcurrentQueue <Tuple <List <int>, List <int>, int[], Hashtable> >();

                workers[0] = new Thread(new ParameterizedThreadStart(anon));
                workers[1] = new Thread(new ParameterizedThreadStart(anon));
                workers[2] = new Thread(new ParameterizedThreadStart(anon));
                workers[3] = new Thread(new ParameterizedThreadStart(anon));

                foreach (var maskQuad in CardUtilities.enumerateHandMasks_ThreadVersion())
                {
                    try
                    {
                        workerThreadQueue.Enqueue(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item1, hashedResults));
                        workerThreadQueue.Enqueue(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item2, hashedResults));
                        workerThreadQueue.Enqueue(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item3, hashedResults));
                        workerThreadQueue.Enqueue(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item4, hashedResults));

                        if (workers[0].ThreadState == ThreadState.Unstarted)
                        {                                                            //hand,    deck  , mask, Storage_hashTable
                            workers[0].Start(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item1, hashedResults));
                            workers[1].Start(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item2, hashedResults));
                            workers[2].Start(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item3, hashedResults));
                            workers[3].Start(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item4, hashedResults));
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }

                workerThreadQueue.Enqueue(null);
                workerThreadQueue.Enqueue(null);
                workerThreadQueue.Enqueue(null);
                workerThreadQueue.Enqueue(null);

                workers[0].Join();
                workers[1].Join();
                workers[2].Join();
                workers[3].Join();
                Console.WriteLine(DateTime.Now.Subtract(start).ToString());

                if (workerThreadQueue.Count != 0)
                {
                    throw new Exception();
                }
                else
                {
                    workerThreadQueue = null;
                }
            }
            else //This else occurs when the user wants to know about a SPECIFIC mask, not neccessarily the optimal one
            {
                //Do the chosen mask of the user
                Dictionary <string, int> handTypeCount = new Dictionary <string, int>()
                {
                    { "High Card", 0 }, { "Pair", 0 }, { "Jacks or Better", 0 }, { "Two Pair", 0 }, { "Three of a Kind", 0 }, { "Straight", 0 }, { "Flush", 0 }, { "Full House", 0 }, { "Four of a Kind", 0 }, { "Straight Flush", 0 }, { "Royal Flush", 0 }
                };

                foreach (string hand in CardUtilities.enumeratePossibleHands(handCards, sortedDeckClone, chosenMask))
                {
                    handTypeCount[hand]++;
                }

                hashedResults.Add(chosenMask, handTypeCount);

                //Compute the draw all mask, that we use for opponent draw odds
                if (!(chosenMask[0] == 0 && chosenMask[0] == chosenMask[1] && chosenMask[1] == chosenMask[2] && chosenMask[2] == chosenMask[3] && chosenMask[3] == chosenMask[4]))
                {
                    handTypeCount = new Dictionary <string, int>()
                    {
                        { "High Card", 0 }, { "Pair", 0 }, { "Jacks or Better", 0 }, { "Two Pair", 0 }, { "Three of a Kind", 0 }, { "Straight", 0 }, { "Flush", 0 }, { "Full House", 0 }, { "Four of a Kind", 0 }, { "Straight Flush", 0 }, { "Royal Flush", 0 }
                    };

                    int[] drawAll = new int[] { 0, 0, 0, 0, 0 };
                    foreach (string hand in CardUtilities.enumeratePossibleHands(handCards, sortedDeckClone, drawAll))
                    {
                        handTypeCount[hand]++;
                    }

                    hashedResults.Add(drawAll, handTypeCount);
                }
            }

            //By this stage we have the raw count data.
            //Next thing is to use that data to find optimal strageies and caluclate the odds

            List <int[]> bestMasks = new List <int[]>()
            {
                new int[] { 1, 1, 1, 1, 1 }
            };

            int[] factorials = { 1, 2, 6, 24, 120 };

            double highestExpected = 0;

            ///Keeps track of how many tied hand masks there are
            int tiedMasks = 0;


            foreach (var singleResult in hashedResults)
            {
                double runningTotal = 0;
                double top          = sortedDeckClone.Count;
                int    draws        = 5 - ((int[])((DictionaryEntry)singleResult).Key).Sum();

                for (int i = 1; i < draws; i++)
                {
                    top = top * (sortedDeckClone.Count - i);
                }

                if (draws == 0)
                {
                    if (highestExpected < payoffTable[currentHandType])
                    {
                        highestExpected = payoffTable[currentHandType];
                        bestMasks       = new List <int[]>()
                        {
                            (int[])((DictionaryEntry)singleResult).Key
                        };                                                                         //= (int[])((DictionaryEntry)singleResult).Key;
                    }
                    continue;
                }

                foreach (var pair in ((Dictionary <string, int>)((DictionaryEntry)singleResult).Value))
                {
                    runningTotal += (payoffTable[pair.Key] * pair.Value);
                }



                if (highestExpected == runningTotal / (top / factorials[draws - 1]))
                {
                    tiedMasks++;
                    bestMasks.Add((int[])((DictionaryEntry)singleResult).Key);
                }

                if (draws > 0 && highestExpected < runningTotal / (top / factorials[draws - 1]))
                {
                    tiedMasks       = 0;
                    highestExpected = runningTotal / (top / factorials[draws - 1]);
                    bestMasks       = new List <int[]>()
                    {
                        (int[])((DictionaryEntry)singleResult).Key
                    };
                }
            }

            //Once here, we have an optimal strategy selected (or the users selected mask)

            double weaker = 0, tied = -1, better = 0;

            int[] drawAllMask = null;
            //We need to find the reference to the actual list on the hashtable ([0,0,0,0,0])
            foreach (int[] key in hashedResults.Keys)
            {
                if (key[0] == 0 && key[0] == key[1] && key[1] == key[2] && key[2] == key[3] && key[3] == key[4])
                {
                    drawAllMask = key;
                    break;
                }
            }

            foreach (var type in (Dictionary <string, int>)hashedResults[drawAllMask])
            {
                //are we still adding values to weaker and tied?
                if (tied == -1)
                {
                    if (type.Key == currentHandType)
                    {
                        tied = type.Value;
                    }
                    else
                    {
                        weaker += type.Value;
                    }
                    continue;
                }

                //Getting here means that tied is greater than -1 (so we must be adding to better from here on)
                better += type.Value;
            }

            Console.WriteLine("Opponents have a %{0:0.000} of starting with a BETTER hand than what you have", (better / (tied + weaker)) * 100);

            ///Alter this to find the highest held card various masks and display that
            foreach (var mask in bestMasks)
            {
                foreach (var elem in mask)
                {
                    Console.Write(elem);
                }
                Console.WriteLine();
            }


            btn_Card1Holding.Content = bestMasks[0][0] == 1 ? "Hold" : "Draw";
            btn_Card2Holding.Content = bestMasks[0][1] == 1 ? "Hold" : "Draw";
            btn_Card3Holding.Content = bestMasks[0][2] == 1 ? "Hold" : "Draw";
            btn_Card4Holding.Content = bestMasks[0][3] == 1 ? "Hold" : "Draw";
            btn_Card5Holding.Content = bestMasks[0][4] == 1 ? "Hold" : "Draw";

            Console.WriteLine("Optimal return rate- " + highestExpected);
            Console.WriteLine("ties identical masks" + tiedMasks);

            Console.WriteLine(DateTime.Now.Subtract(start).ToString());

            int betterHands = 0;
            int tiedHands   = -1;
            int worseHands  = 0;

            foreach (var pair in (Dictionary <string, int>)hashedResults[bestMasks[0]])
            {
                if (pair.Key == currentHandType)
                {
                    tiedHands = pair.Value;
                    handTypeCountLabels[pair.Key].Foreground = new SolidColorBrush(Colors.Blue);
                    handTypeLabels[pair.Key].Foreground      = new SolidColorBrush(Colors.Blue);
                }
                else
                if (tiedHands == -1)
                {
                    worseHands += pair.Value;
                    handTypeCountLabels[pair.Key].Foreground = new SolidColorBrush(Colors.Red);
                    handTypeLabels[pair.Key].Foreground      = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    betterHands += pair.Value;
                    handTypeCountLabels[pair.Key].Foreground = new SolidColorBrush(Colors.Green);
                    handTypeLabels[pair.Key].Foreground      = new SolidColorBrush(Colors.Green);
                }
            }

            double totalHands = betterHands + tiedHands + worseHands;

            foreach (var pair in (Dictionary <string, int>)hashedResults[bestMasks[0]])
            {
                //The flow direction property of labels causes weird positioning of special charachters: special symols seem to go to the opposite side you place them O_o when using "RightToLeft"
                if (totalHands == 0)
                {
                    if (pair.Key != currentHandType)
                    {
                        handTypeCountLabels[pair.Key].Content = "%0.00";
                    }
                    else
                    {
                        handTypeCountLabels[pair.Key].Content = "%100.00";
                    }
                }
                else
                {
                    double chance = (pair.Value / (totalHands) * 100);
                    if (chance != 0 && chance < 0.01)
                    {
                        handTypeCountLabels[pair.Key].Content = "%0.01>";
                    }
                    else
                    {
                        handTypeCountLabels[pair.Key].Content = string.Format("%{0:0.00}", (pair.Value / (totalHands) * 100));
                    }
                }
            }

            lbl_decrease.Content    = string.Format("{0:0.0%} chance of value decreasing", worseHands / totalHands);
            lbl_increase.Content    = string.Format("{0:0.0%} chance of value increasing", betterHands / totalHands);
            lbl_returnRate.Content  = string.Format("{0:0.0%} estimated return rate", highestExpected);
            lbl_betterStart.Content = string.Format("{0:0.0%} chance of better starting hand", (better / (tied + weaker)));
        }