diff --git a/CodeReviews.Console.MathGame.csproj b/CodeReviews.Console.MathGame.csproj new file mode 100644 index 00000000..aa8486be --- /dev/null +++ b/CodeReviews.Console.MathGame.csproj @@ -0,0 +1,14 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/Controllers/PrintController.cs b/Controllers/PrintController.cs new file mode 100644 index 00000000..34ab77eb --- /dev/null +++ b/Controllers/PrintController.cs @@ -0,0 +1,67 @@ +using Spectre.Console; + +namespace CodeReviews.Console.MathGame.Controllers; + +internal static class PrintController +{ + internal static void Welcome() + { + AnsiConsole.Clear(); + AnsiConsole.MarkupLine("[blue]***********************************************[/]"); + AnsiConsole.MarkupLine("[blue]*** Welcome to the Tiny Math Game ***[/]"); + AnsiConsole.MarkupLine("[blue]***********************************************[/]"); + AnsiConsole.WriteLine("What would you like to do?"); + AnsiConsole.MarkupLine("[green]y: play game[/]"); + AnsiConsole.MarkupLine("[red]n: exit game[/]"); + AnsiConsole.MarkupLine("[yellow]h: view history[/]"); + } + + internal static void PresentRules(int winningScore, int losingScore) + { + AnsiConsole.Clear(); + AnsiConsole.MarkupLine("[yellow]**************************************[/]"); + AnsiConsole.MarkupLine("[yellow]*** Tiny Math Game Rules ***[/]"); + AnsiConsole.MarkupLine("[yellow]**************************************[/]"); + AnsiConsole.WriteLine(); + AnsiConsole.MarkupLine(" - Answer [green]correctly[/] and earn 1 point."); + AnsiConsole.MarkupLine(" - Answer [red]incorrectly[/] and lose 1 point."); + AnsiConsole.MarkupLine($" - To win, reach {winningScore} points."); + AnsiConsole.MarkupLine($" - You will lose if you reach {losingScore} points."); + AnsiConsole.WriteLine(); + Pause(); + } + + internal static void Pause() + { + AnsiConsole.Markup("[blue]Press any key to continue.[/] "); + System.Console.ReadKey(); + } + + internal static void PrintHistory(List history) + { + if (history.Count < 1) + { + AnsiConsole.MarkupLine("You haven't played any games!"); + Pause(); + return; + } + + AnsiConsole.Clear(); + AnsiConsole.MarkupLine("[yellow]******************************[/]"); + AnsiConsole.MarkupLine("[yellow]*** Play History ***[/]"); + AnsiConsole.MarkupLine("[yellow]******************************[/]"); + + var table = new Table(); + + table.AddColumn("[blue]Game[/]"); + table.AddColumn("[blue]Result[/]"); + + for (int i = 0; i < history.Count; i += 1) + { + table.AddRow($"{i + 1}", $"{history[i]}"); + } + + AnsiConsole.Write(table); + Pause(); + } +} diff --git a/Enums.cs b/Enums.cs new file mode 100644 index 00000000..3fcfbeaa --- /dev/null +++ b/Enums.cs @@ -0,0 +1,9 @@ +namespace CodeReviews.Console.MathGame; + +internal enum Operator +{ + Add, + Subtract, + Multiply, + Divide, +} diff --git a/Models/Game.cs b/Models/Game.cs new file mode 100644 index 00000000..5eb15e02 --- /dev/null +++ b/Models/Game.cs @@ -0,0 +1,145 @@ +using CodeReviews.Console.MathGame.Controllers; +using Spectre.Console; + +namespace CodeReviews.Console.MathGame.Models; + +internal class Game +{ + readonly List history = []; + + readonly Dictionary operatorMap = new() + { + { Operator.Add, "+" }, + { Operator.Subtract, "-" }, + { Operator.Divide, "/" }, + { Operator.Multiply, "*" }, + }; + + internal void Initialize() + { + bool keepPlaying = true; + + while (keepPlaying) + { + PrintController.Welcome(); + + string? playerInput = System.Console.ReadLine(); + + switch (playerInput!.ToLower()) + { + case "y": + Play(); + break; + case "n": + keepPlaying = false; + break; + case "h": + PrintController.PrintHistory(history); + break; + default: + AnsiConsole.WriteLine("Your input was not understood. Please try again."); + break; + } + } + + AnsiConsole.WriteLine("Thank you for playing. Goodbye!"); + } + + internal void Play(int winningScore = 5, int losingScore = -3) + { + int playerScore = 0; + + PrintController.PresentRules(winningScore, losingScore); + + while (true) + { + AnsiConsole.Clear(); + + var choice = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Please choose one:") + .AddChoices(Enum.GetValues()) + ); + + int operand1 = Random.Shared.Next(0, 100); + int operand2 = Random.Shared.Next(0, 100); + + if (choice == Operator.Divide) + { + while (operand1 <= operand2 || operand1 % operand2 != 0) + { + operand1 = Random.Shared.Next(0, 100); + operand2 = Random.Shared.Next(1, 100); + } + } + + string question = $"{operand1} {operatorMap[choice]} {operand2} = "; + + AnsiConsole.Write(question); + + string? playerAnswer = System.Console.ReadLine(); + + while (!int.TryParse(playerAnswer, out int _)) + { + AnsiConsole.WriteLine($"Your answer was not understood. Please try again."); + PrintController.Pause(); + AnsiConsole.Clear(); + AnsiConsole.Write(question); + playerAnswer = System.Console.ReadLine(); + } + + if (Convert.ToInt32(playerAnswer) == CalculateAnswer(choice, operand1, operand2)) + { + playerScore += 1; + AnsiConsole.MarkupLine($"[green]Correct![/]"); + } + else + { + playerScore -= 1; + AnsiConsole.MarkupLine($"[yellow]Incorrect...[/]"); + } + + AnsiConsole.WriteLine($"Your score: {playerScore}"); + + if (GameOver(playerScore, winningScore, losingScore)) + { + break; + } + } + } + + internal bool GameOver(int playerScore, int winningScore, int losingScore) + { + bool isGameOver = false; + + if (playerScore >= winningScore) + { + isGameOver = true; + history.Add("Win"); + AnsiConsole.MarkupLine($"[green]Congratulations. You won![/]"); + } + + if (playerScore <= losingScore) + { + isGameOver = true; + history.Add("Loss"); + AnsiConsole.MarkupLine($"[red]You lost... :([/]"); + } + + PrintController.Pause(); + + return isGameOver; + } + + internal static int CalculateAnswer(Operator op, int operand1, int operand2) + { + return op switch + { + Operator.Add => operand1 + operand2, + Operator.Subtract => operand1 - operand2, + Operator.Divide => operand1 / operand2, + Operator.Multiply => operand1 * operand2, + _ => 0, + }; + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 00000000..1cf259f0 --- /dev/null +++ b/Program.cs @@ -0,0 +1,4 @@ +using CodeReviews.Console.MathGame.Models; + +Game game = new(); +game.Initialize(); diff --git a/README.md b/README.md new file mode 100644 index 00000000..971fb0d0 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# MathGame + +A tiny, basic math console game.