This is a follow up question to this one.
I have been working on this game for some time, and now I would like it to be reviewed. Most importantly, I want to know about my code readability, commenting, naming, efficiency, code practicality, class and method splitting. Also I'm afraid that the code is needlessly complicated (but that could be because I still consider myself a beginner), if that is the case please mention that too in your review.
I consider the game to be finished, since it has all the features that I wanted to implement. I think the only thing missing is some sort of betting system that I might add in the future.
Program class:
using System;
class Program
{
static void Main(string[] args)
{
//Variable declaration
Console.Write("Insert a name: ");
string playerName = Console.ReadLine();
bool play = true;
while (play == true)
{
Game game = new Game();
game.Play(playerName);
Console.WriteLine("Press ENTER to continue");
Console.ReadLine();
Console.Clear();
//ask for replay
Console.Write("Do you want to play again? yes/no: ");
bool answer = true;
string ans = Console.ReadLine();
//Looping until a correct answer is given
while (answer)
{
if (ans == "y" || ans == "Y" || ans == "yes" || ans == "YES")
{
play = true;
answer = false;
}
else if (ans == "n" || ans == "N" || ans == "no" || ans == "NO")
{
play = false;
answer = false;
}
else
{
Console.Write("error, unexpected input\nPlease type y or n ");
ans = Console.ReadLine();
}
}
Console.Clear();
}
}
}
Game Class:
using System;
enum Status
{
gameOn,
playerWin,
houseWin,
draw,
blackjack
}
class Game
{
byte status = (byte)Status.gameOn;
House house = new House();
Player player1 = new Player("");
Card deck = new Card();
//player hits as many times as he wants when < 21
public void PlayerHit()
{
player1.CheckIfBust();
if (!player1.Bust)
{
Console.Write("{0} Hits", player1.Name);
player1.hand.Add(deck.DealCard(false));
player1.GetTotal();
}
}
//Initial cards
public void InitialHits()
{
PlayerHit();
PlayerHit();
house.CheckIfBust();
if (!house.Bust)
{
Console.Write("The House Hits");
house.hand.Add(deck.DealCard(false));
Console.WriteLine("The House gets a secret card");
house.hand.Add(deck.DealCard(true));
house.CheckIfBust();
house.ChangeAces();
}
}
//House hits untill it reaches 16
public int HouseHit()
{
while (house.total < 16)
{
Console.Write("The House Hits");
house.hand.Add(deck.DealCard(false));
house.CheckIfBust();
house.ChangeAces();
}
house.Stand();
return house.total;
}
public void Play(string pName)
{
player1.Name = pName;
player1.CheckIfBust();
deck.CreateDeck();
//Initial cards
InitialHits();
//Player wins automatically if he has a "blackjack"
if (player1.HasBlackjack() == true)
{
Console.WriteLine($"{player1.Name} has a Blackjack!");
status = (byte)Status.blackjack;
}
else
{
//loops as long as the player hasn't gone bust
while (!player1.Bust && !player1.isStanding)
{
//Player gives input
Console.WriteLine($"It is {player1.Name}'s turn:");
Console.WriteLine("Press H to hit Press S to stand" +
"\nPress V to view your hand");
string input = Console.ReadLine();
//input check
if (input == "h" || input == "H")
{
PlayerHit();
}
else if (input == "s" || input == "S")
{
player1.Stand();
break;
}
else if (input == "v" || input == "V")
{
player1.ViewHand();
}
else
{
Console.Write("Unknown command\nPlease type a valid command ");
input = Console.ReadLine();
}
player1.CheckIfBust();
player1.ChangeAces();
}
if (player1.Bust)
{
Console.WriteLine("{0}'s hand is {1} so he goes bust"
, player1.Name, player1.total);
}
HouseHit();
CompareHands();
}
AnounceWinner();
}
public void AnounceWinner()
{
switch (status)
{
case 1:
Console.WriteLine($"{player1.Name} wins!");
break;
case 2:
Console.WriteLine("The House wins!");
break;
case 3:
Console.WriteLine("Is is a draw");
break;
case 4:
Console.WriteLine($"{player1.Name} wins!");
break;
}
}
void CompareHands()
{
if (player1.total > 21)
player1.total = 0;
if (house.total > 21)
house.total = 0;
if (player1.total > house.total)
{
status = (byte)Status.playerWin;
}
else if (house.total > player1.total)
{
status = (byte)Status.houseWin;
}
else
{
status = (byte)Status.draw;
}
if (player1.Bust && house.Bust)
{
status = (byte)Status.draw;
}
}
}
The Player class:
using System;
using System.Collections.Generic;
class Player
{
public string Name { get; set; }
public List<int> hand = new List<int>();
public bool Bust = false;
public bool isStanding = false;
public int total;
public Player(string name = "")
{
Name = name;
total = 0;
}
public int GetTotal()
{
total = 0;
foreach (int card in hand)
{
total += card;
}
return total;
}
public bool HasBlackjack()
{
return (total == 21) ? true : false;
}
public virtual void Stand()
{
CheckIfBust();
if (!Bust)
{
Console.WriteLine("{0} stands at {1}", Name, total);
}
isStanding = true;
}
public virtual void ViewHand()
{
Console.WriteLine("{0}'s hand is {1}", Name, total);
}
public bool CheckIfBust()
{
GetTotal();
return Bust = (total > 21) ? true : false;
}
public void ChangeAces()
{
while (Bust && hand.Contains(11))
{
hand[hand.FindIndex(index => index.Equals(11))] = 1;
CheckIfBust();
}
}
}
The Dealer class:
using System;
class House : Player
{
public override void Stand()
{
CheckIfBust();
if (Bust)
{
Console.WriteLine("The Houses's hand was {0} so it went bust", total);
total = 0;
}
else
{
Console.WriteLine("The House stands at {0}", total);
}
}
}
The Card class:
using System;
using System.Collections.Generic;
class Card
{
private readonly Random randCard = new Random(DateTime.Now.Millisecond);
public List<string> Deck = new List<string>();
public void CreateDeck()
{
List<string> values = new List<string>
{
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"Jack",
"Queen",
"King",
"Ace"
};
List<string> suits = new List<string>
{
"Spades",
"Diamonds",
"Hearts",
"Clubs"
};
foreach (string value in values)
{
foreach (string suit in suits)
{
Deck.Add($"{value} of {suit}");
}
}
}
public int DealCard(bool secret)
{
int value = 0;
int randomCard = randCard.Next(Deck.Count);
string card = Deck[randomCard];
Deck.RemoveAt(randomCard);
if (!secret)
{
Console.Write(" and was dealt the {0}\n", card);
}
//Making the numbers exept 10 have their value
if (card[0] == '2' || card[0] == '3' || card[0] == '4' || card[0] == '5' ||
card[0] == '6' || card[0] == '7' || card[0] == '8' || card[0] == '9')
{
value = int.Parse(card[0].ToString());
}
//Making the faces and 10 have a value of 10
else if (card[0] == '1' || card[0] == 'J' || card[0] == 'Q' || card[0] == 'K')
{
value = 10;
}
//Making the Aces have a value of 11
else if (card[0] == 'A')
{
value = 11;
}
return value;
}
}