From dedca6ac0d3662863fa3721fb0ad4f08b00355b5 Mon Sep 17 00:00:00 2001 From: Flow Date: Sun, 9 Jan 2022 18:51:34 +0100 Subject: [PATCH] Add pizza implementation in c# --- 69_Pizza/csharp/Pizza/CustomerMap.cs | 131 ++++++++ 69_Pizza/csharp/Pizza/Pizza.csproj | 10 + 69_Pizza/csharp/Pizza/Pizza.sln | 25 ++ 69_Pizza/csharp/Pizza/PizzaGame.cs | 296 ++++++++++++++++++ 69_Pizza/csharp/Pizza/Program.cs | 11 + .../csharp/Pizza/StringBuilderExtensions.cs | 21 ++ 6 files changed, 494 insertions(+) create mode 100644 69_Pizza/csharp/Pizza/CustomerMap.cs create mode 100644 69_Pizza/csharp/Pizza/Pizza.csproj create mode 100644 69_Pizza/csharp/Pizza/Pizza.sln create mode 100644 69_Pizza/csharp/Pizza/PizzaGame.cs create mode 100644 69_Pizza/csharp/Pizza/Program.cs create mode 100644 69_Pizza/csharp/Pizza/StringBuilderExtensions.cs diff --git a/69_Pizza/csharp/Pizza/CustomerMap.cs b/69_Pizza/csharp/Pizza/CustomerMap.cs new file mode 100644 index 00000000..ee991de3 --- /dev/null +++ b/69_Pizza/csharp/Pizza/CustomerMap.cs @@ -0,0 +1,131 @@ +using System.Text; + +namespace Pizza +{ + internal class CustomerMap + { + private readonly int _mapSize; + private readonly string[,] _customerMap; + + public CustomerMap(int mapSize) + { + _mapSize = mapSize; + _customerMap = GenerateCustomerMap(); + } + + /// + /// Gets customer on position X, Y. + /// + /// Represents X position. + /// Represents Y position. + /// If positions is valid then returns customer name otherwise returns empty string. + public string GetCustomerOnPosition(int x, int y) + { + if(IsPositionOutOfRange(x, y)) + { + return string.Empty; + } + + return _customerMap[y, x]; + } + + /// + /// Overridden ToString for getting text representation of customers map. + /// + /// Text representation of customers map. + public override string ToString() + { + int verticalSpace = 4; + int horizontalSpace = 5; + + var mapToDisplay = new StringBuilder(); + + AppendXLine(mapToDisplay, horizontalSpace); + + for (int i = _customerMap.GetLength(0) - 1; i >= 0; i--) + { + mapToDisplay.AppendLine("-", verticalSpace); + mapToDisplay.Append($"{i + 1}"); + mapToDisplay.Append(' ', horizontalSpace); + + for (var j = 0; j < _customerMap.GetLength(1); j++) + { + mapToDisplay.Append($"{_customerMap[i, j]}"); + mapToDisplay.Append(' ', horizontalSpace); + } + + mapToDisplay.Append($"{i + 1}"); + mapToDisplay.Append(' ', horizontalSpace); + mapToDisplay.Append(Environment.NewLine); + } + + mapToDisplay.AppendLine("-", verticalSpace); + + AppendXLine(mapToDisplay, horizontalSpace); + + return mapToDisplay.ToString(); + } + + /// + /// Checks if position is out of range or not. + /// + /// Represents X position. + /// Represents Y position. + /// True if position is out of range otherwise false. + private bool IsPositionOutOfRange(int x, int y) + { + return + x < 0 || x > _mapSize - 1 || + y < 0 || y > _mapSize - 1; + } + + /// + /// Generates array which represents customers map. + /// + /// Returns customers map. + private string[,] GenerateCustomerMap() + { + string[,] customerMap = new string[_mapSize, _mapSize]; + string[] customerNames = GetCustomerNames(_mapSize * _mapSize); + int currentCustomerNameIndex = 0; + + for (int i = 0; i < customerMap.GetLength(0); i++) + { + for (int j = 0; j < customerMap.GetLength(1); j++) + { + customerMap[i, j] = customerNames[currentCustomerNameIndex++].ToString(); + } + } + + return customerMap; + } + + /// + /// Generates customer names. Names are represented by alphanumerics from 'A'. Name of last customer depends on passed parameter. + /// + /// How many customers need to be generated. + /// List of customer names. + private static string[] GetCustomerNames(int numberOfCustomers) + { + // returns ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"]; + return Enumerable.Range(65, numberOfCustomers).Select(c => ((Char)c).ToString()).ToArray(); + } + + /// + /// Appends line with X coordinates. + /// + /// Current map where a new line will be appended. + /// Number of horizontal delimiters which will be added between each coordination. + private void AppendXLine(StringBuilder mapToDisplay, int horizontalSpace) + { + mapToDisplay.Append(' '); + mapToDisplay.Append('-', horizontalSpace); + for (var i = 0; i < _customerMap.GetLength(0); i++) + { + mapToDisplay.Append($"{i + 1}"); + mapToDisplay.Append('-', horizontalSpace); + } + mapToDisplay.Append(Environment.NewLine); + } + } +} \ No newline at end of file diff --git a/69_Pizza/csharp/Pizza/Pizza.csproj b/69_Pizza/csharp/Pizza/Pizza.csproj new file mode 100644 index 00000000..74abf5c9 --- /dev/null +++ b/69_Pizza/csharp/Pizza/Pizza.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/69_Pizza/csharp/Pizza/Pizza.sln b/69_Pizza/csharp/Pizza/Pizza.sln new file mode 100644 index 00000000..91785a8c --- /dev/null +++ b/69_Pizza/csharp/Pizza/Pizza.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pizza", "Pizza.csproj", "{6AABE938-39C4-4661-AEA5-23CECA1DFEE1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6AABE938-39C4-4661-AEA5-23CECA1DFEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6AABE938-39C4-4661-AEA5-23CECA1DFEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6AABE938-39C4-4661-AEA5-23CECA1DFEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6AABE938-39C4-4661-AEA5-23CECA1DFEE1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8F7E9FAD-38C5-47A2-B5CA-2B6E5947B982} + EndGlobalSection +EndGlobal diff --git a/69_Pizza/csharp/Pizza/PizzaGame.cs b/69_Pizza/csharp/Pizza/PizzaGame.cs new file mode 100644 index 00000000..22c78e05 --- /dev/null +++ b/69_Pizza/csharp/Pizza/PizzaGame.cs @@ -0,0 +1,296 @@ +namespace Pizza +{ + internal class PizzaGame + { + private const int CustomerMapSize = 4; + private readonly CustomerMap _customerMap = new CustomerMap(CustomerMapSize); + + /// + /// Starts game. Main coordinator for pizza game. + /// It is responsible for showing information, getting data from user and starting to delivery pizza. + /// + public void Play() + { + ShowHeader(); + + string playerName = GetPlayerName(); + + ShowIntroduction(playerName); + ShowMap(); + + if (AskForMoreDirections()) + { + ShowMoreDirections(playerName); + + var playerUnderstands = AskIfPlayerUnderstand(); + if (!playerUnderstands) + { + return; + } + } + + StartDelivery(playerName); + EndDelivery(playerName); + } + + /// + /// Starts with pizza delivering to customers. + /// Every 5 deliveries it is asking user whether want to continue in delivering. + /// + /// Player name which was filled by user. + private void StartDelivery(string playerName) + { + var numberOfDeliveredPizzas = 0; + while (true) + { + numberOfDeliveredPizzas++; + string deliverPizzaToCustomer = GetRandomCustomer(); + + WriteEmptyLine(); + Console.WriteLine($"HELLO {playerName}'S PIZZA. THIS IS {deliverPizzaToCustomer}."); + Console.WriteLine("\tPLEASE SEND A PIZZA."); + + DeliverPizzaByPlayer(playerName, deliverPizzaToCustomer); + + if (numberOfDeliveredPizzas % 5 == 0) + { + bool playerWantToDeliveryMorePizzas = AskQuestionWithYesNoResponse("DO YOU WANT TO DELIVER MORE PIZZAS?"); + if (!playerWantToDeliveryMorePizzas) + { + WriteEmptyLine(); + break; + } + } + } + } + + /// + /// Gets random customer for which pizza should be delivered. + /// + /// Customer name. + private string GetRandomCustomer() + { + int randomPositionOnX = Random.Shared.Next(0, CustomerMapSize); + int randomPositionOnY = Random.Shared.Next(0, CustomerMapSize); + + return _customerMap.GetCustomerOnPosition(randomPositionOnX, randomPositionOnY); + } + + /// + /// Delivers pizza to customer by player. It verifies whether player was delivering pizza to correct customer. + /// + /// Player name which was filled by user. + /// Customer name which order pizza. + private void DeliverPizzaByPlayer(string playerName, string deliverPizzaToCustomer) + { + while (true) + { + string userInput = GetPlayerInput($"\tDRIVER TO {playerName}: WHERE DOES {deliverPizzaToCustomer} LIVE?"); + var deliveredToCustomer = GetCustomerFromPlayerInput(userInput); + if (string.IsNullOrEmpty(deliveredToCustomer)) + { + deliveredToCustomer = "UNKNOWN CUSTOMER"; + } + + if (deliveredToCustomer.Equals(deliverPizzaToCustomer)) + { + Console.WriteLine($"HELLO {playerName}. THIS IS {deliverPizzaToCustomer}, THANKS FOR THE PIZZA."); + break; + } + + Console.WriteLine($"THIS IS {deliveredToCustomer}. I DID NOT ORDER A PIZZA."); + Console.WriteLine($"I LIVE AT {userInput}"); + } + } + + /// + /// Gets customer name by user input with customer coordinations. + /// + /// Input from users - it should represent customer coordination separated by ','. + /// If coordinations are correct and customer exists then returns true otherwise false. + private string GetCustomerFromPlayerInput(string userInput) + { + var pizzaIsDeliveredToPosition = userInput? + .Split(',') + .Select(i => int.TryParse(i, out var customerPosition) ? (customerPosition - 1) : -1) + .Where(i => i != -1) + .ToArray() ?? Array.Empty(); + if (pizzaIsDeliveredToPosition.Length != 2) + { + return string.Empty; + } + + return _customerMap.GetCustomerOnPosition(pizzaIsDeliveredToPosition[0], pizzaIsDeliveredToPosition[1]); + } + + /// + /// Shows game header in console. + /// + private void ShowHeader() + { + Console.WriteLine("PIZZA".PadLeft(22)); + Console.WriteLine("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + WriteEmptyLine(3); + Console.WriteLine("PIZZA DELIVERY GAME"); + WriteEmptyLine(); + } + + /// + /// Asks user for name which will be used in game. + /// + /// Player name. + private string GetPlayerName() + { + return GetPlayerInput("WHAT IS YOUR FIRST NAME:"); + } + + /// + /// Shows game introduction in console + /// + /// Player name which was filled by user. + private void ShowIntroduction(string playerName) + { + Console.WriteLine($"HI, {playerName}. IN THIS GAME YOU ARE TO TAKE ORDERS"); + Console.WriteLine("FOR PIZZAS. THEN YOU ARE TO TELL A DELIVERY BOY"); + Console.WriteLine("WHERE TO DELIVER THE ORDERED PIZZAS."); + WriteEmptyLine(2); + } + + /// + /// Shows customers map in console. In this method is used overridden method 'ToString' for getting text representation of customers map. + /// + private void ShowMap() + { + Console.WriteLine("MAP OF THE CITY OF HYATTSVILLE"); + WriteEmptyLine(); + + Console.WriteLine(_customerMap.ToString()); + + Console.WriteLine("THE OUTPUT IS A MAP OF THE HOMES WHERE"); + Console.WriteLine("YOU ARE TO SEND PIZZAS."); + WriteEmptyLine(); + Console.WriteLine("YOUR JOB IS TO GIVE A TRUCK DRIVER"); + Console.WriteLine("THE LOCATION OR COORDINATES OF THE"); + Console.WriteLine("HOME ORDERING THE PIZZA."); + WriteEmptyLine(); + } + + /// + /// Asks user if needs more directions. + /// + /// True if user need more directions otherwise false. + private bool AskForMoreDirections() + { + var playerNeedsMoreDirections = AskQuestionWithYesNoResponse("DO YOU NEED MORE DIRECTIONS?"); + WriteEmptyLine(); + + return playerNeedsMoreDirections; + } + + /// + /// Shows more directions. + /// + /// Player name which was filled by user. + private void ShowMoreDirections(string playerName) + { + Console.WriteLine("SOMEBODY WILL ASK FOR A PIZZA TO BE"); + Console.WriteLine("DELIVERED. THEN A DELIVERY BOY WILL"); + Console.WriteLine("ASK YOU FOR THE LOCATION."); + Console.WriteLine("\tEXAMPLE:"); + Console.WriteLine("THIS IS J. PLEASE SEND A PIZZA."); + Console.WriteLine($"DRIVER TO {playerName}. WHERE DOES J LIVE?"); + Console.WriteLine("YOUR ANSWER WOULD BE 2,3"); + } + + /// + /// Asks user if understands to instructions. + /// + /// True if user understand otherwise false. + private bool AskIfPlayerUnderstand() + { + var playerUnderstands = AskQuestionWithYesNoResponse("UNDERSTAND?"); + if (!playerUnderstands) + { + Console.WriteLine("THIS JOB IS DEFINITELY TOO DIFFICULT FOR YOU. THANKS ANYWAY"); + return false; + } + + WriteEmptyLine(); + Console.WriteLine("GOOD. YOU ARE NOW READY TO START TAKING ORDERS."); + WriteEmptyLine(); + Console.WriteLine("GOOD LUCK!!"); + WriteEmptyLine(); + + return true; + } + + /// + /// Shows message about ending delivery in console. + /// + /// Player name which was filled by user. + private void EndDelivery(string playerName) + { + Console.WriteLine($"O.K. {playerName}, SEE YOU LATER!"); + WriteEmptyLine(); + } + + /// + /// Gets input from user. + /// + /// Question which is displayed in console. + /// User input. + private string GetPlayerInput(string question) + { + Console.Write($"{question} "); + + while (true) + { + var userInput = Console.ReadLine(); + if (!string.IsNullOrWhiteSpace(userInput)) + { + return userInput; + } + } + } + + /// + /// Asks user with required resposne 'YES', 'Y, 'NO', 'N'. + /// + /// Question which is displayed in console. + /// True if user write 'YES', 'Y'. False if user write 'NO', 'N'. + private static bool AskQuestionWithYesNoResponse(string question) + { + var possitiveResponse = new string[] { "Y", "YES" }; + var negativeResponse = new string[] { "N", "NO" }; + var validUserInputs = possitiveResponse.Concat(negativeResponse); + + Console.Write($"{question} "); + + string? userInput; + while (true) + { + userInput = Console.ReadLine(); + if (!string.IsNullOrWhiteSpace(userInput) && validUserInputs.Contains(userInput.ToUpper())) + { + break; + } + + Console.Write($"'YES' OR 'NO' PLEASE, NOW THEN, {question} "); + } + + return possitiveResponse.Contains(userInput.ToUpper()); + } + + /// + /// Writes empty line in console. + /// + /// Number of empty lines which will be written in console. Parameter is optional and default value is 1. + private void WriteEmptyLine(int numberOfEmptyLines = 1) + { + for (int i = 0; i < numberOfEmptyLines; i++) + { + Console.WriteLine(); + } + } + } +} \ No newline at end of file diff --git a/69_Pizza/csharp/Pizza/Program.cs b/69_Pizza/csharp/Pizza/Program.cs new file mode 100644 index 00000000..6c21fad0 --- /dev/null +++ b/69_Pizza/csharp/Pizza/Program.cs @@ -0,0 +1,11 @@ +namespace Pizza +{ + internal class Program + { + static void Main(string[] args) + { + var pizzaGame = new PizzaGame(); + pizzaGame.Play(); + } + } +} \ No newline at end of file diff --git a/69_Pizza/csharp/Pizza/StringBuilderExtensions.cs b/69_Pizza/csharp/Pizza/StringBuilderExtensions.cs new file mode 100644 index 00000000..f7cb828d --- /dev/null +++ b/69_Pizza/csharp/Pizza/StringBuilderExtensions.cs @@ -0,0 +1,21 @@ +using System.Text; + +namespace Pizza +{ + internal static class StringBuilderExtensions + { + /// + /// Extensions for adding new lines of specific value. + /// + /// Extended class. + /// Value which will be repeated. + /// Number of lines that will be appended. + public static void AppendLine(this StringBuilder stringBuilder, string value, int numberOfLines) + { + for (int i = 0; i < numberOfLines; i++) + { + stringBuilder.AppendLine(value); + } + } + } +} \ No newline at end of file