mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-22 23:26:40 -08:00
Implement Blackjack (game 10) in C#
This commit is contained in:
9
10 Blackjack/csharp/Blackjack.csproj
Normal file
9
10 Blackjack/csharp/Blackjack.csproj
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>Blackjack</RootNamespace>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
32
10 Blackjack/csharp/Card.cs
Normal file
32
10 Blackjack/csharp/Card.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
namespace Blackjack
|
||||||
|
{
|
||||||
|
public class Card
|
||||||
|
{
|
||||||
|
private static readonly string[] _names = new[] {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
|
||||||
|
|
||||||
|
public Card(int index)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Index { get; private set; }
|
||||||
|
|
||||||
|
public string Name => _names[Index];
|
||||||
|
|
||||||
|
public string IndefiniteArticle => (Index == 0 || Index == 7) ? "an" : "a";
|
||||||
|
|
||||||
|
public bool IsAce => Index == 0;
|
||||||
|
|
||||||
|
public int Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IsAce)
|
||||||
|
return 11;
|
||||||
|
if (Index > 8)
|
||||||
|
return 10;
|
||||||
|
return Index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
10 Blackjack/csharp/Deck.cs
Normal file
56
10 Blackjack/csharp/Deck.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Blackjack
|
||||||
|
{
|
||||||
|
public class Deck
|
||||||
|
{
|
||||||
|
private static readonly Random _random = new Random();
|
||||||
|
|
||||||
|
private readonly List<Card> _cards = new List<Card>(52);
|
||||||
|
private readonly List<Card> _discards = new List<Card>(52);
|
||||||
|
|
||||||
|
public Deck()
|
||||||
|
{
|
||||||
|
for (var index = 0; index < 12; index++)
|
||||||
|
{
|
||||||
|
for (var suit = 0; suit < 4; suit++)
|
||||||
|
{
|
||||||
|
_discards.Add(new Card(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reshuffle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Reshuffle()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Reshuffling");
|
||||||
|
|
||||||
|
_cards.AddRange(_discards);
|
||||||
|
_discards.Clear();
|
||||||
|
|
||||||
|
for (var index1 = _cards.Count - 1; index1 > 0; index1--)
|
||||||
|
{
|
||||||
|
var index2 = _random.Next(0, index1);
|
||||||
|
var swapCard = _cards[index1];
|
||||||
|
_cards[index1] = _cards[index2];
|
||||||
|
_cards[index2] = swapCard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Card DrawCard()
|
||||||
|
{
|
||||||
|
if (_cards.Count < 2)
|
||||||
|
Reshuffle();
|
||||||
|
|
||||||
|
var card = _cards[_cards.Count - 1];
|
||||||
|
_cards.RemoveAt(_cards.Count - 1);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Discard(IEnumerable<Card> cards)
|
||||||
|
{
|
||||||
|
_discards.AddRange(cards);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
232
10 Blackjack/csharp/Game.cs
Normal file
232
10 Blackjack/csharp/Game.cs
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Blackjack
|
||||||
|
{
|
||||||
|
public class Game
|
||||||
|
{
|
||||||
|
private readonly Deck _deck = new Deck();
|
||||||
|
private readonly int _numberOfPlayers;
|
||||||
|
private readonly Player[] _players;
|
||||||
|
private readonly Hand _dealerHand;
|
||||||
|
|
||||||
|
public Game(int numberOfPlayers)
|
||||||
|
{
|
||||||
|
_numberOfPlayers = numberOfPlayers;
|
||||||
|
_players = new Player[_numberOfPlayers];
|
||||||
|
for (var playerIndex = 0; playerIndex < _numberOfPlayers; playerIndex++)
|
||||||
|
_players[playerIndex] = new Player(playerIndex);
|
||||||
|
_dealerHand = new Hand();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayGame()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
PlayRound();
|
||||||
|
TallyResults();
|
||||||
|
ResetRoundState();
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayRound()
|
||||||
|
{
|
||||||
|
GetPlayerBets();
|
||||||
|
|
||||||
|
DealHands();
|
||||||
|
|
||||||
|
// Test for insurance
|
||||||
|
var dealerIsShowingAce = _dealerHand.Cards[0].IsAce;
|
||||||
|
if (dealerIsShowingAce && Prompt.ForYesNo("Any insurance?"))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Insurance bets");
|
||||||
|
var insuranceBets = new int[_numberOfPlayers];
|
||||||
|
foreach (var player in _players)
|
||||||
|
insuranceBets[player.Index] = Prompt.ForInteger($"# {player.Index + 1} ?", 0, player.RoundBet / 2);
|
||||||
|
|
||||||
|
var insuranceEffectMultiplier = _dealerHand.IsBlackjack ? 2 : -1;
|
||||||
|
foreach (var player in _players)
|
||||||
|
player.RoundWinnings += insuranceBets[player.Index] * insuranceEffectMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for dealer blackjack
|
||||||
|
var concealedCard = _dealerHand.Cards[0];
|
||||||
|
if (_dealerHand.IsBlackjack)
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Dealer has {0} {1} in the hole for blackjack.", concealedCard.IndefiniteArticle, concealedCard.Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (dealerIsShowingAce)
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("No dealer blackjack.");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var player in _players)
|
||||||
|
PlayHand(player);
|
||||||
|
|
||||||
|
// Dealer hand
|
||||||
|
var allPlayersBusted = _players.All(p => p.Hand.IsBusted && (!p.SecondHand.Exists || p.SecondHand.IsBusted));
|
||||||
|
if (allPlayersBusted)
|
||||||
|
Console.WriteLine("Dealer had {0} {1} concealed.", concealedCard.IndefiniteArticle, concealedCard.Name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Dealer has {0} {1} concealed for a total of {2}", concealedCard.IndefiniteArticle, concealedCard.Name, _dealerHand.Total);
|
||||||
|
if (_dealerHand.Total < 17)
|
||||||
|
{
|
||||||
|
Console.Write("Draws");
|
||||||
|
while (_dealerHand.Total < 17)
|
||||||
|
{
|
||||||
|
var card = _dealerHand.AddCard(_deck.DrawCard());
|
||||||
|
Console.Write(" {0}", card.Name);
|
||||||
|
}
|
||||||
|
if (_dealerHand.IsBusted)
|
||||||
|
Console.WriteLine(" ...Busted");
|
||||||
|
else
|
||||||
|
Console.WriteLine(" ---Total is {0}", _dealerHand.Total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetPlayerBets()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Bets:");
|
||||||
|
foreach (var player in _players)
|
||||||
|
player.RoundBet = Prompt.ForInteger($"# {player.Name} ?", 1, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DealHands()
|
||||||
|
{
|
||||||
|
Console.Write("Player ");
|
||||||
|
foreach (var player in _players)
|
||||||
|
Console.Write("{0} ", player.Name);
|
||||||
|
Console.WriteLine("Dealer");
|
||||||
|
|
||||||
|
for (var cardIndex = 0; cardIndex < 2; cardIndex++)
|
||||||
|
{
|
||||||
|
Console.Write(" ");
|
||||||
|
foreach (var player in _players)
|
||||||
|
Console.Write(" {0,-4}", player.Hand.AddCard(_deck.DrawCard()).Name);
|
||||||
|
var dealerCard = _dealerHand.AddCard(_deck.DrawCard());
|
||||||
|
Console.Write(" {0,-4}", (cardIndex == 0) ? "XX" : dealerCard.Name);
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlayHand(Player player)
|
||||||
|
{
|
||||||
|
var hand = player.Hand;
|
||||||
|
|
||||||
|
Console.Write("Player {0} ", player.Name);
|
||||||
|
|
||||||
|
var playerCanSplit = hand.Cards[0].Value == hand.Cards[1].Value;
|
||||||
|
var command = Prompt.ForCommandCharacter("?", playerCanSplit ? "HSD/" : "HSD");
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case "D":
|
||||||
|
player.RoundBet *= 2;
|
||||||
|
goto case "H";
|
||||||
|
|
||||||
|
case "H":
|
||||||
|
while (TakeHit(hand) && PromptForAnotherHit())
|
||||||
|
{ }
|
||||||
|
if (!hand.IsBusted)
|
||||||
|
Console.WriteLine("Total is {0}", hand.Total);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "S":
|
||||||
|
if (hand.IsBlackjack)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Blackjack!");
|
||||||
|
player.RoundWinnings = (int)(1.5 * player.RoundBet + 0.5);
|
||||||
|
player.RoundBet = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Console.WriteLine("Total is {0}", hand.Total);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "/":
|
||||||
|
hand.SplitHand(player.SecondHand);
|
||||||
|
var card = hand.AddCard(_deck.DrawCard());
|
||||||
|
Console.WriteLine("First hand receives {0} {1}", card.IndefiniteArticle, card.Name);
|
||||||
|
card = player.SecondHand.AddCard(_deck.DrawCard());
|
||||||
|
Console.WriteLine("Second hand receives {0} {1}", card.IndefiniteArticle, card.Name);
|
||||||
|
|
||||||
|
for (int handNumber = 1; handNumber <= 2; handNumber++)
|
||||||
|
{
|
||||||
|
hand = (handNumber == 1) ? player.Hand : player.SecondHand;
|
||||||
|
|
||||||
|
Console.Write("Hand {0}", handNumber);
|
||||||
|
while (PromptForAnotherHit() && TakeHit(hand))
|
||||||
|
{ }
|
||||||
|
if (!hand.IsBusted)
|
||||||
|
Console.WriteLine("Total is {0}", hand.Total);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TakeHit(Hand hand)
|
||||||
|
{
|
||||||
|
var card = hand.AddCard(_deck.DrawCard());
|
||||||
|
Console.Write("Received {0,-6}", $"{card.IndefiniteArticle} {card.Name}");
|
||||||
|
if (hand.IsBusted)
|
||||||
|
{
|
||||||
|
Console.WriteLine("...Busted");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool PromptForAnotherHit()
|
||||||
|
{
|
||||||
|
return String.Equals(Prompt.ForCommandCharacter(" Hit?", "HS"), "H");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TallyResults()
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
foreach (var player in _players)
|
||||||
|
{
|
||||||
|
player.RoundWinnings += CalculateWinnings(player, player.Hand);
|
||||||
|
if (player.SecondHand.Exists)
|
||||||
|
player.RoundWinnings += CalculateWinnings(player, player.SecondHand);
|
||||||
|
player.TotalWinnings += player.RoundWinnings;
|
||||||
|
|
||||||
|
Console.WriteLine("Player {0} {1,-6} {2,3} Total= {3,5}",
|
||||||
|
player.Name,
|
||||||
|
(player.RoundWinnings > 0) ? "wins" : (player.RoundWinnings) < 0 ? "loses" : "pushes",
|
||||||
|
(player.RoundWinnings != 0) ? Math.Abs(player.RoundWinnings).ToString() : "",
|
||||||
|
player.TotalWinnings);
|
||||||
|
}
|
||||||
|
Console.WriteLine("Dealer's total= {0}", -_players.Sum(p => p.TotalWinnings));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CalculateWinnings(Player player, Hand hand)
|
||||||
|
{
|
||||||
|
if (hand.IsBusted)
|
||||||
|
return -player.RoundBet;
|
||||||
|
if (hand.Total == _dealerHand.Total)
|
||||||
|
return 0;
|
||||||
|
if (_dealerHand.IsBusted || hand.Total > _dealerHand.Total)
|
||||||
|
return player.RoundBet;
|
||||||
|
return -player.RoundBet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetRoundState()
|
||||||
|
{
|
||||||
|
foreach (var player in _players)
|
||||||
|
{
|
||||||
|
player.RoundWinnings = 0;
|
||||||
|
player.RoundBet = 0;
|
||||||
|
player.Hand.Discard(_deck);
|
||||||
|
player.SecondHand.Discard(_deck);
|
||||||
|
}
|
||||||
|
_dealerHand.Discard(_deck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
10 Blackjack/csharp/Hand.cs
Normal file
67
10 Blackjack/csharp/Hand.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Blackjack
|
||||||
|
{
|
||||||
|
public class Hand
|
||||||
|
{
|
||||||
|
private readonly List<Card> _cards = new List<Card>(12);
|
||||||
|
private int _cachedTotal = 0;
|
||||||
|
|
||||||
|
public Card AddCard(Card card)
|
||||||
|
{
|
||||||
|
_cards.Add(card);
|
||||||
|
_cachedTotal = 0;
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Discard(Deck deck)
|
||||||
|
{
|
||||||
|
deck.Discard(_cards);
|
||||||
|
_cards.Clear();
|
||||||
|
_cachedTotal = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SplitHand(Hand secondHand)
|
||||||
|
{
|
||||||
|
if (Count != 2 || secondHand.Count != 0)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
secondHand.AddCard(_cards[1]);
|
||||||
|
_cards.RemoveAt(1);
|
||||||
|
_cachedTotal = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<Card> Cards => _cards;
|
||||||
|
|
||||||
|
public int Count => _cards.Count;
|
||||||
|
|
||||||
|
public bool Exists => _cards.Count > 0;
|
||||||
|
|
||||||
|
public int Total
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_cachedTotal == 0)
|
||||||
|
{
|
||||||
|
var aceCount = 0;
|
||||||
|
foreach (var card in _cards)
|
||||||
|
{
|
||||||
|
_cachedTotal += card.Value;
|
||||||
|
if (card.IsAce)
|
||||||
|
aceCount++;
|
||||||
|
}
|
||||||
|
while (_cachedTotal > 21 && aceCount > 0)
|
||||||
|
{
|
||||||
|
_cachedTotal -= 10;
|
||||||
|
aceCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _cachedTotal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsBlackjack => Total == 21 && Count == 2;
|
||||||
|
|
||||||
|
public bool IsBusted => Total > 21;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
10 Blackjack/csharp/Player.cs
Normal file
27
10 Blackjack/csharp/Player.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
namespace Blackjack
|
||||||
|
{
|
||||||
|
public class Player
|
||||||
|
{
|
||||||
|
public Player(int index)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
Name = (index + 1).ToString();
|
||||||
|
Hand = new Hand();
|
||||||
|
SecondHand = new Hand();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Index { get; private set; }
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public Hand Hand { get; private set; }
|
||||||
|
|
||||||
|
public Hand SecondHand { get; private set;}
|
||||||
|
|
||||||
|
public int RoundBet { get; set; }
|
||||||
|
|
||||||
|
public int RoundWinnings { get; set; }
|
||||||
|
|
||||||
|
public int TotalWinnings { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
41
10 Blackjack/csharp/Program.cs
Normal file
41
10 Blackjack/csharp/Program.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Blackjack
|
||||||
|
{
|
||||||
|
static class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("{0}BLACK JACK", new string(' ', 31));
|
||||||
|
Console.WriteLine("{0}CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", new string(' ', 15));
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
OfferInstructions();
|
||||||
|
|
||||||
|
var numberOfPlayers = Prompt.ForInteger("Number of players?", 1, 6);
|
||||||
|
var game = new Game(numberOfPlayers);
|
||||||
|
game.PlayGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OfferInstructions()
|
||||||
|
{
|
||||||
|
if (!Prompt.ForYesNo("Do you want instructions?"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Console.WriteLine("This is the game of 21. As many as 7 players may play the");
|
||||||
|
Console.WriteLine("game. On each deal, bets will be asked for, and the");
|
||||||
|
Console.WriteLine("players' bets should be typed in. The cards will then be");
|
||||||
|
Console.WriteLine("dealt, and each player in turn plays his hand. The");
|
||||||
|
Console.WriteLine("first response should be either 'D', indicating that the");
|
||||||
|
Console.WriteLine("player is doubling down, 'S', indicating that he is");
|
||||||
|
Console.WriteLine("standing, 'H', indicating he wants another card, or '/',");
|
||||||
|
Console.WriteLine("indicating that he wants to split his cards. After the");
|
||||||
|
Console.WriteLine("initial response, all further responses should be 's' or");
|
||||||
|
Console.WriteLine("'H', unless the cards were split, in which case doubling");
|
||||||
|
Console.WriteLine("down is again permitted. In order to collect for");
|
||||||
|
Console.WriteLine("Blackjack, the initial response should be 'S'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
10 Blackjack/csharp/Prompt.cs
Normal file
58
10 Blackjack/csharp/Prompt.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Blackjack
|
||||||
|
{
|
||||||
|
public static class Prompt
|
||||||
|
{
|
||||||
|
public static bool ForYesNo(string prompt)
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
Console.Write("{0} ", prompt);
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (input.StartsWith("y", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return true;
|
||||||
|
if (input.StartsWith("n", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return false;
|
||||||
|
WriteNotUnderstood();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ForInteger(string prompt, int minimum = 1, int maximum = int.MaxValue)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Console.Write("{0} ", prompt);
|
||||||
|
if (!int.TryParse(Console.ReadLine(), out var number))
|
||||||
|
WriteNotUnderstood();
|
||||||
|
else if (number < minimum || number > maximum)
|
||||||
|
Console.WriteLine("Sorry, I need a number between {0} and {1}.", minimum, maximum);
|
||||||
|
else
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ForCommandCharacter(string prompt, string allowedCharacters)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Console.Write("{0} ", prompt);
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (input.Length > 0)
|
||||||
|
{
|
||||||
|
var character = input.Substring(0, 1);
|
||||||
|
var characterIndex = allowedCharacters.IndexOf(character, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
if (characterIndex != -1)
|
||||||
|
return allowedCharacters.Substring(characterIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Type one of {0} please", String.Join(", ", allowedCharacters.ToCharArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteNotUnderstood()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Sorry, I didn't understand.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user