public static void ShowPlayableHands(StrategyBase strategy, Canvas canvas, string savedImageName, string displayText) { // clear the screen canvas.Children.Clear(); Color hitColor = Colors.LightGreen, standColor = Color.FromRgb(252, 44, 44), doubleColor = Colors.Yellow, splitColor = Colors.MediumPurple; AddInformationalText(displayText, canvas); // display a grid for non-paired hands without an ace. One column for each possible dealer upcard AddColorBox(Colors.White, "", 0, 0, canvas); int x = 1, y = 0; foreach (var upcardRank in Card.ListOfRanks) { // strategy for 10, J, Q, and K are the same, so skip some of those if (upcardRank == Card.Ranks.Jack || upcardRank == Card.Ranks.Queen || upcardRank == Card.Ranks.King) { continue; } Card dealerUpcard = new Card(upcardRank, Card.Suits.Diamonds); string upcardRankName = Card.RankText(upcardRank); AddColorBox(Colors.White, upcardRankName, x, 0, canvas); y = 1; for (int hardTotal = 20; hardTotal > 4; hardTotal--) { // add a white box with the total AddColorBox(Colors.White, hardTotal.ToString(), 0, y, canvas); // build player hand Hand playerHand = new Hand(); // divide by 2 if it's even, else add one and divide by two int firstCardRank = ((hardTotal % 2) != 0) ? (hardTotal + 1) / 2 : hardTotal / 2; int secondCardRank = hardTotal - firstCardRank; if (firstCardRank == secondCardRank) { firstCardRank++; secondCardRank--; if (firstCardRank == 11) { // hard 20 needs to be three cards, so in this case 9, 4, 7 firstCardRank = 4; playerHand.AddCard(new Card(Card.Ranks.Seven, Card.Suits.Clubs)); } } playerHand.AddCard(new Card((Card.Ranks)firstCardRank, Card.Suits.Diamonds)); playerHand.AddCard(new Card((Card.Ranks)secondCardRank, Card.Suits.Hearts)); // get strategy and display var action = strategy.GetActionForHand(playerHand, dealerUpcard); switch (action) { case ActionToTake.Hit: AddColorBox(hitColor, "H", x, y, canvas); break; case ActionToTake.Stand: AddColorBox(standColor, "S", x, y, canvas); break; case ActionToTake.Double: AddColorBox(doubleColor, "D", x, y, canvas); break; } y++; } x++; } // and another for hands with an ace // display a grid for hands without an ace. One column for each possible dealer upcard const int leftColumnForAces = 12; AddColorBox(Colors.White, "", leftColumnForAces, 0, canvas); x = leftColumnForAces + 1; foreach (var upcardRank in Card.ListOfRanks) { // strategy for 10, J, Q, and K are the same, so skip some of those if (upcardRank == Card.Ranks.Jack || upcardRank == Card.Ranks.Queen || upcardRank == Card.Ranks.King) { continue; } string upcardRankName = Card.RankText(upcardRank); Card dealerUpcard = new Card(upcardRank, Card.Suits.Diamonds); AddColorBox(Colors.White, upcardRankName, x, 0, canvas); y = 1; // we don't start with Ace, because that would be AA, which is handled in the pair zone // we also don't start with 10, since that's blackjack. So 9 is our starting point // only need 2 through 9, since a-a is in the pairs table, and a-10 is blackjack for (var otherCard = Card.Ranks.Nine; otherCard >= Card.Ranks.Two; otherCard--) { // add a white box with the player hand: "A-x" string otherCardRank = Card.RankText(otherCard); AddColorBox(Colors.White, "A-" + otherCardRank, leftColumnForAces, y, canvas); // build player hand Hand playerHand = new Hand(); // first card is an ace, second card is looped over playerHand.AddCard(new Card(Card.Ranks.Ace, Card.Suits.Hearts)); // ace of hearts playerHand.AddCard(new Card(otherCard, Card.Suits.Spades)); // get strategy and display var action = strategy.GetActionForHand(playerHand, dealerUpcard); switch (action) { case ActionToTake.Hit: AddColorBox(hitColor, "H", x, y, canvas); break; case ActionToTake.Stand: AddColorBox(standColor, "S", x, y, canvas); break; case ActionToTake.Double: AddColorBox(doubleColor, "D", x, y, canvas); break; } y++; } x++; } // finally, a grid for pairs int startY = y + 1; AddColorBox(Colors.White, "", leftColumnForAces, startY, canvas); x = leftColumnForAces + 1; foreach (var upcardRank in Card.ListOfRanks) { // strategy for 10, J, Q, and K are the same, so skip some of those if (upcardRank == Card.Ranks.Jack || upcardRank == Card.Ranks.Queen || upcardRank == Card.Ranks.King) { continue; } string upcardRankName = Card.RankText(upcardRank); Card dealerUpcard = new Card(upcardRank, Card.Suits.Diamonds); AddColorBox(Colors.White, upcardRankName, x, startY, canvas); y = startY + 1; for (var pairedRank = Card.Ranks.Ace; pairedRank >= Card.Ranks.Two; pairedRank--) { // strategy for 10, J, Q, and K are the same, so skip some of those if (pairedRank == Card.Ranks.Jack || pairedRank == Card.Ranks.Queen || pairedRank == Card.Ranks.King) { continue; } // add a white box with the player hand: "x-x" string pairedCardRank = Card.RankText(pairedRank); AddColorBox(Colors.White, pairedCardRank + "-" + pairedCardRank, leftColumnForAces, y, canvas); // build player hand Hand playerHand = new Hand(); playerHand.AddCard(new Card(pairedRank, Card.Suits.Hearts)); // X of hearts playerHand.AddCard(new Card(pairedRank, Card.Suits.Spades)); // X of spades // get strategy and display var action = strategy.GetActionForHand(playerHand, dealerUpcard); switch (action) { case ActionToTake.Hit: AddColorBox(hitColor, "H", x, y, canvas); break; case ActionToTake.Stand: AddColorBox(standColor, "S", x, y, canvas); break; case ActionToTake.Double: AddColorBox(doubleColor, "D", x, y, canvas); break; case ActionToTake.Split: AddColorBox(splitColor, "P", x, y, canvas); break; } y++; } x++; } // now that's it's drawn, save an image? if (!string.IsNullOrEmpty(savedImageName)) { SaveCanvasToPng(canvas, savedImageName); } }