diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..53e00acd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+################################################################################
+# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
+################################################################################
+
+/01 Acey Ducey/csharp/obj
+/47 Hi-Lo/csharp/obj
+/.vs
+/33 Dice/csharp/obj
+/01 Acey Ducey/csharp/.vs/AceyDucey
+/01 Acey Ducey/csharp/bin/Debug/netcoreapp3.1
+/33 Dice/csharp/bin/Debug/net5.0
+/basic-computer-games-dot-net/.vs/basic-computer-games-dot-net/v16
diff --git a/33 Dice/csharp/Dice.csproj b/33 Dice/csharp/Dice.csproj
new file mode 100644
index 00000000..54cdbe42
--- /dev/null
+++ b/33 Dice/csharp/Dice.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ net5.0
+
+
+
+
+
+
+
diff --git a/33 Dice/csharp/Game.cs b/33 Dice/csharp/Game.cs
new file mode 100644
index 00000000..3938e4c4
--- /dev/null
+++ b/33 Dice/csharp/Game.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Linq;
+
+namespace BasicComputerGames.Dice
+{
+ public class Game
+ {
+ private readonly RollGenerator _roller = new RollGenerator();
+
+ public void GameLoop()
+ {
+ DisplayIntroText();
+
+ // RollGenerator.ReseedRNG(1234); // hard-code seed for repeatabilty during testing
+
+ do
+ {
+ int numRolls = GetInput();
+ var counter = CountRolls(numRolls);
+ DisplayCounts(counter);
+ } while (TryAgain());
+ }
+
+ private void DisplayIntroText()
+ {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("Dice");
+ Console.WriteLine("Creating Computing, Morristown, New Jersey."); Console.WriteLine();
+
+ Console.ForegroundColor = ConsoleColor.DarkGreen;
+ Console.WriteLine("Original code by Danny Freidus.");
+ Console.WriteLine("Originally published in 1978 in the book 'Basic Computer Games' by David Ahl.");
+ Console.WriteLine("Modernized and converted to C# in 2021 by James Curran (noveltheory.com).");
+ Console.WriteLine();
+
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Console.WriteLine("This program simulates the rolling of a pair of dice.");
+ Console.WriteLine("You enter the number of times you want the computer to");
+ Console.WriteLine("'roll' the dice. Watch out, very large numbers take");
+ Console.WriteLine("a long time. In particular, numbers over 10 million.");
+ Console.WriteLine();
+
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("Press any key start the game.");
+ Console.ReadKey(true);
+ }
+
+ private int GetInput()
+ {
+ int num = -1;
+ Console.WriteLine();
+ do
+ {
+ Console.WriteLine();
+ Console.Write("How many rolls? ");
+ } while (!Int32.TryParse(Console.ReadLine(), out num));
+
+ return num;
+ }
+
+ private void DisplayCounts(int[] counter)
+ {
+ Console.WriteLine();
+ Console.WriteLine($"\tTotal\tTotal Number");
+ Console.WriteLine($"\tSpots\tof Times");
+ Console.WriteLine($"\t===\t=========");
+ for (var n = 1; n < counter.Length; ++n)
+ {
+ Console.WriteLine($"\t{n + 1,2}\t{counter[n],9:#,0}");
+ }
+ Console.WriteLine();
+ }
+
+ private int[] CountRolls(int x)
+ {
+ var counter = _roller.Rolls().Take(x).Aggregate(new int[12], (cntr, r) =>
+ {
+ cntr[r.die1 + r.die2 - 1]++;
+ return cntr;
+ });
+ return counter;
+ }
+ ///
+ /// 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');
+ }
+ }
+}
\ No newline at end of file
diff --git a/33 Dice/csharp/Program.cs b/33 Dice/csharp/Program.cs
new file mode 100644
index 00000000..959587cc
--- /dev/null
+++ b/33 Dice/csharp/Program.cs
@@ -0,0 +1,14 @@
+namespace BasicComputerGames.Dice
+{
+ public class Program
+ {
+ public 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/33 Dice/csharp/README.md b/33 Dice/csharp/README.md
index 4daabb5c..23ccd0fe 100644
--- a/33 Dice/csharp/README.md
+++ b/33 Dice/csharp/README.md
@@ -1,3 +1,4 @@
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 James Curran (http://www.noveltheory.com)
+
diff --git a/33 Dice/csharp/RollGenerator.cs b/33 Dice/csharp/RollGenerator.cs
new file mode 100644
index 00000000..08f2df6b
--- /dev/null
+++ b/33 Dice/csharp/RollGenerator.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace BasicComputerGames.Dice
+{
+ public class RollGenerator
+ {
+ static Random _rnd = new Random();
+
+ public static void ReseedRNG(int seed) => _rnd = new Random(seed);
+
+ public IEnumerable<(int die1, int die2)> Rolls()
+ {
+ while (true)
+ {
+ yield return (_rnd.Next(1, 7), _rnd.Next(1, 7));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/basic-computer-games-dot-net/basic-computer-games-dot-net.sln b/basic-computer-games-dot-net/basic-computer-games-dot-net.sln
new file mode 100644
index 00000000..d6485c9a
--- /dev/null
+++ b/basic-computer-games-dot-net/basic-computer-games-dot-net.sln
@@ -0,0 +1,45 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31004.235
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01 Acey Ducey", "01 Acey Ducey", "{63FEF89A-DAF1-42C6-B86B-AAD51E885553}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{9ADA338C-DAB6-4EE8-8F53-F3F711BEA985}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AceyDucey", "..\01 Acey Ducey\csharp\AceyDucey.csproj", "{DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "33 Dice", "33 Dice", "{3C6771F4-513C-4B8D-A042-15E18EB27740}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "csharp", "csharp", "{AC302ACD-C3B2-460D-BA1A-0A511C36A848}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dice", "..\33 Dice\csharp\Dice.csproj", "{26D086DE-0BBD-4A18-AC63-2476A7DB52D3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {26D086DE-0BBD-4A18-AC63-2476A7DB52D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {26D086DE-0BBD-4A18-AC63-2476A7DB52D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {26D086DE-0BBD-4A18-AC63-2476A7DB52D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {26D086DE-0BBD-4A18-AC63-2476A7DB52D3}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {9ADA338C-DAB6-4EE8-8F53-F3F711BEA985} = {63FEF89A-DAF1-42C6-B86B-AAD51E885553}
+ {DA16CAAE-A3BE-42D0-9525-623AA6B0EDC3} = {9ADA338C-DAB6-4EE8-8F53-F3F711BEA985}
+ {AC302ACD-C3B2-460D-BA1A-0A511C36A848} = {3C6771F4-513C-4B8D-A042-15E18EB27740}
+ {26D086DE-0BBD-4A18-AC63-2476A7DB52D3} = {AC302ACD-C3B2-460D-BA1A-0A511C36A848}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {703D538E-7F20-4DD0-A3DD-7BBE36AC82AF}
+ EndGlobalSection
+EndGlobal