c# poker game [B] Let the user replace one of their cards in their hand, and aut
ID: 3902284 • Letter: C
Question
c# poker game
[B] Let the user replace one of their cards in their hand, and auto-replace a low card in the computer's hand [C] Recognize if entire hand is all the same suit (a "flush"), and treat that as a winning hand In this assignment, we will be working on part B which lets user replace one of their cards in their hand, and auto-replace a low card in the computer's hand. Read the document carefully to make sure you have implemented everything required The Goal We want to allow the user and the computer to replace one card to improve their hand before deciding who won Implementation Steps: 1) First add a new method in Cardset class called GetOneCard that will be used by the user to replace one card public SuperCard GetOneCard) // gets one card from the deck of 52. Using very similar code to your GetCards method, add this new method. It must have similar logic to make sure the card it returns is not already in use, and it must set the property of the card it returns to be true. Note also that this method returns a single SuperCard, and not an array of cards as is done in GetCards method. In program.cs, implement a new method called PlayerDrawsOne that allows the user to replace one of the cards if the user wants to: public void PlayerDrawsOne (SuperCard[] hand, CardSet deck) Start by asking the user which card they want to replace, and allow them to type 1,2,3,4 or 5, etc, which is to indicate which card they want to replace, or they can enter a O if they don't want to change any card. If they do want to change a card, call your new GetOneCard method to get a new card, and replace that one card object in their hand array corresponding to the number they selected. Remember, arrays are "by reference" types, so when you pass in the array to the PlayerDrawsOne method, and the method modifies the hand array there, you don't have to return anything, as the original hand array is now modified too. Also note, if for example they say they want to replace their 3rd card, you should replace the card at index 2, since arrays are zero-index based In program.cs, in the main game loop, right after the cards for the player are displayed, call the new method PlayerDrawsOne passing the player's hand and myDeck field of type Cardset. 2) 3) Get this working before going forward. You should be able to play the game, and pick any of your cards to be replaced, or select a 0 and replace none. You will now have an advantage over the computer, asExplanation / Answer
PokerTable
namespace Poker.Game
{
public abstract class PokerTable {
/*
* Represents first bet size.
* It is a positive number.
*/
protected readonly Decimal SmallBlind;
/*
* Represents second bet size.
* Is atleast two times bigger than smallBlind.
* And it is positive number.
*/
protected readonly Decimal BigBlind;
/*
* Maximum amount of players at table.
*/
private readonly uint MaxPlayers;
/*
* Contains all players who are in current hand(not folded, not waiting).
* If player folds/leaves then he is removed from this list.
*/
protected CircularList<Player> playersInHand;
/*
* Contains all players who are sitting at table either waiting or playing a hand.
* key is seat at which player is seated,
* value is Player who is sitting there.
*/
private Dictionary<int, Player> playersAtTable = new Dictionary<int, Player>();
/*
* Creates basic game instance with setting blind and max player count.
*/
public PokerTable(Decimal smallBlind, Decimal bigBlind, uint maxPlayers)
{
if (bigBlind / 2 < smallBlind) throw new ArgumentException("Big blind must be twice as big as small blind");
if (smallBlind <= 0) throw new ArgumentException("Small blind must be positive");
if (bigBlind <= 0) throw new ArgumentException("Big blind must be positive");
SmallBlind = smallBlind;
BigBlind = bigBlind;
MaxPlayers = maxPlayers;
}
/*
* Seats player at table, it doesn't mean he will be in the hand.
* He might be in the next hand.
*/
public void addPlayer(int seat, Player player)
{
if(seat < 0 || seat >= MaxPlayers) throw new ArgumentException("Player can sit only at [0;" + (MaxPlayers - 1) + "]");
playersAtTable[seat] = player;
}
/*
* This method starts Game: Deals cards and players
* can make their bets/folds etc.
*
* If there is less then 2 players the exception will be thrown
* since one player can't play this game.
*/
public void StartHand()
{
if(playersAtTable.Count < 2) throw new LackOfPlayersException();
//Moves players sitting at table to list of players who are playing a hand
List<Player> playersAtTable0 = new List<Player>();
foreach (var entry in playersAtTable)
{
playersAtTable0.Add(entry.Value);
}
playersInHand = new CircularList<Player>(playersAtTable0);
StartAction();
}
/*
* This method is called when game can start and playersInHand are set.
*/
protected abstract void StartAction();
public string GetTableState()
{
string state = "";
foreach (var entry in playersAtTable)
{
state += entry.Value.ToString() + " ";
}
return state;
}
}
public class LackOfPlayersException : Exception { }
}
PokerGame
namespace Poker.Game
{
public class PokerGame : PokerTable, TableAction
{
/*
* Helper var for preflop end of street counter;
*/
private int overlap = 0;
/*
* Represent number of cards each player has in his hand.
*/
private const int CARDS_PER_PLAYER = 2;
/*
* Represents amount of cards on each street
*/
private const int PRE_FLOP = 0;
private const int FLOP = 3;
private const int TURN = 4;
private const int RIVER = 5;
/*
* Represents chips in middle of the table
*/
private Decimal chipsInPot = 0;
/*
* Contains cards to deal to players and to set at middle of the table
*/
private Deck deck;
/*
* Contains all cards that are in the middle of table
*/
private List<Card> tableCards = new List<Card>();
/*
* Represents player who had the first action in each street
* (preflop, flop, turn, river). It's used to determine when
* round is finished.
*/
private Player firstPlayer;
public PokerGame() : base(5, 10, 6)
{
}
/*
* This method is called when there is enough players
* to start the game and playersInHand are set, but
* no blinds are posted.
*/
protected override void StartAction() {
deck = new Deck();
deck.Shuffle();
overlap = 0;
PostBlinds();
dealCards();
}
private void dealCards()
{
foreach (Player player in playersInHand)
{
player.Cards = deck.DrawCards(CARDS_PER_PLAYER);
}
}
/*
* Posts small blind, big blind and moves action to the
* next player.
*/
private void PostBlinds()
{
playersInHand.getSelected().MakeABet(SmallBlind);
playersInHand.incrementCounter();
playersInHand.getSelected().MakeABet(BigBlind);
playersInHand.incrementCounter();
firstPlayer = playersInHand.getSelected();
}
/*
* Next player in the line will make a raise to specified amount.
*/
public void MakeABet(Decimal amount)
{
Player prevPlayer = playersInHand.getPrevious();
amount = (amount < prevPlayer.Bet) ? prevPlayer.Bet : amount;
playersInHand.getSelected().MakeABet(amount);
playersInHand.incrementCounter();
}
/*
* Next player in line will make a call.
*
* if everyone is called and everyone has had an action then
* next card is dealt.
*/
public void MakeACall()
{
//sets player to action starter
if (firstPlayer == null) firstPlayer = playersInHand.getSelected();
Player better = playersInHand.getPrevious();
Decimal callAmount = better.Bet;
playersInHand.getSelected().MakeABet(callAmount);
playersInHand.incrementCounter();
if (IsEndOfStreet())
{
DealNextStreet();
firstPlayer = null;
if(playersInHand != null) playersInHand.resetCounter();
}
}
/*
* Checks if it is end of the street
*/
private bool IsEndOfStreet()
{
if (playersInHand.getSelected() == firstPlayer || playersInHand.getPrevious().Bet != 0)
{
Player prevPlayer = playersInHand.getPrevious();
Player currPlayer = playersInHand.getSelected();
if (tableCards.Count == PRE_FLOP && overlap == 0)
{
overlap++;
}
if (prevPlayer.Bet == currPlayer.Bet)
{
if (tableCards.Count == PRE_FLOP && overlap == 0)
{
overlap++;
} else {
return true;
}
}
}
return false;
}
/*
* Moves chips to pot, deals next card
* if it's end of the river then calculate winner
* and gives him all pot chip.
*/
private void DealNextStreet()
{
MoveBetsToPot();
switch (tableCards.Count)
{
case PRE_FLOP:
tableCards.AddRange(deck.DrawCards(FLOP));
break;
case FLOP:
tableCards.AddRange(deck.DrawCards(TURN - FLOP));
break;
case TURN:
tableCards.AddRange(deck.DrawCards(RIVER - TURN));
break;
case RIVER:
EndGame();
break;
default:
throw new ArgumentOutOfRangeException("Not accepted card count " + tableCards.Count);
}
}
/*
* Move players raises/calls to chopInPot and sets
* their bets to 0.
*/
private void MoveBetsToPot()
{
foreach (Player player in playersInHand)
{
chipsInPot += player.Bet;
player.ResetBet();
}
}
/*
* Next player in line will fold. Player will be removed from
* playersInHand list and hes bet will be moved to pot
*/
public void MakeAFold()
{
Player player = playersInHand.getSelected();
chipsInPot += player.Bet;
player.Reset();
playersInHand.DropSelected();
if (playersInHand.Count == 1)
{
MoveBetsToPot();
EndGame();
}
else if (IsEndOfStreet())
{
DealNextStreet();
firstPlayer = null;
if (playersInHand != null) playersInHand.resetCounter();
}
}
/*
* Calcualtes winner and gives him all chips that are in the pot
* Resets cards from last hand.
*/
private void EndGame()
{
List<Player> winners = PokerWinner.GetList(playersInHand, tableCards);
Decimal wonSize = chipsInPot / winners.Count; //divide by zero exception
foreach (Player winner in winners)
{
winner.AddToStack(wonSize);
}
chipsInPot = 0;
//resets cards, maybe other stuff too..
foreach (Player player in playersInHand)
{
player.Reset();
}
playersInHand = null;
}
public string GetGameState()
{
string info = "Stakes are: " + SmallBlind + "/" + BigBlind + " ";
string table = base.GetTableState() + " ";
string pot = "Pot is: " + chipsInPot.ToString() + " ";
string actionOnPlayer = "Player on action: ";
actionOnPlayer += (playersInHand != null) ? playersInHand.getSelected().ToString() : "None is on action ";
string tableCardsStr = "Table Cards: " + string.Join(",", tableCards) + " ";
return info + table + pot + tableCardsStr + actionOnPlayer + " ";
}
}
/*
* This class detects winner or winners from their hand and from the board
*/
static class PokerWinner
{
/*
* Returns a list of players between whom pot should be split
*/
public static List<Player> GetList(List<Player> players, List<Card> tableCards)
{
List<PlayerPokerHand> playerHands = new List<PlayerPokerHand>();
foreach(Player player in players) {
PlayerPokerHand playerHand = new PlayerPokerHand();
List<Card> playerCards = new List<Card>(tableCards);
playerCards.AddRange(player.Cards);
playerHand.Hand = PokerRanker.GetPokerHand(playerCards);
playerHand.Player = player;
playerHands.Add(playerHand);
}
playerHands.Sort();
for (int i = 1; i < playerHands.Count; i++)
{
if (playerHands[0].CompareTo(playerHands[i]) != 0)
{
playerHands = playerHands.GetRange(0, i);
break;
}
}
List<Player> winners = new List<Player>();
for (int i = 0; i < playerHands.Count; i++)
{
winners.Add(playerHands[i].Player);
}
return winners;
}
/*
* This is structure to keep location of Players when PokerHands
* are sorted.
*/
class PlayerPokerHand : IComparable<PlayerPokerHand>
{
public Player Player;
public PokerHand Hand;
public int CompareTo(PlayerPokerHand other)
{
return Hand.CompareTo(other.Hand);
}
}
}
Player
namespace Poker.Game
{
public class Player
{
private int counter = 0;
private readonly int id;
public readonly string Name;
/*
* Amount of chips that player has. Not in pot nor raised.
*/
private decimal stack = 0;
/*
* Amount of chips that player has raised or called, but round is not
* finished. After finishing round these chips are moved black to player(if he wins)
* of moved to the pot if game continous to the next round.
*/
private decimal bet = 0;
/*
* Cards that player has during hand. Ussualy it will be in the holdem.
* If he dont have any then null is set.
*/
private List<Card> cards;
/*
* This creates player with name and stack. Stack must be >= 0.
*/
public Player(string name, Decimal stack)
{
this.Name = name;
this.Stack = stack;
id = Interlocked.Increment(ref counter);
}
/*
* Will throw exception if assigning negative value to stack
*/
public decimal Stack
{
get{
return stack;
}
set
{
if (value < 0) throw new ArgumentException("Stack can't be negative");
stack = value;
}
}
/*
* This method is called when player calls, bets or raised.
*
* betAmount - is amount to make bet equal to or less then
* That means when player needs to call 100, but already has betted 50
* then betAmount should be 100. It will subtrack 50 from stack and add
* to bet variable.
*
* If player has less then hipotetical 100 chips then maximum amount will be added to the pot.
*/
public void MakeABet(Decimal betAmount)
{
if (betAmount < 0) throw new ArgumentException("Bet can't be negative");
Decimal amount = betAmount - bet;
betAmount = (Stack < amount) ? Stack : amount;
bet += betAmount;
Stack -= betAmount;
}
/*
* Returns amount of chips that are raised/called, but not yet moved to the pot.
*/
public Decimal Bet {
get {
return bet;
}
}
public List<Card> Cards
{
get
{
return cards;
}
set
{
cards = new List<Card>(value);
}
}
/*
* This method is called when chips are moved from bet to pot.
* GetBet method should be called before this.
*/
internal void ResetBet()
{
bet = 0;
}
internal void AddToStack(decimal wonSize)
{
stack += wonSize;
}
internal void Reset()
{
cards = null;
bet = 0;
}
public override int GetHashCode()
{
return id;
}
public override string ToString()
{
string cardsStr = (Cards != null) ? string.Join(",", cards) : "None";
return "Player: " + Name + ", Cards: " + cardsStr
+ ", Stack: " + Stack.ToString() + ", Bet: " + Bet.ToString();
}
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.