Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions MathGame/Game.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MathGame;

public class Game(int score) {
public int _score { get; } = score;
public DateTime _timestamp { get; } = DateTime.Now;
}
21 changes: 21 additions & 0 deletions MathGame/HistoryManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using CSharpCasino.Utils;

namespace MathGame;

public class HistoryManager {
private List<Game> Games { get; } = [];
private readonly IoConsole _console = new();

public void AppendGame(Game game) {
Games.Add(game);
}

public void PrintHistory() {
foreach (Game game in Games) {
_console.PrintColored(AnsiColor.Auto, "//////////////////////////////\n" +
$"{game._timestamp}\nScore: {game._score}\n" +
"//////////////////////////////\n");
}
}

}
10 changes: 10 additions & 0 deletions MathGame/MathGame.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
48 changes: 48 additions & 0 deletions MathGame/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using CSharpCasino.Utils;

namespace MathGame;

/*
* Requirements

- Must consist of asking the player what's the result of a math question (i.e. 9 x 9 = ?),
collecting the input and adding a point in case of a correct answer.
- A game needs to have at least 5 questions
- Integer division only
- Users should be presented with a menu to choose an operation
- You should record previous games in a List
- There should be an option in the menu for the user to visualize a history of previous games
- Once the program is closed the results will be deleted
*/

class MathGame() {
private static readonly IoConsole Console = new();
private static readonly HistoryManager History = new();

public static void Main() {
Run();
}

private static void Run() {
while (true) {
string answer = Console.GetValidInput("Select an option:\nH: history\nP: play game\nE: exit",
["h", "p", "e"]);

switch (answer) {
case "h":
History.PrintHistory();
break;
case "p":
Quiz quiz = new();
History.AppendGame(quiz.PlayGame());
break;
case "e":
Environment.Exit(0);
break;
default:
Console.PrintError("Invalid response");
break;
}
}
}
}
6 changes: 6 additions & 0 deletions MathGame/Quiz/Question.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MathGame;

public class Question(string problem, int answer) {
public readonly string Problem = problem;
public readonly int Answer = answer;
}
29 changes: 29 additions & 0 deletions MathGame/Quiz/QuestionManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace MathGame;

public static class QuestionManager {
public static Question[] CreateQuestion(char op) {
Question[] questions = new Question[5];
int minRand = op is '-' or '+' ? 50 : 5;
int maxRand = op is '-' or '+' ? 100 : 10;

for (int i = 0; i < 5; i++) {
int num1 = Random.Shared.Next(minRand, maxRand);
int num2 = Random.Shared.Next(1, num1);

if (op == '/') {
questions[i] = new Question($"{num1 * num2} {op} {num1}", num2);
} else {
int answer = op switch {
'+' => num1 + num2,
'-' => num1 - num2,
'*' => num1 * num2,
_ => 0
};

questions[i] = new Question($"{num1} {op} {num2}", answer);
}
}

return questions;
}
}
34 changes: 34 additions & 0 deletions MathGame/Quiz/Quiz.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace MathGame;

public class Quiz {
private int _score;
private readonly IoConsole _console = new();

private void HandleQuestion(Question question) {
Console.WriteLine(question.Problem);
int answer = _console.GetIntInput("Your answer: ");

if (question.Answer == answer) {
_score++;
}
}

public Game PlayGame() {
string op = _console.GetValidInput("Enter a operator: + - * /", ["+", "-", "*", "/"]);

Question[] questions = op switch {
"+" => QuestionManager.CreateQuestion('+'),
"-" => QuestionManager.CreateQuestion('-'),
"*" => QuestionManager.CreateQuestion('*'),
"/" => QuestionManager.CreateQuestion('/'),
_ => []
};

foreach (Question question in questions) {
HandleQuestion(question);
}

Console.WriteLine($"Congrats your score was {_score}");
return new Game(_score);
}
}
37 changes: 37 additions & 0 deletions MathGame/Utils/AnsiColor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace CSharpCasino.Utils;

public enum AnsiColor
{
Auto,
Black,
Red,
Green,
Yellow,
Blue,
Purple,
Cyan,
White
}

