diff --git a/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/.gitignore b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/.gitignore new file mode 100644 index 00000000..32cd9cc7 --- /dev/null +++ b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/.gitignore @@ -0,0 +1,15 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/projectSettingsUpdater.xml +/modules.xml +/.idea.Rakenkode.MathGame.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/indexLayout.xml b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/indexLayout.xml new file mode 100644 index 00000000..a76448c1 --- /dev/null +++ b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/indexLayout.xml @@ -0,0 +1,10 @@ + + + + + ../../CodeReviews.Console.MathGame + + + + + \ No newline at end of file diff --git a/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/vcs.xml b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/vcs.xml new file mode 100644 index 00000000..62bd7a01 --- /dev/null +++ b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Rakenkode.MathGame/Rakenkode.MathGame.sln b/Rakenkode.MathGame/Rakenkode.MathGame.sln new file mode 100644 index 00000000..e87d799b --- /dev/null +++ b/Rakenkode.MathGame/Rakenkode.MathGame.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rakenkode.MathGame", "Rakenkode.MathGame\Rakenkode.MathGame.csproj", "{A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Rakenkode.MathGame/Rakenkode.MathGame/Game.cs b/Rakenkode.MathGame/Rakenkode.MathGame/Game.cs new file mode 100644 index 00000000..ae94607a --- /dev/null +++ b/Rakenkode.MathGame/Rakenkode.MathGame/Game.cs @@ -0,0 +1,41 @@ +namespace Rakenkode.MathGame; + +public class Game +{ + private double _rating = 0; + public double Rating + { + get { return _rating; } + } + public int Duration { get; set; } + public GameType GameType { get;} + public Question[] Questions; + + public Game(GameType gameType, int numberOfQuestions) + { + GameType = gameType; + Questions = new Question[numberOfQuestions]; + Questions = Question.CreateProblems(gameType, numberOfQuestions); + } + + public void Evaluate() + { + int score = 0; + + for (int i = 0; i < Questions.Length; i++) + { + if (Questions[i].IsPlayerCorrect()) + score++; + } + _rating = Math.Round((score / (double) Questions.Length) * 100, 1); + } +} + +public enum GameType +{ + Addition = 0, + Subtraction = 1, + Multiplication = 2, + Division = 3, + Random = 4 +} \ No newline at end of file diff --git a/Rakenkode.MathGame/Rakenkode.MathGame/Program.cs b/Rakenkode.MathGame/Rakenkode.MathGame/Program.cs new file mode 100644 index 00000000..b6bdd7f2 --- /dev/null +++ b/Rakenkode.MathGame/Rakenkode.MathGame/Program.cs @@ -0,0 +1,326 @@ +using System.Diagnostics; + +namespace Rakenkode.MathGame +{ + class Program + { + private static bool _isAppActive = true; + private static int _questionNumber = 0; + private static int _numberOfQuestions = 5; + private static int _selectedGameNumber = 1; + private static Game game = new Game(GameType.Addition, 5); + private static List games = new List(); + private static Stopwatch _stopWatch = new Stopwatch(); + + static void Main(string[] args) + { + ActivePage activePage = ActivePage.MainPage; + + while (_isAppActive) + { + switch (activePage) + { + case ActivePage.MainPage: + DisplayMain(); + var userInput = Console.ReadLine()?.Trim().ToUpper(); + if (userInput != null) activePage = NavigateFromMain(userInput); + break; + case ActivePage.GamePage: + if (_questionNumber < 5) + { + DisplayGame(_questionNumber); + var gameInput = Console.ReadLine()?.Trim().ToUpper(); + if (gameInput != null) activePage = NavigateFromGame(gameInput); + } + else + { + DisplayResults(); + var gameInput = Console.ReadLine()?.Trim().ToUpper(); + if (gameInput != null) activePage = NavigateFromGameResults(gameInput); + } + break; + case ActivePage.HistoryPage: + if (games.Count == 0) + { + DisplayZeroGameHistory(); + var historyInput = Console.ReadLine()?.Trim().ToUpper(); + if (historyInput != null) activePage = NavigateFromZeroGameHistory(historyInput); + } + else + { + DisplayGameHistory(); + var historyInput = Console.ReadLine()?.Trim().ToUpper(); + if (historyInput != null) activePage = NavigateFromGameHistory(historyInput); + } + break; + case ActivePage.GameInfoPage: + DisplayGameInfo(); + var gameDataInput = Console.ReadLine()?.Trim().ToUpper(); + if (gameDataInput != null) activePage = NavigateFromGameInfo(gameDataInput); + break; + default: + ExitApplication(); + break; + } + } + + Console.WriteLine("Goodbye!"); + } + + private static void ExitApplication() + { + _isAppActive = false; + + if(_stopWatch.IsRunning) + _stopWatch.Stop(); + + for (int i = 3; i >= 0; i--) + { + Console.Clear(); + Console.WriteLine($"Closing in {i}..."); + Thread.Sleep(400); + } + } + + private static void DisplayMain() + { + Console.Clear(); + Console.WriteLine("========== MATH GAME CONSOLE =========="); + Console.WriteLine(string.Empty); + Console.WriteLine(" Choose an option:"); + Console.WriteLine(" [ 1 ] = Addition Game"); + Console.WriteLine(" [ 2 ] = Subtraction Game"); + Console.WriteLine(" [ 3 ] = Multiplication Game"); + Console.WriteLine(" [ 4 ] = Division Game"); + Console.WriteLine(" [ 5 ] = Random Game"); + Console.WriteLine(" [ 6 ] = Game History"); + Console.WriteLine(" [ x ] = Exit Application"); + Console.WriteLine(); + Console.Write(" Input: "); + } + + private static ActivePage NavigateFromMain(string userInput) + { + switch (userInput) + { + case "X": + return ActivePage.ExitPage; + case "1": + game = new Game(GameType.Addition, _numberOfQuestions); + InitGameParams(); + return ActivePage.GamePage; + case "2": + game = new Game(GameType.Subtraction, _numberOfQuestions); + InitGameParams(); + return ActivePage.GamePage; + case "3": + game = new Game(GameType.Multiplication, _numberOfQuestions); + InitGameParams(); + return ActivePage.GamePage; + case "4": + game = new Game(GameType.Division, _numberOfQuestions); + InitGameParams(); + return ActivePage.GamePage; + case "5": + game = new Game(GameType.Random, _numberOfQuestions); + InitGameParams(); + return ActivePage.GamePage; + case "6": + return ActivePage.HistoryPage; + default: + return ActivePage.MainPage; + } + } + + private static void InitGameParams() + { + _questionNumber = 0; + _stopWatch.Restart(); + } + + private static void DisplayGame(int gameNumber) + { + Console.Clear(); + Console.WriteLine($"=========== GAME {gameNumber + 1} of 5 ==========="); + Console.WriteLine(string.Empty); + Console.WriteLine($" Problem: {game.Questions[gameNumber].ToString()}"); + Console.WriteLine(string.Empty); + Console.Write(" Answer [ x to quit ]: "); + } + + private static ActivePage NavigateFromGame(string userInput) + { + if (Int32.TryParse(userInput, out int number)) + { + game.Questions[_questionNumber].PlayerAnswer = number; + _questionNumber++; + if (_questionNumber == 5) + { + _stopWatch.Stop(); + game.Duration = (int) _stopWatch.ElapsedMilliseconds / 1000; + game.Evaluate(); + games.Add(game); + } + } + else if (userInput.Equals("X", StringComparison.OrdinalIgnoreCase)) + { + return ActivePage.ExitPage; + } + + return ActivePage.GamePage; + } + + private static void DisplayGameData(Game game) + { + Console.WriteLine($" problem answer result"); + for (int i = 0; i < game.Questions.Length; i++) + { + Console.WriteLine($" {game.Questions[i].ToString(),-14} {game.Questions[i].PlayerAnswer.ToString(),-10} {(game.Questions[i].IsPlayerCorrect() ? "pass" : "fail")}"); + } + Console.WriteLine(string.Empty); + Console.WriteLine($" Game time: {game.Duration} sec Rating: {game.Rating}%"); + } + + private static void DisplayResults() + { + Console.Clear(); + Console.WriteLine("=========== GAME OVER ==========="); + Console.WriteLine(string.Empty); + DisplayGameData(game); + Console.WriteLine(string.Empty); + Console.WriteLine(" Choose an option:"); + Console.WriteLine(" [ m ] = Main Menu"); + Console.WriteLine(" [ x ] = Exit Application"); + Console.WriteLine(); + Console.Write(" Input: "); + } + + private static ActivePage NavigateFromGameResults(string userInput) + { + if (userInput.Equals("X", StringComparison.OrdinalIgnoreCase)) + { + return ActivePage.ExitPage; + } + else if (userInput.Equals("M", StringComparison.OrdinalIgnoreCase)) + { + return ActivePage.MainPage; + } + + return ActivePage.GamePage; + } + + private static void DisplayZeroGameHistory() + { + Console.Clear(); + Console.WriteLine("=========== GAME HISTORY =========="); + Console.WriteLine(string.Empty); + Console.WriteLine(" There are no previous games played."); + Console.WriteLine(string.Empty); + Console.WriteLine(" Choose an option:"); + Console.WriteLine(" [ m ] = Main Menu"); + Console.WriteLine(" [ x ] = Exit Application"); + Console.WriteLine(); + Console.Write(" Input: "); + } + + private static ActivePage NavigateFromZeroGameHistory(string userInput) + { + if (userInput.Equals("M", StringComparison.OrdinalIgnoreCase)) + { + return ActivePage.MainPage; + } + else if (userInput.Equals("X", StringComparison.OrdinalIgnoreCase)) + { + return ActivePage.ExitPage; + } + + return ActivePage.HistoryPage; + } + + private static void DisplayGameHistory() + { + Console.Clear(); + Console.WriteLine("=========== GAME HISTORY =========="); + Console.WriteLine(string.Empty); + + Console.WriteLine("Game# Type Rating Duration"); + for (int i = 0; i < games.Count; i++) + { + Console.WriteLine($" {(i + 1).ToString(),-6} {games[i].GameType,-15} {games[i].Rating + "%",-11} {games[i].Duration} sec"); + } + + Console.WriteLine(string.Empty); + Console.WriteLine(" Choose an option:"); + Console.WriteLine(" [ n ] = Where n is Game# to view"); + Console.WriteLine(" [ m ] = Main Menu"); + Console.WriteLine(" [ x ] = Exit Application"); + Console.WriteLine(); + Console.Write(" Input: "); + } + + private static ActivePage NavigateFromGameHistory(string userInput) + { + if (int.TryParse(userInput, out int number)) + { + if (number > 0 && number <= games.Count) + { + _selectedGameNumber = number; + return ActivePage.GameInfoPage; + } + } + else + { + if (userInput.Equals("M", StringComparison.OrdinalIgnoreCase)) + { + return ActivePage.MainPage; + } + else if (userInput.Equals("X", StringComparison.OrdinalIgnoreCase)) + { + return ActivePage.ExitPage; + } + } + return ActivePage.HistoryPage; + } + + private static void DisplayGameInfo() + { + Console.Clear(); + Console.WriteLine("=========== GAME INFO ==========="); + Console.WriteLine(string.Empty); + DisplayGameData(games[_selectedGameNumber - 1]); + Console.WriteLine(string.Empty); + Console.WriteLine(" Choose an option:"); + Console.WriteLine(" [ h ] = Game History"); + Console.WriteLine(" [ m ] = Main Menu"); + Console.WriteLine(" [ x ] = Exit Application"); + Console.WriteLine(); + Console.Write(" Input: "); + } + + private static ActivePage NavigateFromGameInfo(string userInput) + { + switch (userInput) + { + case "H": + return ActivePage.HistoryPage; + case "M": + return ActivePage.MainPage; + case "X": + return ActivePage.ExitPage; + default: + return ActivePage.GameInfoPage; + } + } + + private enum ActivePage + { + MainPage = 0, + GamePage = 1, + HistoryPage = 2, + GameInfoPage = 3, + ExitPage = 4 + } + } + + +} \ No newline at end of file diff --git a/Rakenkode.MathGame/Rakenkode.MathGame/Question.cs b/Rakenkode.MathGame/Rakenkode.MathGame/Question.cs new file mode 100644 index 00000000..e3189cca --- /dev/null +++ b/Rakenkode.MathGame/Rakenkode.MathGame/Question.cs @@ -0,0 +1,188 @@ +namespace Rakenkode.MathGame +{ + public abstract class Question + { + private protected int _num1 = 0; + private protected int _num2 = 0; + private protected int _answer = 0; + public int PlayerAnswer { get; set; } + private protected Random _random = new Random(); + + public int GetAnswer() + { + return _answer; + } + + public int GetNum1() + { + return _num1; + } + + public int GetNum2() + { + return _num2; + } + + public bool IsPlayerCorrect() + { + return _answer == PlayerAnswer; + } + + public static Question[] CreateProblems(int mode) + { + int numQuestion = 5; + Question[] questions = new Question[numQuestion]; + Random random = new Random(); + int type = 0; + + for (int i = 0; i < numQuestion; i++) + { + if (mode < 4) + { + type = mode; + } + else + { + Thread.Sleep(random.Next(0, 101)); + type = random.Next(0, 4); + } + + switch (type) + { + case 0: + questions[i] = new AdditionProblem(); + break; + case 1: + questions[i] = new SubtractionProblem(); + break; + case 2: + questions[i] = new MultiplicationProblem(); + break; + case 3: + questions[i] = new DivisionProblem(); + break; + } + } + + return questions; + } + + public static Question[] CreateProblems(GameType gameType, int numQuestion) + { + Question[] questions = new Question[numQuestion]; + Random random = new Random(); + int type = 0; + + for (int i = 0; i < numQuestion; i++) + { + if (gameType == GameType.Random) + { + Thread.Sleep(random.Next(0, 101)); + type = random.Next(0, 4); + } + else + { + type = (int) gameType; + } + + switch (type) + { + case 0: + questions[i] = new AdditionProblem(); + break; + case 1: + questions[i] = new SubtractionProblem(); + break; + case 2: + questions[i] = new MultiplicationProblem(); + break; + case 3: + questions[i] = new DivisionProblem(); + break; + } + } + + return questions; + } + } + + internal class AdditionProblem : Question + { + public AdditionProblem() + { + _num1 = _random.Next(0, 101); + do + { + _num2 = _random.Next(0, 101); + } while(_num2 == _num1); + + _answer = _num1 + _num2; + PlayerAnswer = -1; + } + + public override string ToString() + { + return $"{_num1} + {_num2}"; + } + } + + internal class SubtractionProblem : Question + { + public SubtractionProblem() + { + int temp1 = _random.Next(0, 101); + int temp2 = 0; + do + { + temp2 = _random.Next(0, 101); + }while (temp1 == temp2); + + _num1 = Math.Max(temp1, temp2); + _num2 = Math.Min(temp1, temp2); + _answer = _num1 - _num2; + PlayerAnswer = -1; + } + + public override string ToString() + { + return $"{_num1} - {_num2}"; + } + } + + internal class MultiplicationProblem : Question + { + public MultiplicationProblem() + { + _num1 = _random.Next(0, 101); + _num2 = _random.Next(0, 101); + _answer = _num1 * _num2; + PlayerAnswer = -1; + } + + public override string ToString() + { + return $"{_num1} x {_num2}"; + } + } + + internal class DivisionProblem : Question + { + public DivisionProblem() + { + while (true) + { + _num2 = _random.Next(1, 101); + _num1 = _num2 * _random.Next(2, 11); + if (_num1 < 101) + break; + } + _answer = _num1 / _num2; + PlayerAnswer = -1; + } + + public override string ToString() + { + return $"{_num1} / {_num2}"; + } + } +} \ No newline at end of file diff --git a/Rakenkode.MathGame/Rakenkode.MathGame/Rakenkode.MathGame.csproj b/Rakenkode.MathGame/Rakenkode.MathGame/Rakenkode.MathGame.csproj new file mode 100644 index 00000000..6c1dc922 --- /dev/null +++ b/Rakenkode.MathGame/Rakenkode.MathGame/Rakenkode.MathGame.csproj @@ -0,0 +1,10 @@ + + + + Exe + net10.0 + enable + enable + + +