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