public static class AnsiColorExtension
{
public static string GetCode(this AnsiColor color)
{
return color switch
{
AnsiColor.Auto => "\u001B[0m",
AnsiColor.Black => "\u001B[30m",
AnsiColor.Red => "\u001B[31m",
AnsiColor.Green => "\u001B[32m",
AnsiColor.Yellow => "\u001B[33m",
AnsiColor.Blue => "\u001B[34m",
AnsiColor.Purple => "\u001B[35m",
AnsiColor.Cyan => "\u001B[36m",
AnsiColor.White => "\u001B[37m",

// Default
_ => throw new ArgumentOutOfRangeException(nameof(color), color,
$"{color} is not a valid {nameof(AnsiColor)}")
};
}
}
162 changes: 162 additions & 0 deletions MathGame/Utils/IOConsole.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
using CSharpCasino.Utils;
using System.Globalization;

namespace MathGame;

public class IoConsole(AnsiColor color)
{
private readonly AnsiColor _color = color;

public IoConsole() : this(AnsiColor.Auto) // Calls Constructor with color parameter
{
}

public void PrintColored(AnsiColor color, string message)
{
Console.WriteLine($"{color.GetCode()}{message}{AnsiColor.Auto.GetCode()}");
}

private void PrintColored(string message)
{
Console.WriteLine($"{_color.GetCode()}{message}{AnsiColor.Auto.GetCode()}");
}

public void PrintError(string message)
{
PrintColored(AnsiColor.Red, message);
}

public void PrintSuccess(string message)
{
PrintColored(AnsiColor.Green, message);
}

private string RepromptInput(string prompt, string message)
{
PrintError($"{message}. Please try again");
return GetStringInput(prompt);
}

private static bool CheckForExit(string input)
{
return input.ToLower() == "exit";
}

public string GetStringInput(string prompt)
{
PrintColored(prompt);
string? input = Console.ReadLine();

while (input == null)
{
input = RepromptInput(prompt, "Invalid Input");
}

if (CheckForExit(input))
{
Environment.Exit(0);
}

return input;
}

public double GetDoubleInput(string prompt)
{
string input = GetStringInput(prompt);
double doubleInput;

while (!double.TryParse(input, out doubleInput))
{
input = RepromptInput(prompt, $"{input} is not a valid decimal number");
}

return doubleInput;
}

private float GetFloatInput(string prompt)
{
string input = GetStringInput(prompt);
float floatInput;

while (!float.TryParse(input, out floatInput))
{
input = RepromptInput(prompt, "Number is not a valid float");
}

return floatInput;
}

public int GetIntInput(string prompt)
{
string input = GetStringInput(prompt);
int intInput;

while (!int.TryParse(input, out intInput))
{
input = RepromptInput(prompt, "Number is not an integer");
}

return intInput;
}

public bool GetBooleanInput(string prompt)
{
string input = GetStringInput(prompt);
bool booleanInput;

while (!bool.TryParse(input, out booleanInput))
{
input = RepromptInput(prompt, "Input is not a boolean");
}

return booleanInput;
}

public bool GetYesNoInput(string prompt)
{
string[] acceptedInputs = ["yes", "no", "y", "n"];
string input = GetValidInput(prompt, acceptedInputs).ToLower();

if(input == "yes" || input == "y")
{
return true;
}

return false;
}

private static int CountDigitsAfterDecimal(float input) {
string inputAsString = input.ToString(CultureInfo.InvariantCulture);

return !inputAsString.Contains('.') ? 0 : inputAsString.Split(".")[1].Length;
}

public float GetMonetaryInput(string prompt)
{
float input = GetFloatInput(prompt);
int digitsAfterDecimal = CountDigitsAfterDecimal(input);

while(digitsAfterDecimal > 2 || input < 0)
{
PrintError("Invalid monetary input");
input = GetFloatInput("Please try again");
digitsAfterDecimal = CountDigitsAfterDecimal(input);
}

return input;
}

public string GetValidInput(string prompt, string[] validOptions)
{
string input = GetStringInput(prompt);


while(!validOptions.Contains(input))
{
PrintError("Invalid input. Please enter a valid input");
input = GetStringInput(prompt);
}

return input;
}
}
Binary file added MathGame/bin/Debug/net8.0/MathGame
Binary file not shown.
23 changes: 23 additions & 0 deletions MathGame/bin/Debug/net8.0/MathGame.deps.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v8.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v8.0": {
"MathGame/1.0.0": {
"runtime": {
"MathGame.dll": {}
}
}
}
},
"libraries": {
"MathGame/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}
Binary file added MathGame/bin/Debug/net8.0/MathGame.dll
Binary file not shown.
Binary file added MathGame/bin/Debug/net8.0/MathGame.pdb
Binary file not shown.
Loading