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
3 changes: 3 additions & 0 deletions MathGame.ivangar/MathGame.ivangar.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Solution>
<Project Path="MathGame.ivangar/MathGame.ivangar.csproj" />
</Solution>
9 changes: 9 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/Enums/MainMenuOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace MathGame.ivangar.Enums
{
public enum MainMenuItems
{
Play = 1,
Exit = 2,
History = 3
}
}
154 changes: 154 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/Game.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using MathGame.ivangar.Validators;

namespace MathGame.ivangar
{
public class Game : IGame
{
private static readonly char[] _operators = ['+', '-', '*', '/'];

private readonly int _maxNumberOfQuestions;
private readonly Random _random;

// State fields
private int _currentQuestionNumber;
private int _score;
private int _result;
private int _op1, _op2;

public int UserAnswer { get; set; }

private readonly List<MathOperation> _gameHistory = new();

public Game()
{
_random = new Random();
_maxNumberOfQuestions = _random.Next(5, 11);
_currentQuestionNumber = 1;
_score = 0;
}

public void Play()
{
bool continueGame = true;
char operation = Menu.StartGamePrompt(_maxNumberOfQuestions, _currentQuestionNumber);
GameValidator validator = new GameValidator();

while (continueGame)
{
while (!Array.Exists(_operators, o => o == operation))
{
operation = Menu.PrintGameOptions(invalid: true);
}

PerformMathOperation(operation);
validator.ValidateAnswer(_result, UserAnswer, ref _score);

_currentQuestionNumber++;

if (_currentQuestionNumber > _maxNumberOfQuestions)
break;

continueGame = validator.ValidateContinueGame(Menu.ContinueGamePrompt());

if (continueGame)
operation = Menu.PrintGameOptions(false, _currentQuestionNumber);
}

FinishGame();
}

public void PerformMathOperation(char operation)
{
_op1 = operation == '/' ? _random.Next(1, 101) : _random.Next(0, 101);
_op2 = operation == '/' ? GetDivisor() : _random.Next(0, 101);
CalculateResult(operation);

Console.Write($"\n\nWhat is the result of:\n{_op1} {operation} {_op2} = ");
string? answer = Console.ReadLine();

int parsedAnswer;
while (!int.TryParse(answer, out parsedAnswer))
{
Console.WriteLine("Invalid input. Please enter a valid number: ");
answer = Console.ReadLine();
}

UserAnswer = parsedAnswer;

_gameHistory.Add(new MathOperation
{
OperandA = _op1,
OperandB = _op2,
Operation = operation,
UserAnswer = UserAnswer,
ScoreMark = UserAnswer == _result ? "Correct" : "Incorrect"
}
);
}

public void PrintGameHistory()
{
Console.WriteLine("\nGame History:\n");

foreach (var (index, operation) in _gameHistory.Select((o, i) => (i, o)))
{
Console.WriteLine($"{index + 1}. {operation}");
}

Console.WriteLine("\n\n");
}

public void PrintScore()
{
var numberOfQuestionsAnswered = _currentQuestionNumber - 1;
decimal finalScore = Math.Round((decimal)_score * 100 / numberOfQuestionsAnswered, MidpointRounding.AwayFromZero);

Console.WriteLine($"You answered correctly {_score}/{numberOfQuestionsAnswered} questions.");
Console.WriteLine($"Your score is: {finalScore}%");
}

public void FinishGame()
{
Console.WriteLine("\n\nGame Over!\n");
PrintGameHistory();
PrintScore();
}

#region Private Methods
private void CalculateResult(char operation)
{
_result = operation switch
{
'+' => _op1 + _op2,
'-' => _op1 - _op2,
'*' => _op1 * _op2,
'/' => _op1 / _op2,
_ => throw new InvalidOperationException("Invalid operation")
};
}

/*Get a list of potential divisors (without remainders) and return randomly any divisor */
private int GetDivisor()
{
if (IsPrimeNumber(_op1))
return 1;

var divisors = Enumerable
.Range(1, _op1)
.Where(x => _op1 % x == 0)
.ToList();

return divisors[_random.Next(0, divisors.Count)];
}

private static bool IsPrimeNumber(int number)
{
var primes = Enumerable.Range(2, 100)
.Where(n => !Enumerable.Range(2, (int)Math.Sqrt(n) - 1).Any(d => n % d == 0))
.ToList();

return primes.Contains(number);
}
#endregion
}
}
80 changes: 80 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/GameCenter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using MathGame.ivangar.Enums;
using MathGame.ivangar.Validators;

