diff --git a/01 Acey Ducey/csharp/AceyDucey.csproj b/01 Acey Ducey/csharp/AceyDucey.csproj
new file mode 100644
index 00000000..c73e0d16
--- /dev/null
+++ b/01 Acey Ducey/csharp/AceyDucey.csproj
@@ -0,0 +1,8 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
diff --git a/01 Acey Ducey/csharp/AceyDucey.sln b/01 Acey Ducey/csharp/AceyDucey.sln
new file mode 100644
index 00000000..f406d9cf
--- /dev/null
+++ b/01 Acey Ducey/csharp/AceyDucey.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30709.132
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AceyDucey", "AceyDucey.csproj", "{A8FE2F04-3DFE-4254-BD5B-281DC8E30B1C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A8FE2F04-3DFE-4254-BD5B-281DC8E30B1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A8FE2F04-3DFE-4254-BD5B-281DC8E30B1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A8FE2F04-3DFE-4254-BD5B-281DC8E30B1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A8FE2F04-3DFE-4254-BD5B-281DC8E30B1C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F620B340-EB7A-48C1-B12F-9D3D94AE7771}
+ EndGlobalSection
+EndGlobal
diff --git a/01 Acey Ducey/csharp/Game.cs b/01 Acey Ducey/csharp/Game.cs
new file mode 100644
index 00000000..76c58cd7
--- /dev/null
+++ b/01 Acey Ducey/csharp/Game.cs
@@ -0,0 +1,326 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace AceyDucey
+{
+ ///
+ /// The main class that implements all the game logic
+ ///
+ internal class Game
+ {
+ ///
+ /// Our Random number generator object
+ ///
+ private Random Rnd { get; } = new Random();
+
+ ///
+ /// A line of underscores that we'll print between turns to separate them from one another on screen
+ ///
+ private string SeparatorLine { get; } = new string('_', 70);
+
+
+ ///
+ /// Main game loop function. This will play the game endlessly until the player chooses to quit.
+ ///
+ internal void GameLoop()
+ {
+ // First display instructions to the player
+ DisplayIntroText();
+
+ // We'll loop for each game until the player decides not to continue
+ do
+ {
+ // Play a game!
+ PlayGame();
+
+ // Play again?
+ } while (TryAgain());
+ }
+
+ ///
+ /// Play the game
+ ///
+ private void PlayGame()
+ {
+ GameState state = new GameState();
+
+ // Clear the display
+ Console.Clear();
+ // Keep looping until the player has no money left
+ do
+ {
+ // Play the next turn. Pass in our state object so the turn can see the money available,
+ // can update it after the player makes a bet, and can update the turn count.
+ PlayTurn(state);
+
+ // Keep looping until the player runs out of money
+ } while (state.Money > 0);
+
+ // Looks like the player is bankrupt, let them know how they did.
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("");
+ Console.WriteLine($"Sorry, friend, but you blew your wad. Your game is over after {state.TurnCount} {(state.TurnCount == 1 ? "turn" : "turns")}. Your highest balance was ${state.MaxMoney}.");
+ }
+
+
+ ///
+ /// Play a turn
+ ///
+ /// The current game state
+ private void PlayTurn(GameState state)
+ {
+ // Let the player know what's happening
+ Console.WriteLine("");
+ Console.WriteLine(SeparatorLine);
+ Console.WriteLine("");
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("");
+ Console.WriteLine("Here are your next two cards:");
+
+ // Generate two random cards
+ int firstCard = GetCard();
+ int secondCard = GetCard();
+
+ // If the second card is lower than the first card, swap them over
+ if (secondCard < firstCard)
+ {
+ (firstCard, secondCard) = (secondCard, firstCard);
+ }
+
+ // Display the cards
+ DisplayCard(firstCard);
+ DisplayCard(secondCard);
+
+ // Ask the player what they want to do
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("");
+ Console.Write("You currently have ");
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.Write($"${state.Money}");
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine(". How much would you like to bet?");
+
+ // Read the bet amount
+ int betAmount = PlayTurn_GetBetAmount(state.Money);
+
+ // Display a summary of their inpout
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("");
+ Console.WriteLine($"You choose to {(betAmount == 0 ? "pass" : $"bet {betAmount}")}.");
+
+ // Generate and display the final card
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("");
+ Console.WriteLine("The next card is:");
+
+ int thirdCard = GetCard();
+ DisplayCard(thirdCard);
+ Console.WriteLine("");
+
+ // Was the third card between the first two cards?
+ if (thirdCard > firstCard && thirdCard < secondCard)
+ {
+ // It was! Inform the player and add to their money
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("You win!");
+ if (betAmount == 0)
+ {
+ Console.WriteLine("(It's just a shame you chose not to bet!)");
+ }
+ else
+ {
+ state.Money += betAmount;
+ // If their money exceeds the MaxMoney, update that too
+ state.MaxMoney = Math.Max(state.Money, state.MaxMoney);
+ }
+ }
+ else
+ {
+ // Oh dear, the player lost. Let them know the bad news and take their bet from their money
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("You lose!");
+ if (betAmount == 0)
+ {
+ Console.WriteLine("(It's lucky you chose not to bet!)");
+ }
+ else
+ {
+ state.Money -= betAmount;
+ }
+ }
+
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.Write("You now have ");
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.Write($"${state.Money}");
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine(".");
+
+ // Update the turn count now that another turn has been played
+ state.TurnCount += 1;
+
+ // Ready for the next turn...
+ Console.ForegroundColor = ConsoleColor.DarkGreen;
+ Console.WriteLine("");
+ Console.WriteLine("Press any key to continue...");
+ Console.ReadKey(true);
+ }
+
+ ///
+ /// Prompt the user for their bet amount and validate their input
+ ///
+ /// The player's current money
+ /// Returns the amount the player chooses to bet
+ private int PlayTurn_GetBetAmount(int currentMoney)
+ {
+ int betAmount;
+ // Loop until the user enters a valid value
+ do
+ {
+ // Move this to a separate function...
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.Write("> $");
+ string input = Console.ReadLine();
+
+ // Is this a valid number?
+ if (!int.TryParse(input, out betAmount))
+ {
+ // No
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("Sorry, I didn't understand. Please enter how much you would like to bet.");
+ // Continue looping
+ continue;
+ }
+
+ // If the amount between 0 and their available money?
+ if (betAmount < 0 || betAmount > currentMoney)
+ {
+ // No
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Please enter a bet amount between $0 and ${currentMoney}.");
+ // Continue looping
+ continue;
+ }
+
+ // We have a valid bet, stop looping
+ break;
+ } while (true);
+
+ // Return whatever the player entered
+ return betAmount;
+ }
+
+ ///
+ /// Generate a new random card.
+ ///
+ /// Will return a value between 2 and 14, inclusive.
+ /// Values 2 to 10 are their face values. 11 represents a Jack, 12 is a Queen, 13 a King and 14 an Ace.
+ /// Even though this is a slightly offset sequence, it allows us to perform a simple greater-than/less-than
+ /// comparison with the card values, treating an Ace as a high card.
+ private int GetCard()
+ {
+ return Rnd.Next(2, 15);
+ }
+
+ ///
+ /// Display the card number on screen, translating values 11 through to 14 into their named equivalents.
+ ///
+ ///
+ private void DisplayCard(int card)
+ {
+ string cardText;
+ switch (card)
+ {
+ case 11:
+ cardText = "Jack";
+ break;
+ case 12:
+ cardText = "Queen";
+ break;
+ case 13:
+ cardText = "King";
+ break;
+ case 14:
+ cardText = "Ace";
+ break;
+ default:
+ cardText = card.ToString();
+ break;
+ }
+
+ // Format as black text on a white background
+ Console.Write(" ");
+ Console.BackgroundColor = ConsoleColor.White;
+ Console.ForegroundColor = ConsoleColor.Black;
+ Console.Write($" {cardText} ");
+ Console.BackgroundColor = ConsoleColor.Black;
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("");
+ }
+
+ ///
+ /// Display instructions on how to play the game and wait for the player to press a key.
+ ///
+ private void DisplayIntroText()
+ {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("Acey Ducey Gard Game.");
+ Console.WriteLine("Creating Computing, Morristown, New Jersey.");
+ Console.WriteLine("");
+
+ Console.ForegroundColor = ConsoleColor.DarkGreen;
+ Console.WriteLine("Originally published in 1978 in the book 'Basic Computer Games' by David Ahl.");
+ Console.WriteLine("Modernised and converted to C# in 2021 by Adam Dawes (@AdamDawes575).");
+ Console.WriteLine("");
+
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Console.WriteLine("Acey Ducey is played in the following manner:");
+ Console.WriteLine("");
+ Console.WriteLine("The dealer (computer) deals two cards, face up.");
+ Console.WriteLine("");
+ Console.WriteLine("You have an option to bet or pass, depending on whether or not you feel the next card will have a value between the");
+ Console.WriteLine("first two.");
+ Console.WriteLine("");
+ Console.WriteLine("If the card is between, you will win your stake, otherwise you will lose it. Ace is 'high' (higher than a King).");
+ Console.WriteLine("");
+ Console.WriteLine("If you want to pass, enter a bet amount of $0.");
+ Console.WriteLine("");
+
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("Press any key start the game.");
+ Console.ReadKey(true);
+
+ }
+
+ ///
+ /// Prompt the player to try again, and wait for them to press Y or N.
+ ///
+ /// Returns true if the player wants to try again, false if they have finished playing.
+ private bool TryAgain()
+ {
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("Would you like to try again? (Press 'Y' for yes or 'N' for no)");
+
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.Write("> ");
+
+ char pressedKey;
+ // Keep looping until we get a recognised input
+ do
+ {
+ // Read a key, don't display it on screen
+ ConsoleKeyInfo key = Console.ReadKey(true);
+ // Convert to upper-case so we don't need to care about capitalisation
+ pressedKey = Char.ToUpper(key.KeyChar);
+ // Is this a key we recognise? If not, keep looping
+ } while (pressedKey != 'Y' && pressedKey != 'N');
+ // Display the result on the screen
+ Console.WriteLine(pressedKey);
+
+ // Return true if the player pressed 'Y', false for anything else.
+ return (pressedKey == 'Y');
+ }
+
+ }
+}
diff --git a/01 Acey Ducey/csharp/GameState.cs b/01 Acey Ducey/csharp/GameState.cs
new file mode 100644
index 00000000..5f8ccbcf
--- /dev/null
+++ b/01 Acey Ducey/csharp/GameState.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace AceyDucey
+{
+ ///
+ /// The GameState class keeps track of all the game variables while the game is being played
+ ///
+ internal class GameState
+ {
+
+ ///
+ /// How much money does the player have at the moment?
+ ///
+ internal int Money { get; set; }
+
+ ///
+ /// What's the highest amount of money they had at any point in the game?
+ ///
+ internal int MaxMoney { get; set; }
+
+ ///
+ /// How many turns have they played?
+ ///
+ internal int TurnCount { get; set; }
+
+ ///
+ /// Class constructor -- initialise all values to their defaults.
+ ///
+ internal GameState()
+ {
+ // Setting Money to 100 gives the player their starting balance. Changing this will alter how much they have to begin with.
+ Money = 100;
+ MaxMoney = Money;
+ TurnCount = 0;
+ }
+ }
+}
diff --git a/01 Acey Ducey/csharp/Program.cs b/01 Acey Ducey/csharp/Program.cs
new file mode 100644
index 00000000..cf6052c9
--- /dev/null
+++ b/01 Acey Ducey/csharp/Program.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Threading;
+
+namespace AceyDucey
+{
+ ///
+ /// The application's entry point
+ ///
+ class Program
+ {
+
+ ///
+ /// This function will be called automatically when the application begins
+ ///
+ ///
+ static void Main(string[] args)
+ {
+ // Create an instance of our main Game class
+ Game game = new Game();
+
+ // Call its GameLoop function. This will play the game endlessly in a loop until the player chooses to quit.
+ game.GameLoop();
+ }
+
+
+ }
+}
diff --git a/01 Acey Ducey/csharp/README.md b/01 Acey Ducey/csharp/README.md
index 4daabb5c..6bb4c49e 100644
--- a/01 Acey Ducey/csharp/README.md
+++ b/01 Acey Ducey/csharp/README.md
@@ -1,3 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
-Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/)
+Conversion to [Microsoft C#](https://docs.microsoft.com/en-us/dotnet/csharp/) by Adam Dawes (@AdamDawes575, https://adamdawes.com).