Created
July 25, 2016 01:33
-
-
Save c9952594/35f9b2a418975e0499d92bc1aebe0756 to your computer and use it in GitHub Desktop.
An implementation of the BlackJack Helper coding challenge on CoderRadio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using NUnit.Framework; | |
/* Slightly more logic to implement the implicit rules | |
* | |
* Program expects a single string as the input | |
* The first character is the dealers card the rest are the players cards | |
* | |
* Example: BlackJack Helper.exe 43T5 | |
* Dealer has a 4 | |
* Player has a 3 and a Ten and a Five | |
*/ | |
namespace Blackjack_Helper { | |
class Program { | |
public const string Hit = "Hit"; | |
public const string Stand = "Stand"; | |
public const string Double = "Double if allowed, otherwise Hit"; | |
public const string DoubleStand = "Double if allowed, otherwise Stand"; | |
public const string Split = "Split"; | |
public const string SurrenderOrHit = "Surrender if allowed, otherwise Hit"; | |
public const string SurrenderOrSplit = "Surrender if allowed, otherwise Split"; | |
public const string SurrenderOrStand = "Surrender if allowed, otherwise Stand"; | |
public const string HelpText = "[Dealer card][Players cards]. Cards = 2,3,4,5,6,7,8,9,T,A"; | |
static void Main(string[] args) | |
{ | |
new Program(Console.In, Console.Out); | |
} | |
public Program(TextReader input, TextWriter output) | |
{ | |
var cards = input.ReadLine(); | |
if (cards == null || cards.Length < 3) { | |
output.Write(HelpText); | |
return; | |
} | |
var dealersIndex = new List<char> { '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'A' }.IndexOf(cards.First()); | |
var playersHand = new Hand(cards.Substring(1)); | |
var rule = FindRule(playersHand, dealersIndex); | |
output.Write(rule); | |
} | |
private string FindRule(Hand playersHand, int dealersIndex) | |
{ | |
if (playersHand.CanSplit) | |
return FindSplitRule(playersHand, dealersIndex); | |
if (playersHand.IsSoft) | |
return FindSoftRule(playersHand, dealersIndex); | |
return FindNormalRule(playersHand, dealersIndex); | |
} | |
private static string FindSplitRule(Hand playersHand, int dealersIndex) | |
{ | |
return new Dictionary<int, string[]>() | |
{ | |
[2] = new[] { Split, Split, Split, Split, Split, Split, Split, Split, Split, Split }, | |
[4] = new[] { Split, Split, Split, Split, Split, Split, Hit, Hit, Hit, Hit }, | |
[6] = new[] { Split, Split, Split, Split, Split, Split, Hit, Hit, Hit, Hit }, | |
[8] = new[] { Hit, Hit, Hit, Split, Split, Hit, Hit, Hit, Hit, Hit }, | |
[10] = new[] { Double, Double, Double, Double, Double, Double, Double, Double, Hit, Hit }, | |
[12] = new[] { Split, Split, Split, Split, Split, Hit, Hit, Hit, Hit, Hit }, | |
[14] = new[] { Split, Split, Split, Split, Split, Split, Hit, Hit, Hit, Hit }, | |
[16] = new[] { Split, Split, Split, Split, Split, Split, Split, Split, Split, SurrenderOrSplit }, | |
[19] = new[] { Split, Split, Split, Split, Split, Stand, Split, Split, Stand, Stand }, | |
[20] = new[] { Stand, Stand, Stand, Stand, Stand, Stand, Stand, Stand, Stand, Stand } | |
}[playersHand.Value][dealersIndex]; | |
} | |
private static string FindSoftRule(Hand playersHand, int dealersIndex) | |
{ | |
return new Dictionary<int, string[]> | |
{ | |
[3] = new[] { Hit, Hit, Hit, Double, Double, Hit, Hit, Hit, Hit, Hit }, | |
[4] = new[] { Hit, Hit, Hit, Double, Double, Hit, Hit, Hit, Hit, Hit }, | |
[5] = new[] { Hit, Hit, Double, Double, Double, Hit, Hit, Hit, Hit, Hit }, | |
[6] = new[] { Hit, Hit, Double, Double, Double, Hit, Hit, Hit, Hit, Hit }, | |
[7] = new[] { Hit, Double, Double, Double, Double, Hit, Hit, Hit, Hit, Hit }, | |
[8] = new[] { Stand, DoubleStand, DoubleStand, DoubleStand, DoubleStand, Stand, Stand, Hit, Hit, Hit } | |
}[playersHand.Value][dealersIndex]; | |
} | |
private static string FindNormalRule(Hand playersHand, int dealersIndex) | |
{ | |
if (playersHand.Value < 8) return Hit; | |
if (playersHand.Value >= 17) return Stand; | |
return new Dictionary<int, string[]> | |
{ | |
[8] = new[] { Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit }, | |
[9] = new[] { Hit, Double, Double, Double, Double, Hit, Hit, Hit, Hit, Hit }, | |
[10] = new[] { Double, Double, Double, Double, Double, Double, Double, Double, Hit, Hit }, | |
[11] = new[] { Double, Double, Double, Double, Double, Double, Double, Double, Double, Double }, | |
[12] = new[] { Hit, Hit, Stand, Stand, Stand, Hit, Hit, Hit, Hit, Hit }, | |
[13] = new[] { Stand, Stand, Stand, Stand, Stand, Hit, Hit, Hit, Hit, Hit }, | |
[14] = new[] { Stand, Stand, Stand, Stand, Stand, Hit, Hit, Hit, Hit, Hit }, | |
[15] = new[] { Stand, Stand, Stand, Stand, Stand, Hit, Hit, Hit, SurrenderOrHit, SurrenderOrHit }, | |
[16] = new[] { Stand, Stand, Stand, Stand, Stand, Hit, Hit, SurrenderOrHit, SurrenderOrHit, SurrenderOrHit }, | |
[17] = new[] { Stand, Stand, Stand, Stand, Stand, Stand, Stand, Stand, Stand, SurrenderOrStand } | |
}[playersHand.Value][dealersIndex]; | |
} | |
} | |
class Hand { | |
private readonly string _hand; | |
private readonly int _softValue; | |
private readonly int _hardValue; | |
public Hand(string hand) | |
{ | |
_hand = hand.ToUpper(); | |
var values = CalculateHandValue(hand); | |
_softValue = values.Item1; | |
_hardValue = values.Item2; | |
} | |
private Tuple<int, int> CalculateHandValue(string hand) | |
{ | |
var aces = hand.Count(m => m == 'A'); | |
var hard = hand.ToCharArray().Sum(c => { | |
if (c == 'A') return 11; | |
if (c == 'T') return 10; | |
return (int)char.GetNumericValue(c); | |
}); | |
var soft = hard - (aces * 10); | |
while (hard > 21 && aces-- > 0) | |
hard -= 10; | |
return Tuple.Create(soft, hard); | |
} | |
public bool CanSplit => _hand.Length == 2 && _hand.All(card => card == _hand.First()); | |
public bool IsSoft => _softValue <= 8 && _softValue != _hardValue; | |
public int Value => IsSoft ? _softValue : _hardValue; | |
} | |
public class Tests { | |
// 12 | |
[TestCase("248", Program.Hit)] | |
[TestCase("557", Program.Stand)] | |
// 15 | |
[TestCase("TT5", Program.SurrenderOrHit)] | |
[TestCase("T5T", Program.SurrenderOrHit)] | |
// Soft | |
[TestCase("3A7", Program.DoubleStand)] | |
[TestCase("3A34", Program.DoubleStand)] | |
[TestCase("342AA", Program.DoubleStand)] | |
[TestCase("37A", Program.DoubleStand)] | |
[TestCase("38A", Program.Stand)] | |
// Split (12) | |
[TestCase("566", Program.Split)] | |
public void HappyPath(string input, string expectedOutput) | |
{ | |
TextReader inputStream = new StringReader(input); | |
TextWriter outputStream = new StringWriter(new StringBuilder()); | |
new Program(inputStream, outputStream); | |
Assert.That(outputStream.ToString(), Is.EqualTo(expectedOutput)); | |
} | |
[TestCase("")] | |
[TestCase("AA")] | |
[TestCase("/?")] | |
public void IncorrectInput(string input) | |
{ | |
HappyPath(input, Program.HelpText); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment