BlackjackPlayer.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // BlackjackPlayer.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Text;
  13. using CardsFramework;
  14. #endregion
  15. namespace Blackjack
  16. {
  17. /// <summary>
  18. /// Depicts hands the player can interact with.
  19. /// </summary>
  20. public enum HandTypes
  21. {
  22. First,
  23. Second
  24. }
  25. public class BlackjackPlayer : Player
  26. {
  27. #region Fields/Properties
  28. // Various fields which depict the state of the players two hands
  29. private int firstValue;
  30. private bool firstValueConsiderAce;
  31. private int secondValue;
  32. private bool secondValueConsiderAce;
  33. public bool Bust { get; set; }
  34. public bool SecondBust { get; set; }
  35. public bool BlackJack { get; set; }
  36. public bool SecondBlackJack { get; set; }
  37. public bool Double { get; set; }
  38. public bool SecondDouble { get; set; }
  39. public bool IsSplit { get; set; }
  40. public Hand SecondHand { get; private set; }
  41. /// <summary>
  42. /// The type of hand that the player is currently interacting with.
  43. /// </summary>
  44. public HandTypes CurrentHandType { get; set; }
  45. /// <summary>
  46. /// Returns the hand that the player is currently interacting with.
  47. /// </summary>
  48. public Hand CurrentHand
  49. {
  50. get
  51. {
  52. switch (CurrentHandType)
  53. {
  54. case HandTypes.First:
  55. return Hand;
  56. case HandTypes.Second:
  57. return SecondHand;
  58. default:
  59. throw new Exception("No hand to return");
  60. }
  61. }
  62. }
  63. public int FirstValue
  64. {
  65. get { return firstValue; }
  66. }
  67. public bool FirstValueConsiderAce
  68. {
  69. get { return firstValueConsiderAce; }
  70. }
  71. public int SecondValue
  72. {
  73. get { return secondValue; }
  74. }
  75. public bool SecondValueConsiderAce
  76. {
  77. get { return secondValueConsiderAce; }
  78. }
  79. public bool MadeBet { get { return BetAmount > 0; } }
  80. public bool IsDoneBetting { get; set; }
  81. public float Balance { get; set; }
  82. public float BetAmount { get; private set; }
  83. public bool IsInsurance { get; set; }
  84. #endregion
  85. /// <summary>
  86. /// Creates a new blackjack player instance.
  87. /// </summary>
  88. /// <param name="name">The player's name.</param>
  89. /// <param name="game">The game associated with the player.</param>
  90. public BlackjackPlayer(string name, CardsFramework.CardsGame game)
  91. : base(name, game)
  92. {
  93. Balance = 500;
  94. CurrentHandType = HandTypes.First;
  95. }
  96. /// <summary>
  97. /// Calculates the value represented by a specified hand.
  98. /// </summary>
  99. /// <param name="hand">The hand for which to calculate the value.</param>
  100. /// <param name="game">The associated game.</param>
  101. /// <param name="value">Will contain the hand's value. If the hand has two
  102. /// possible values due to it containing an ace, this will be the lower
  103. /// value.</param>
  104. /// <param name="considerAce">Whether or not an ace can be considered to
  105. /// make the hand have an alternative value.</param>
  106. private static void CalulateValue(Hand hand, CardsFramework.CardsGame game,
  107. out int value, out bool considerAce)
  108. {
  109. value = 0;
  110. considerAce = false;
  111. for (int cardIndex = 0; cardIndex < hand.Count; cardIndex++)
  112. {
  113. value += game.CardValue(hand[cardIndex]);
  114. if (hand[cardIndex].Value == CardValue.Ace)
  115. {
  116. considerAce = true;
  117. }
  118. }
  119. if (considerAce && value + 10 > 21)
  120. {
  121. considerAce = false;
  122. }
  123. }
  124. #region Public Methods
  125. /// <summary>
  126. /// Bets a specified amount of money, if the player's balance permits it.
  127. /// </summary>
  128. /// <param name="amount">The amount to bet.</param>
  129. /// <returns>True if the player has enough money to perform the bet, false
  130. /// otherwise.</returns>
  131. /// <remarks>The player's bet amount and balance are only updated if this
  132. /// method returns true.</remarks>
  133. public bool Bet(float amount)
  134. {
  135. if (amount > Balance)
  136. {
  137. return false;
  138. }
  139. BetAmount += amount;
  140. Balance -= amount;
  141. return true;
  142. }
  143. /// <summary>
  144. /// Resets the player's bet to 0, returning the current bet amount to
  145. /// the player's balance.
  146. /// </summary>
  147. public void ClearBet()
  148. {
  149. Balance += BetAmount;
  150. BetAmount = 0;
  151. }
  152. /// <summary>
  153. /// Calculates the values of the player's two hands.
  154. /// </summary>
  155. public void CalculateValues()
  156. {
  157. CalulateValue(Hand, Game, out firstValue, out firstValueConsiderAce);
  158. if (SecondHand != null)
  159. {
  160. CalulateValue(SecondHand, Game, out secondValue,
  161. out secondValueConsiderAce);
  162. }
  163. }
  164. /// <summary>
  165. /// Reset's the player's various state fields.
  166. /// </summary>
  167. public void ResetValues()
  168. {
  169. BlackJack = false;
  170. SecondBlackJack = false;
  171. Bust = false;
  172. SecondBust = false;
  173. Double = false;
  174. SecondDouble = false;
  175. firstValue = 0;
  176. firstValueConsiderAce = false;
  177. IsSplit = false;
  178. secondValue = 0;
  179. secondValueConsiderAce = false;
  180. BetAmount = 0;
  181. IsDoneBetting = false;
  182. IsInsurance = false;
  183. CurrentHandType = HandTypes.First;
  184. }
  185. /// <summary>
  186. /// Initializes the player's second hand.
  187. /// </summary>
  188. public void InitializeSecondHand()
  189. {
  190. SecondHand = new Hand();
  191. }
  192. /// <summary>
  193. /// Splits the player's current hand into two hands as per the blackjack rules.
  194. /// </summary>
  195. /// <exception cref="InvalidOperationException">Thrown if performing a split
  196. /// is not legal for the current player status.</exception>
  197. public void SplitHand()
  198. {
  199. if (SecondHand == null)
  200. {
  201. throw new InvalidOperationException("Second hand is not initialized.");
  202. }
  203. if (IsSplit == true)
  204. {
  205. throw new InvalidOperationException(
  206. "A hand cannot be split more than once.");
  207. }
  208. if (Hand.Count != 2)
  209. {
  210. throw new InvalidOperationException(
  211. "You must have two cards to perform a split.");
  212. }
  213. if (Hand[0].Value != Hand[1].Value)
  214. {
  215. throw new InvalidOperationException(
  216. "You can only split when both cards are of identical value.");
  217. }
  218. IsSplit = true;
  219. // Move the top card in the first hand to the second hand
  220. Hand[1].MoveToHand(SecondHand);
  221. }
  222. #endregion
  223. }
  224. }