From a8436342616c9cf71eb8f03a71e9f08b3a4cc346 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 25 Apr 2021 13:09:27 -0400 Subject: [PATCH] Ported Depth Charge to C# --- 31 Depth Charge/csharp/DepthCharge.sln | 25 +++++ 31 Depth Charge/csharp/Game.csproj | 9 ++ 31 Depth Charge/csharp/src/Controller.cs | 85 ++++++++++++++++ 31 Depth Charge/csharp/src/Program.cs | 47 +++++++++ 31 Depth Charge/csharp/src/View.cs | 121 +++++++++++++++++++++++ 5 files changed, 287 insertions(+) create mode 100644 31 Depth Charge/csharp/DepthCharge.sln create mode 100644 31 Depth Charge/csharp/Game.csproj create mode 100644 31 Depth Charge/csharp/src/Controller.cs create mode 100644 31 Depth Charge/csharp/src/Program.cs create mode 100644 31 Depth Charge/csharp/src/View.cs diff --git a/31 Depth Charge/csharp/DepthCharge.sln b/31 Depth Charge/csharp/DepthCharge.sln new file mode 100644 index 00000000..8d56c717 --- /dev/null +++ b/31 Depth Charge/csharp/DepthCharge.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31129.286 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Game", "Game.csproj", "{CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBC9D8D9-9EDE-4D34-A20E-C90D929ABF8F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {738F08DD-89E9-44C5-B5AC-3F21C6AEEFA1} + EndGlobalSection +EndGlobal diff --git a/31 Depth Charge/csharp/Game.csproj b/31 Depth Charge/csharp/Game.csproj new file mode 100644 index 00000000..3028f277 --- /dev/null +++ b/31 Depth Charge/csharp/Game.csproj @@ -0,0 +1,9 @@ + + + + Exe + net5.0 + DepthCharge + + + diff --git a/31 Depth Charge/csharp/src/Controller.cs b/31 Depth Charge/csharp/src/Controller.cs new file mode 100644 index 00000000..7669e67c --- /dev/null +++ b/31 Depth Charge/csharp/src/Controller.cs @@ -0,0 +1,85 @@ +using System; + +namespace DepthCharge +{ + /// + /// Contains functions for reading input from the user. + /// + static class Controller + { + /// + /// Retrives a dimension for the play area from the user. + /// + /// + /// Note that the original BASIC version would allow dimension values + /// of 0 or less. We're doing a little extra validation here in order + /// to avoid strange behaviour. + /// + public static int InputDimension() + { + View.PromptDimension(); + + while (true) + { + if (!Int32.TryParse(Console.ReadLine(), out var dimension)) + View.ShowInvalidNumber(); + else + if (dimension < 1) + View.ShowInvalidDimension(); + else + return dimension; + } + } + + /// + /// Retrieves a set of coordinates from the user. + /// + /// + /// The current trail number. + /// + public static (int x, int y, int depth) InputCoordinates(int trailNumber) + { + View.PromptGuess(trailNumber); + + while (true) + { + var coordinates = Console.ReadLine().Split(','); + + if (coordinates.Length < 3) + View.ShowTooFewCoordinates(); + else + if (coordinates.Length > 3) + View.ShowTooManyCoordinates(); + else + if (!Int32.TryParse(coordinates[0], out var x) || + !Int32.TryParse(coordinates[1], out var y) || + !Int32.TryParse(coordinates[2], out var depth)) + View.ShowInvalidNumber(); + else + return (x, y, depth); + } + } + + /// + /// Retrieves the user's intention to play again (or not). + /// + public static bool InputPlayAgain() + { + View.PromptPlayAgain(); + + while (true) + { + switch (Console.ReadLine()) + { + case "Y": + return true; + case "N": + return false; + default: + View.ShowInvalidYesOrNo(); + break; + } + } + } + } +} diff --git a/31 Depth Charge/csharp/src/Program.cs b/31 Depth Charge/csharp/src/Program.cs new file mode 100644 index 00000000..de3db6d9 --- /dev/null +++ b/31 Depth Charge/csharp/src/Program.cs @@ -0,0 +1,47 @@ +using System; + +namespace DepthCharge +{ + class Program + { + static void Main(string[] args) + { + var random = new Random(); + + View.ShowBanner(); + + var dimension = Controller.InputDimension(); + var maximumGuesses = CalculateMaximumGuesses(); + + View.ShowInstructions(maximumGuesses); + + do + { + View.ShowStartGame(); + + var submarineCoordinates = PlaceSubmarine(); + var trailNumber = 1; + var guess = (0, 0, 0); + + do + { + guess = Controller.InputCoordinates(trailNumber); + if (guess != submarineCoordinates) + View.ShowGuessPlacement(submarineCoordinates, guess); + } + while (guess != submarineCoordinates && trailNumber++ < maximumGuesses); + + View.ShowGameResult(submarineCoordinates, guess, trailNumber); + } + while (Controller.InputPlayAgain()); + + View.ShowFarewell(); + + int CalculateMaximumGuesses() => + (int)Math.Log2(dimension) + 1; + + (int x, int y, int depth) PlaceSubmarine() => + (random.Next(dimension), random.Next(dimension), random.Next(dimension)); + } + } +} diff --git a/31 Depth Charge/csharp/src/View.cs b/31 Depth Charge/csharp/src/View.cs new file mode 100644 index 00000000..71e83a9f --- /dev/null +++ b/31 Depth Charge/csharp/src/View.cs @@ -0,0 +1,121 @@ +using System; + +namespace DepthCharge +{ + /// + /// Contains methods for displaying information to the user. + /// + static class View + { + public static void ShowBanner() + { + Console.WriteLine(" DEPTH CHARGE"); + Console.WriteLine(" CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + } + + public static void ShowInstructions(int maximumGuesses) + { + Console.WriteLine("YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER"); + Console.WriteLine("AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR"); + Console.WriteLine($"MISSION IS TO DESTROY IT. YOU HAVE {maximumGuesses} SHOTS."); + Console.WriteLine("SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A"); + Console.WriteLine("TRIO OF NUMBERS -- THE FIRST TWO ARE THE"); + Console.WriteLine("SURFACE COORDINATES; THE THIRD IS THE DEPTH."); + Console.WriteLine(); + } + + public static void ShowStartGame() + { + Console.WriteLine("GOOD LUCK !"); + Console.WriteLine(); + } + + public static void ShowGuessPlacement((int x, int y, int depth) actual, (int x, int y, int depth) guess) + { + Console.Write("SONAR REPORTS SHOT WAS "); + if (guess.y > actual.y) + Console.Write("NORTH"); + if (guess.y < actual.y) + Console.Write("SOUTH"); + if (guess.x > actual.x) + Console.Write("EAST"); + if (guess.x < actual.x) + Console.Write("WEST"); + if (guess.y != actual.y || guess.x != actual.y) + Console.Write(" AND"); + if (guess.depth > actual.depth) + Console.Write (" TOO LOW."); + if (guess.depth < actual.depth) + Console.Write(" TOO HIGH."); + if (guess.depth == actual.depth) + Console.Write(" DEPTH OK."); + + Console.WriteLine(); + } + + public static void ShowGameResult((int x, int y, int depth) submarineLocation, (int x, int y, int depth) finalGuess, int trailNumber) + { + Console.WriteLine(); + + if (submarineLocation == finalGuess) + { + Console.WriteLine($"B O O M ! ! YOU FOUND IT IN {trailNumber} TRIES!"); + } + else + { + Console.WriteLine("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!"); + Console.WriteLine($"THE SUBMARINE WAS AT {submarineLocation.x}, {submarineLocation.y}, {submarineLocation.depth}"); + } + } + + public static void ShowFarewell() + { + Console.WriteLine ("OK. HOPE YOU ENJOYED YOURSELF."); + } + + public static void ShowInvalidNumber() + { + Console.WriteLine("PLEASE ENTER A NUMBER"); + } + + public static void ShowInvalidDimension() + { + Console.WriteLine("PLEASE ENTER A VALID DIMENSION"); + } + + public static void ShowTooFewCoordinates() + { + Console.WriteLine("TOO FEW COORDINATES"); + } + + public static void ShowTooManyCoordinates() + { + Console.WriteLine("TOO MANY COORDINATES"); + } + + public static void ShowInvalidYesOrNo() + { + Console.WriteLine("PLEASE ENTER Y OR N"); + } + + public static void PromptDimension() + { + Console.Write("DIMENSION OF SEARCH AREA? "); + } + + public static void PromptGuess(int trailNumber) + { + Console.WriteLine(); + Console.Write($"TRIAL #{trailNumber}? "); + } + + public static void PromptPlayAgain() + { + Console.WriteLine(); + Console.Write("ANOTHER GAME (Y OR N)? "); + } + } +}