namespace MathGame.ivangar
{
public class GameCenter
{
private readonly List<Game> _games = [];
private bool _exitGame = false;

public void Start()
{
string? menuOption = Menu.GameIntro();

while (true)
{
while (!MenuValidator.ValidateMainOptions(menuOption))
{
menuOption = Console.ReadLine();
}

Enum.TryParse<MainMenuItems>(menuOption!.Trim(), ignoreCase: true, out MainMenuItems option);

switch (option)
{
case MainMenuItems.Play:
PlayGame();
break;
case MainMenuItems.History:
MathGameHistory();
break;
case MainMenuItems.Exit:
_exitGame = true;
Exit();
break;
}

if (_exitGame)
break;

Menu.PrintMenu();
menuOption = Console.ReadLine();
}
}

public void PlayGame()
{
var mathGame = new Game();
mathGame.Play();
_games.Add(mathGame);
}

public void MathGameHistory()
{
if (_games.Count == 0)
Console.WriteLine("\nYou don't have any registered game played.\n");

foreach (var (index, game) in _games.Select((g, i) => (i, g)))
{
Console.WriteLine($"\n\t\tGame #{index + 1}\n");
game.PrintGameHistory();
game.PrintScore();
}
}

public void Exit()
{
if (_games.Count != 0)
{
Console.WriteLine("\nThank you for playing the Math Game. Here is your Math Game history\n\n");
MathGameHistory();
}

else
Console.WriteLine("\nThank you for playing the Math Game.");

Console.WriteLine("\nHave a nice day!");
}
}
}
10 changes: 10 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/IGame.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace MathGame.ivangar
{
public interface IGame
{
void Play();
void FinishGame();
void PrintGameHistory();
void PrintScore();
}
}
10 changes: 10 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/MathGame.ivangar.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>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
17 changes: 17 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/MathOperation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace MathGame.ivangar
{
public record MathOperation
{
public int OperandA { get; init; }
public int OperandB { get; init; }
public char Operation { get; init; }
public int UserAnswer { get; init; }
public string ScoreMark { get; init; } = string.Empty;

public override string ToString()
{
var leftHandSide = $"{OperandA} {Operation} {OperandB} = {UserAnswer}";
return $"{leftHandSide,-20} {ScoreMark,-5}";
}
}
}
64 changes: 64 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/Menu.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using MathGame.ivangar.Enums;

namespace MathGame.ivangar
{
public static class Menu
{
public static string? GameIntro()
{
Console.WriteLine("\nWelcome to the Math Game!");
Console.WriteLine("We are going to test your math skills!");
PrintMenu();
return Console.ReadLine();
}

public static void PrintMenu(bool invalid = false)
{
if (invalid)
Console.WriteLine("\nInvalid input.");

Console.WriteLine("\nPlease choose any of the following options (you have to type the word, i.e. 'play'):\n");
PrintMenuOptions();
}

public static void PrintMenuOptions()
{
foreach (MainMenuItems option in Enum.GetValues(typeof(MainMenuItems)))
Console.WriteLine($"\t{(int)option}. {option}");

Console.WriteLine("\n");
}

public static char StartGamePrompt(int maxNumberOfQuestions, int currentQuestionNumber)
{
Console.WriteLine($"\nThis game has {maxNumberOfQuestions} questions.");
return PrintGameOptions(invalid: false, currentQuestionNumber);
}

public static char PrintGameOptions(bool invalid = false, int currentQuestionNumber = -1)
{
if (invalid)
Console.Write("\nInvalid operation selected! ");

if (currentQuestionNumber > 0)
Console.WriteLine($"\n\n\tQuestion #{currentQuestionNumber}\n");

Console.Write("Choose an operation (type any of the following options: +, -, *, /): ");
ConsoleKeyInfo keyInfo = Console.ReadKey();
return keyInfo.KeyChar;
}

public static char ContinueGamePrompt(bool invalid = false)
{
if (invalid)
Console.Write("\nInvalid input. Please enter 'y' or 'n': ");

else
Console.Write("\nWould you like to continue the game? (y/n): ");

ConsoleKeyInfo keyInfo = Console.ReadKey();
char continueInput = char.ToLower(keyInfo.KeyChar);
return continueInput;
}
}
}
4 changes: 4 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using MathGame.ivangar;

var gameCenter = new GameCenter();
gameCenter.Start();
27 changes: 27 additions & 0 deletions MathGame.ivangar/MathGame.ivangar/Validators/GameValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace MathGame.ivangar.Validators
{
public class GameValidator
{
public void ValidateAnswer(int result, int userAnswer, ref int score)
{
if (result == userAnswer)
{
Console.WriteLine("Correct Answer!");
score++;
}

else
Console.WriteLine($"Incorrect Answer! The correct answer is: {result}");
}

public bool ValidateContinueGame(char input)
{
while (input != 'y' && input != 'n')
{
input = Menu.ContinueGamePrompt(invalid: true);
}

return input == 'y';
}
}
}
Loading