diff --git a/djimon44.MathGame/djimon44.MathGame.slnx b/djimon44.MathGame/djimon44.MathGame.slnx
new file mode 100644
index 00000000..3911293f
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame.slnx
@@ -0,0 +1,3 @@
+
+
+
diff --git a/djimon44.MathGame/djimon44.MathGame/Enums/Difficulty.cs b/djimon44.MathGame/djimon44.MathGame/Enums/Difficulty.cs
new file mode 100644
index 00000000..6ccfe2d5
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Enums/Difficulty.cs
@@ -0,0 +1,8 @@
+namespace MathGame.Enums;
+
+public enum Difficulty
+{
+ Easy,
+ Medium,
+ Hard
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Enums/GameType.cs b/djimon44.MathGame/djimon44.MathGame/Enums/GameType.cs
new file mode 100644
index 00000000..9bd04ec2
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Enums/GameType.cs
@@ -0,0 +1,10 @@
+namespace MathGame.Enums;
+
+public enum GameType
+{
+ Addition,
+ Subtraction,
+ Multiplication,
+ Division,
+ Random
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Interfaces/IGameEngine.cs b/djimon44.MathGame/djimon44.MathGame/Interfaces/IGameEngine.cs
new file mode 100644
index 00000000..0bfc6627
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Interfaces/IGameEngine.cs
@@ -0,0 +1,9 @@
+using MathGame.Enums;
+using MathGame.Models;
+
+namespace MathGame.Interfaces;
+
+public interface IGameEngine
+{
+ GameSession Play(GameType game, Difficulty difficulty);
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Interfaces/IQuestionGenerator.cs b/djimon44.MathGame/djimon44.MathGame/Interfaces/IQuestionGenerator.cs
new file mode 100644
index 00000000..f3210336
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Interfaces/IQuestionGenerator.cs
@@ -0,0 +1,9 @@
+using MathGame.Enums;
+using MathGame.Models;
+
+namespace MathGame.Interfaces;
+
+public interface IQuestionGenerator
+{
+ MathQuestion Generate(GameType game, DifficultySettings difficulty);
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Models/DifficultySettings.cs b/djimon44.MathGame/djimon44.MathGame/Models/DifficultySettings.cs
new file mode 100644
index 00000000..36c0a224
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Models/DifficultySettings.cs
@@ -0,0 +1,13 @@
+namespace MathGame.Models;
+
+public class DifficultySettings
+{
+ public int MaxValue { get; }
+ public int TimeLimitSeconds { get; }
+
+ public DifficultySettings(int maxValue, int timeLimitSeconds)
+ {
+ MaxValue = maxValue;
+ TimeLimitSeconds = timeLimitSeconds;
+ }
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Models/GameSession.cs b/djimon44.MathGame/djimon44.MathGame/Models/GameSession.cs
new file mode 100644
index 00000000..4ae1ea6b
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Models/GameSession.cs
@@ -0,0 +1,25 @@
+using MathGame.Enums;
+
+namespace MathGame.Models;
+
+public class GameSession
+{
+ // Fields:
+ public DateTime PlayedOn { get; }
+ public GameType Game { get; }
+ public int Score { get; }
+ public int TotalQuestions { get; }
+ public TimeSpan Duration { get; }
+ public Difficulty Difficulty { get; }
+
+ // Constructor
+ public GameSession(GameType game, int score, int totalQuestions, TimeSpan duration, Difficulty difficulty)
+ {
+ PlayedOn = DateTime.Now;
+ Game = game;
+ Score = score;
+ TotalQuestions = totalQuestions;
+ Duration = duration;
+ Difficulty = difficulty;
+ }
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Models/MathQuestion.cs b/djimon44.MathGame/djimon44.MathGame/Models/MathQuestion.cs
new file mode 100644
index 00000000..1f2ce21a
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Models/MathQuestion.cs
@@ -0,0 +1,54 @@
+using MathGame.Enums;
+
+namespace MathGame.Models;
+
+public class MathQuestion
+{
+ // Fields:
+ public int OperandA { get; }
+ public int OperandB { get; }
+ public GameType Game { get; }
+ public int CorrectAnswer { get; }
+ public int? PlayerAnswer { get; private set; } // ? means it can be null; private set means only changable within the class
+
+ public bool IsAnswered
+ {
+ get { return PlayerAnswer.HasValue; }
+ }
+
+ public bool IsCorrect
+ {
+ get { return IsAnswered && (PlayerAnswer == CorrectAnswer); }
+ }
+
+ // Constructor:
+ public MathQuestion(int operandA, int operandB, GameType game)
+ {
+ OperandA = operandA;
+ OperandB = operandB;
+ Game = game;
+ CorrectAnswer = ComputeAnswer();
+ }
+
+ // Methods
+ public void RecordAnswer(int answer)
+ {
+ this.PlayerAnswer = answer;
+ }
+
+ private int ComputeAnswer() {
+ switch (Game) {
+ case GameType.Addition:
+ return OperandA + OperandB;
+ case GameType.Subtraction:
+ return OperandA - OperandB;
+ case GameType.Multiplication:
+ return OperandA * OperandB;
+ case GameType.Division:
+ return OperandA / OperandB;
+
+ default:
+ throw new InvalidOperationException("Unknown Operation.");
+ }
+ }
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Program.cs b/djimon44.MathGame/djimon44.MathGame/Program.cs
new file mode 100644
index 00000000..009dfedb
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Program.cs
@@ -0,0 +1,80 @@
+using MathGame.Enums;
+using MathGame.Models;
+using MathGame.Services;
+using MathGame.UI;
+
+var ui = new ConsoleUI();
+var generator = new QuestionGenerator();
+var history = new GameHistory();
+var engine = new GameEngine(generator, ui);
+
+while (true)
+{
+ string choiceGame = ui.ShowMainMenu();
+
+ if (choiceGame == "0") break;
+
+ if (choiceGame == "5")
+ {
+ ui.DisplayHistory(history.GetAll());
+ continue;
+ }
+
+ GameType game;
+
+ switch (choiceGame)
+ {
+ case "1":
+ game = GameType.Addition;
+ break;
+ case "2":
+ game = GameType.Subtraction;
+ break;
+ case "3":
+ game = GameType.Multiplication;
+ break;
+ case "4":
+ game = GameType.Division;
+ break;
+ case "r":
+ game = GameType.Random;
+ break;
+ default:
+ // Use a "sentinel" value to indicate something went wrong
+ game = (GameType)(-1);
+ break;
+ }
+
+ if ((int)game == -1)
+ {
+ Console.WriteLine("Invalid choice. Press any key...");
+ Console.ReadKey();
+ continue;
+ }
+
+ string choiceDifficulty = ui.ShowDifficultyMenu();
+ Difficulty difficulty;
+
+ switch (choiceDifficulty)
+ {
+ case "1":
+ difficulty = Difficulty.Easy;
+ break;
+ case "2":
+ difficulty = Difficulty.Medium;
+ break;
+ case "3":
+ difficulty= Difficulty.Hard;
+ break;
+
+ default:
+ Console.WriteLine("\nInvalid choice. Press any key to try again...");
+ Console.ReadKey();
+ continue;
+ }
+
+ GameSession session = engine.Play(game, difficulty);
+ history.Add(session);
+}
+
+Console.WriteLine("Thanks for playing!");
\ No newline at end of file
diff --git a/djimon44.MathGame/djimon44.MathGame/Services/GameEngine.cs b/djimon44.MathGame/djimon44.MathGame/Services/GameEngine.cs
new file mode 100644
index 00000000..10bb16c2
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Services/GameEngine.cs
@@ -0,0 +1,83 @@
+using System.Diagnostics;
+using MathGame.Enums;
+using MathGame.Interfaces;
+using MathGame.Models;
+using MathGame.UI;
+
+namespace MathGame.Services;
+
+public class GameEngine : IGameEngine
+{
+ private const int TotalQuestions = 5;
+
+ private readonly QuestionGenerator _generator;
+ private readonly ConsoleUI _ui;
+
+ public GameEngine(QuestionGenerator generator, ConsoleUI ui)
+ {
+ _generator = generator;
+ _ui = ui;
+ }
+
+ public GameSession Play(GameType game, Difficulty difficulty)
+ {
+ int score = 0;
+ DifficultySettings settings = GetDifficultySettings(difficulty);
+ Stopwatch totalSessionTime = Stopwatch.StartNew();
+
+ for (int i = 0; i < TotalQuestions; i++)
+ {
+ MathQuestion question = _generator.Generate(game, settings);
+
+ _ui.DisplayQuestion(question, i + 1, TotalQuestions, settings.TimeLimitSeconds);
+
+ Stopwatch questionTimer = Stopwatch.StartNew();
+ int playerAnswer = _ui.GetPlayerAnswer();
+ questionTimer.Stop();
+
+ bool outOfTime = questionTimer.Elapsed.TotalSeconds > settings.TimeLimitSeconds;
+
+ if (outOfTime)
+ {
+ _ui.DisplayFeedback(correct: false, question.CorrectAnswer);
+ question.RecordAnswer(int.MinValue); // flag as false answer
+ }
+ else
+ {
+ question.RecordAnswer(playerAnswer);
+
+ if (question.IsCorrect)
+ {
+ score++;
+ _ui.DisplayFeedback(correct: true);
+ }
+ else
+ {
+ _ui.DisplayFeedback(correct: false, question.CorrectAnswer);
+ }
+ }
+ }
+
+ totalSessionTime.Stop();
+
+ var session = new GameSession(game, score, TotalQuestions, totalSessionTime.Elapsed, difficulty);
+ _ui.DisplaySummary(session);
+ return session;
+ }
+
+ private static DifficultySettings GetDifficultySettings(Difficulty difficulty)
+ {
+ switch (difficulty)
+ {
+ case Difficulty.Easy:
+ return new DifficultySettings(10, 60);
+ case Difficulty.Medium:
+ return new DifficultySettings(20, 90);
+ case Difficulty.Hard:
+ return new DifficultySettings(35, 90);
+
+ default:
+ return new DifficultySettings(10, 60);
+ }
+ }
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Services/GameHistory.cs b/djimon44.MathGame/djimon44.MathGame/Services/GameHistory.cs
new file mode 100644
index 00000000..1970a7d7
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Services/GameHistory.cs
@@ -0,0 +1,18 @@
+using MathGame.Models;
+
+namespace MathGame.Services;
+
+public class GameHistory
+{
+ private readonly List _sessions = new();
+
+ public void Add(GameSession session)
+ {
+ _sessions.Add(session);
+ }
+
+ public IReadOnlyList GetAll()
+ {
+ return _sessions.AsReadOnly();
+ }
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/Services/QuestionGenerator.cs b/djimon44.MathGame/djimon44.MathGame/Services/QuestionGenerator.cs
new file mode 100644
index 00000000..d6b9f15c
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/Services/QuestionGenerator.cs
@@ -0,0 +1,52 @@
+using MathGame.Enums;
+using MathGame.Interfaces;
+using MathGame.Models;
+
+namespace MathGame.Services;
+
+public class QuestionGenerator : IQuestionGenerator
+{
+ private readonly Random _random = new();
+
+ public MathQuestion Generate(GameType game, DifficultySettings difficulty)
+ {
+ if (game == GameType.Division)
+ return GenerateDivision(difficulty);
+ else if (game == GameType.Multiplication)
+ return GenerateMultiplication(difficulty);
+ else if (game == GameType.Random)
+ return GenerateRandom(difficulty);
+ else
+ return GenerateStandart(game, difficulty);
+ }
+
+ private MathQuestion GenerateStandart(GameType game, DifficultySettings difficulty)
+ {
+ int a = _random.Next(1, difficulty.MaxValue + 1);
+ int b = _random.Next(1, difficulty.MaxValue + 1);
+ return new MathQuestion(a, b, game);
+ }
+
+ private MathQuestion GenerateDivision(DifficultySettings difficulty)
+ {
+ int divisor = _random.Next(1, difficulty.MaxValue + 1);
+ int maxQuotient = difficulty.MaxValue / divisor;
+ int quotient = _random.Next(1, maxQuotient + 1);
+ int dividend = divisor * quotient;
+ return new MathQuestion(dividend, divisor, GameType.Division);
+ }
+
+ private MathQuestion GenerateMultiplication(DifficultySettings difficulty)
+ {
+ int multiplicand = _random.Next(1, difficulty.MaxValue + 1);
+ int multiplier = _random.Next(1, difficulty.MaxValue + 1);
+ return new MathQuestion(multiplicand, multiplier, GameType.Multiplication);
+ }
+
+ private MathQuestion GenerateRandom(DifficultySettings difficulty)
+ {
+ int randomEnum = _random.Next(0, 4);
+ GameType randomGame = (GameType)randomEnum;
+ return Generate(randomGame, difficulty);
+ }
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/UI/ConsoleUI.cs b/djimon44.MathGame/djimon44.MathGame/UI/ConsoleUI.cs
new file mode 100644
index 00000000..2c08c24f
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/UI/ConsoleUI.cs
@@ -0,0 +1,121 @@
+using MathGame.Enums;
+using MathGame.Models;
+
+namespace MathGame.UI;
+
+public class ConsoleUI
+{
+ public string ShowMainMenu()
+ {
+ Console.Clear();
+ Console.WriteLine("=== MATH GAME ===");
+ Console.WriteLine("R. Random");
+ Console.WriteLine("1. Addition");
+ Console.WriteLine("2. Subtraction");
+ Console.WriteLine("3. Multiplication");
+ Console.WriteLine("4. Division");
+ Console.WriteLine("5. View History");
+ Console.WriteLine("0. Exit");
+ Console.Write("\nChoose an option: ");
+
+ return Console.ReadLine()?.Trim().ToLower() ?? string.Empty;
+ }
+
+ public string ShowDifficultyMenu()
+ {
+ Console.Clear();
+ Console.WriteLine("=== PICK DIFFICULTY ===");
+ Console.WriteLine("1. Easy");
+ Console.WriteLine("2. Medium");
+ Console.WriteLine("3. Hard");
+
+ return Console.ReadLine()?.Trim().ToLower() ?? string.Empty;
+ }
+
+ public void DisplayQuestion(MathQuestion question, int number, int total, int timeLimit)
+ {
+ Console.Clear();
+ Console.WriteLine($"=== {question.Game} Game ===");
+ Console.WriteLine($"[You have {timeLimit} seconds!]");
+ Console.WriteLine($"\nQuestion [{number}/{total}]");
+ Console.Write($"{question.OperandA} {OperationSymbol(question.Game)} {question.OperandB} = ");
+ }
+
+ public int GetPlayerAnswer()
+ {
+ while (true)
+ {
+ if (int.TryParse(Console.ReadLine(), out int answer))
+ {
+ return answer;
+ }
+
+ Console.Write("Please enter a whole number: ");
+ }
+ }
+
+ public void DisplayFeedback(bool correct, int correctAnswer = 0)
+ {
+ if (correct)
+ {
+ Console.WriteLine("Correct!");
+ Console.WriteLine("Press any key to continue...");
+ Console.ReadKey();
+ }
+ else
+ {
+ Console.WriteLine($"Wrong/Out of time. The answer is: [{correctAnswer}]");
+ Console.WriteLine("Press any key to continue...");
+ Console.ReadKey();
+ }
+ }
+
+ public void DisplaySummary(GameSession session)
+ {
+ Console.Clear();
+ Console.WriteLine($"\nGame over! You scored {session.Score}/{session.TotalQuestions}.");
+ Console.WriteLine($"Completion time: {session.Duration}");
+ Console.WriteLine("Press any key to return to the menu...");
+ Console.ReadKey();
+ }
+
+ public void DisplayHistory(IReadOnlyList history)
+ {
+ Console.Clear();
+ Console.WriteLine("=== GAME HISTORY ===\n");
+
+ if (!history.Any())
+ {
+ Console.WriteLine("No games played yet.");
+ }
+ else
+ {
+ foreach (GameSession session in history)
+ {
+ Console.WriteLine(
+ $"{session.PlayedOn:HH:mm:ss} | {session.Duration} | {session.Game,-15} Game | {session.Difficulty} | {session.Score}/{session.TotalQuestions}");
+ }
+
+ Console.WriteLine("\nPress any key to return...");
+ Console.ReadKey();
+ }
+ }
+
+ private static string OperationSymbol(GameType op)
+ {
+ switch (op)
+ {
+ case GameType.Addition:
+ return "+";
+ case GameType.Subtraction:
+ return "-";
+ case GameType.Multiplication:
+ return "*";
+ case GameType.Division:
+ return "/";
+
+ default:
+ return "?";
+ }
+ }
+}
diff --git a/djimon44.MathGame/djimon44.MathGame/djimon44.MathGame.csproj b/djimon44.MathGame/djimon44.MathGame/djimon44.MathGame.csproj
new file mode 100644
index 00000000..ed9781c2
--- /dev/null
+++ b/djimon44.MathGame/djimon44.MathGame/djimon44.MathGame.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+
+
+