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 djimon44.MathGame/djimon44.MathGame.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Solution>
<Project Path="djimon44.MathGame/djimon44.MathGame.csproj" />
</Solution>
8 changes: 8 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Enums/Difficulty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace MathGame.Enums;

public enum Difficulty
{
Easy,
Medium,
Hard
}
10 changes: 10 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Enums/GameType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace MathGame.Enums;

public enum GameType
{
Addition,
Subtraction,
Multiplication,
Division,
Random
}
9 changes: 9 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Interfaces/IGameEngine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using MathGame.Enums;
using MathGame.Models;

namespace MathGame.Interfaces;

public interface IGameEngine
{
GameSession Play(GameType game, Difficulty difficulty);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using MathGame.Enums;
using MathGame.Models;

namespace MathGame.Interfaces;

public interface IQuestionGenerator
{
MathQuestion Generate(GameType game, DifficultySettings difficulty);
}
13 changes: 13 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Models/DifficultySettings.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
25 changes: 25 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Models/GameSession.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
54 changes: 54 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Models/MathQuestion.cs
Original file line number Diff line number Diff line change
@@ -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.");
}
}
}
80 changes: 80 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Program.cs
Original file line number Diff line number Diff line change
@@ -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!");
83 changes: 83 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Services/GameEngine.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
18 changes: 18 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Services/GameHistory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using MathGame.Models;

namespace MathGame.Services;

public class GameHistory
{
private readonly List<GameSession> _sessions = new();

public void Add(GameSession session)
{
_sessions.Add(session);
}

public IReadOnlyList<GameSession> GetAll()
{
return _sessions.AsReadOnly();
}
}
52 changes: 52 additions & 0 deletions djimon44.MathGame/djimon44.MathGame/Services/QuestionGenerator.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading