├── Projects ├── LunarDoggo.Beginners.ConsoleIO │ ├── LunarDoggo.ConsoleIO.csproj │ ├── README.md │ └── Program.cs ├── LunarDoggo.FileSystemTree │ ├── LunarDoggo.FileSystemTree.csproj │ ├── README.md │ ├── FileSystemTreeItem.cs │ └── Program.cs ├── LunarDoggo.TicTacToe │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── App.xaml.cs │ ├── README.md │ ├── App.config │ ├── PlayerEventArgs.cs │ ├── App.xaml │ ├── Player.cs │ ├── ButtonTileMapping.cs │ ├── PlayerTileEventArgs.cs │ ├── MainWindow.xaml │ ├── LunarDoggo.TicTacToe.csproj │ ├── GameBoard.cs │ ├── GameState.cs │ └── MainWindow.xaml.cs ├── LunarDoggo.Beginners.ConsoleIOValidation │ ├── LunarDoggo.ConsoleIOValidation.csproj │ ├── README.md │ └── Program.cs └── LunarDoggo.QuizGame │ ├── LunarDoggo.QuizGame.csproj │ ├── README.md │ ├── IO │ ├── IQuizQuestionSerializer.cs │ └── FileQuizQuestionSerializer.cs │ ├── QuizQuestion.cs │ ├── game_questions.json │ ├── Visuals │ ├── ConsoleVisualizer.cs │ └── IVisualizer.cs │ ├── Program.cs │ ├── GameLoop.cs │ └── GameState.cs ├── Algorithms ├── LunarDoggo.Algorithms.csproj ├── Sorting │ ├── ISortingAlgorithm.cs │ └── InsertionSort.cs ├── README.md └── Graphs │ └── Pathfinding │ ├── BreadthFirstSearch.cs │ └── DepthFirstSearch.cs ├── Datastructures ├── Exceptions │ └── UnderflowException.cs ├── LunarDoggo.Datastructures.csproj ├── README.md ├── Graphs │ ├── README.md │ ├── Edge.cs │ ├── IGraph.cs │ ├── UndirectedUnweightedGraph.cs │ └── Vertex.cs ├── Collections │ ├── Stack.cs │ ├── LinkedList.cs │ ├── Queue.cs │ └── ArrayList.cs └── Trees │ └── Tree.cs ├── LICENSE ├── Concepts └── Big O notation.md ├── README.md ├── LunarDoggo.CSharpBeginnerProjects.sln ├── .editorconfig └── .gitignore /Projects/LunarDoggo.Beginners.ConsoleIO/LunarDoggo.ConsoleIO.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.FileSystemTree/LunarDoggo.FileSystemTree.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.Beginners.ConsoleIOValidation/LunarDoggo.ConsoleIOValidation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace TicTacToe 4 | { 5 | /// 6 | /// Interactionlogic for "App.xaml" 7 | /// 8 | public partial class App : Application 9 | { 10 | //In this class you could override multiple methods to customize your application 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/README.md: -------------------------------------------------------------------------------- 1 | # WPF TicTacToe 2 | A small cli quiz game which loads questions and answers from a file and afterwards allows the player to answer the questions. After all questions are answered, the user is shown how many questions they got right and can restart the game. 3 | 4 | # Topics 5 | * Windows GUI with WPF 6 | * Windows Messageboxes 7 | * Events 8 | * Multidimensional arrays -------------------------------------------------------------------------------- /Algorithms/LunarDoggo.Algorithms.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | net7.0 9 | enable 10 | enable 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Datastructures/Exceptions/UnderflowException.cs: -------------------------------------------------------------------------------- 1 | namespace LunarDoggo.Datastructures.Exceptions 2 | { 3 | /// 4 | /// An signifying that there are no items to be removed in a collection 5 | /// 6 | public class UnderflowException : Exception 7 | { 8 | public UnderflowException(string message) : base(message) 9 | { } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/LunarDoggo.QuizGame.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 7 | 8 | 9 | 10 | PreserveNewest 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/README.md: -------------------------------------------------------------------------------- 1 | # ConsoleIO 2 | A small cli quiz game which loads questions and answers from a file and afterwards allows the player to answer the questions. After all questions are answered, the user is shown how many questions they got right and can restart the game. 3 | 4 | # Topics 5 | * Console input without Console.Readline() 6 | * interfaces basics 7 | * System.Linq basics 8 | * serialization basics with System.Text.Json 9 | * attributes for metadata basics -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | -------------------------------------------------------------------------------- /Datastructures/LunarDoggo.Datastructures.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/PlayerEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace TicTacToe 4 | { 5 | /// 6 | /// This class is used for raising events regarding a player 7 | /// 8 | public class PlayerEventArgs : EventArgs 9 | { 10 | public PlayerEventArgs(Player player) 11 | { 12 | this.Player = player; 13 | } 14 | 15 | /// 16 | /// who caused the event to be raised 17 | /// 18 | public Player Player { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.FileSystemTree/README.md: -------------------------------------------------------------------------------- 1 | # FileSystemTree 2 | A console application that recursively reads the file system and prints files and directories to the console. 3 | 4 | At first the user is prompted to enter a valid directory path. The input is used as used as the base directory to recursively read the filesystem into a tree structure. Afterwards the read tree is output to the console. 5 | 6 | # Topics 7 | * sequence (commands that are executed in the same order as they are written in the source-file) 8 | * loops (for, do-while) 9 | * recursion 10 | * file system read access -------------------------------------------------------------------------------- /Algorithms/Sorting/ISortingAlgorithm.cs: -------------------------------------------------------------------------------- 1 | namespace LunarDoggo.Algorithms.Sorting 2 | { 3 | //This interface is used to keep the public interface of all sorting algorithms implemented here clean and uniform. 4 | //The type to be sorted must implement IComparable so that there is a way to tell which value is equal to, greater 5 | //or less than another one 6 | public interface ISortingAlgorithm where T : IComparable 7 | { 8 | /// 9 | /// Sorts the provided in ascending order 10 | /// 11 | void Sort(T[] values); 12 | } 13 | } -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/Player.cs: -------------------------------------------------------------------------------- 1 | namespace TicTacToe 2 | { 3 | /// 4 | /// Representation of a player 5 | /// 6 | public class Player 7 | { 8 | public Player(byte id, string display) 9 | { 10 | this.Display = display; 11 | this.Id = id; 12 | } 13 | 14 | //For tic tac toe this is usually set to either "X" or "O" 15 | /// 16 | /// Display name of the player 17 | /// 18 | public string Display { get; } 19 | /// 20 | /// Id-number of the player 21 | /// 22 | public byte Id { get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.Beginners.ConsoleIO/README.md: -------------------------------------------------------------------------------- 1 | # ConsoleIO 2 | A simple console application that writes to the console-window and reads input from the user. Depending on the users input, different execution-paths can be chosen. 3 | 4 | First the user is greeted by a simple message and is prompted to input their name. If the input is empty or just consists of whitespaces, the program tells the user, that it didn't get a valid name, otherwise, the user is called by their name and wished a great day. Lastly, the application waits for any key to be pressed and terminates afterwards 5 | 6 | # Topics 7 | * sequence (commands that are executed in the same order as they are written in the source-file) 8 | * selection (if-, else-statements) 9 | * variable-declaration 10 | * variable-assignment 11 | * console output 12 | * user-input from the console -------------------------------------------------------------------------------- /Projects/LunarDoggo.FileSystemTree/FileSystemTreeItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LunarDoggo.FileSystemTree 4 | { 5 | public class FileSystemTreeItem 6 | { 7 | private readonly IEnumerable children; 8 | private readonly FileSystemTreeItemType type; 9 | private readonly string name; 10 | 11 | public FileSystemTreeItem(string name, FileSystemTreeItemType type, IEnumerable children) 12 | { 13 | this.children = children; 14 | this.name = name; 15 | this.type = type; 16 | } 17 | 18 | public IEnumerable Children { get { return this.children; } } 19 | public FileSystemTreeItemType Type { get { return this.type; } } 20 | public string Name { get { return this.name; } } 21 | } 22 | 23 | public enum FileSystemTreeItemType 24 | { 25 | Directory, 26 | File 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/ButtonTileMapping.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace TicTacToe 4 | { 5 | /// 6 | /// Represents a mapping between a and a tile with the specified coordinates 7 | /// 8 | public class ButtonTileMapping 9 | { 10 | public ButtonTileMapping(Button button, int tileX, int tileY) 11 | { 12 | this.Button = button; 13 | this.TileX = tileX; 14 | this.TileY = tileY; 15 | } 16 | 17 | /// 18 | /// of the window 19 | /// 20 | public Button Button { get; } 21 | /// 22 | /// X-coordinate of the tile 23 | /// 24 | public int TileX { get; } 25 | /// 26 | /// Y-coordinate of the tile 27 | /// 28 | public int TileY { get; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/PlayerTileEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace TicTacToe 4 | { 5 | /// 6 | /// This class is used for raising events regarding a player and a specific tile on the 7 | /// 8 | public class PlayerTileEventArgs : EventArgs 9 | { 10 | public PlayerTileEventArgs(Player player, int tileX, int tileY) 11 | { 12 | this.Player = player; 13 | this.TileX = tileX; 14 | this.TileY = tileY; 15 | } 16 | 17 | /// 18 | /// who caused the event to be raised 19 | /// 20 | public Player Player { get; } 21 | /// 22 | /// X coordinate of the events tile 23 | /// 24 | public int TileX { get; } 25 | /// 26 | /// Y coordinate of the events tile 27 | /// 28 | public int TileY { get; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.Beginners.ConsoleIOValidation/README.md: -------------------------------------------------------------------------------- 1 | # ConsoleIO 2 | A simple console application that writes to the console-window and reads input from the user. Depending on the users input, different outputs are given. 3 | 4 | At first the user receives a list of games to the console-window. Afterwards the application prompts the user to select the index of a game they want to play. If the user inserts a valid index, the program prints the name of the game to the console, if the user inserts an invalid index or any non-numeric character, the application prompts the user again for an index. After the game-choice is printed, the program waits for any key to be pressed and finally terminates. 5 | 6 | # Topics 7 | * sequence (commands that are executed in the same order as they are written in the source-file) 8 | * loops (for, do-while) 9 | * static-class-variable-declaration 10 | * static-class-variable-assignment 11 | * checking if the user-input is an integer and if it is a valid index 12 | * boolean-negation (!-operator) -------------------------------------------------------------------------------- /Datastructures/README.md: -------------------------------------------------------------------------------- 1 | # Datastructures 2 | Datastructures define a specific format to organize data with that makes storing, using and altering the data easier. Most of the time you can choose between multiple different data structures to solve a problem, but there are different data structures that excel at different jobs. Binary trees, for example, are great for searching for items, graphs are great for modelling networks and flows, and Sets are well suited for storing items that may only occur once in the collection. 3 | 4 | Many data structures are fundamental for certain algorithms, so after looking at these data structures you may want to have a look at the corresponding [algorithms](https://github.com/lunardoggo/CSharpBeginnerProjects/tree/main/Algorithms). 5 | 6 | This project showcases some basic data structures that one should know before studying advanced computer science topics. You could theoretically use these implementations in your projcest, but the data structures contained in the standard library are usually more efficient, as this project aims at explaining the basic principles and not how to optimally implement every single operation. -------------------------------------------------------------------------------- /Algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Algorithms 2 | Algorithms are an ordered collection of predefined steps for solving a specific problem. The problem scope of an algorithms usually is very narrow, but specific problems are somtimes solvable by slightly adapting a well known algorithm. Therefore it's very helpful to know the algorithms many other algorithms are based upon. For example the depth-first-search (DFS) algorithm can be adapted to check if a given graph has a valid 2-coloring or if it contains a rooted spanning tree, or even find the minimum rooted spanning tree. 3 | 4 | This project shows some basic algorithms one should know before moving on to more advanced algorithms. Some algorithms also use some basic data structures, such as graphs in case of DFS, threfor you may want to have a look at the basic data structures layed out in [data structures](https://github.com/lunardoggo/CSharpBeginnerProjects/tree/main/Datastructures) first. You could use these implementations for your own projects, but the algorithms focus on teaching basic principles and may not catch all edge cases. If the standard library provides an implementation of an algorithm you should use that instead, as the standard library usually won't cause crashes due to edge cases. -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | namespace TicTacToe.Properties 13 | { 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 17 | { 18 | 19 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 20 | 21 | public static Settings Default 22 | { 23 | get 24 | { 25 | return defaultInstance; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/IO/IQuizQuestionSerializer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LunarDoggo.QuizGame.IO 4 | { 5 | /* 6 | * Interfaces in C# are like blueprints for classes, every class that "implements" this interface must also define all 7 | * methods and properties of this interface as public members. 8 | * Interfaces can be used to define common methods and properties of multiple classes in order to be able to change 9 | * the instance of a concrete class in the source code without having to rewrite the application. 10 | * In the real world interfaces are for example used, when you have multiple datasources like databases, files, ... 11 | * or rendering-libraries like DirectX, OpenGL, Vulcan, ... which can be swapped in and out at runtime 12 | * 13 | * In this case, all classes that implement IQuizQuestionSerializer must declare the public method DeserializeQuestions() 14 | * that returns a IEnumerable 15 | * 16 | * Serialization is the process of converting a data structure/object into a storable format (Json, XML, BIN, ...) 17 | * Deserialization is the reverse, content of a storable format is converted into a data structure/object to be used in your application 18 | */ 19 | public interface IQuizQuestionSerializer 20 | { 21 | /// 22 | /// Load all s from the datasource 23 | /// 24 | IEnumerable DeserializeQuestions(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/QuizQuestion.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using System.Linq; 3 | using System; 4 | 5 | namespace LunarDoggo.QuizGame 6 | { 7 | /* 8 | * These are simple data containers 9 | * 10 | * Note: you can define multiple classes in the same file, in theory you could define your whole application in a single file, for 11 | * small classes this is ok, for big classes with a lot of logic, it is advisable to split the classes into their own files to increase 12 | * the readability and clarity of your code 13 | */ 14 | public class QuizQuestion 15 | { 16 | public QuizQuestionAnswer[] Answers { get; set; } 17 | public string Question { get; set; } 18 | /* 19 | * members of a class can have attributes that define metadata of that member. The metadata can be directed towards the compiler 20 | * (e.g. System.Runtime.CompilerServices.CallerMemberName) or can be used at runtime (e.g. JsonIgnore) 21 | * 22 | * a notable example is the attribute "System.ComponentModel.DataAnnotations.Display" which in many ui-frameworks is used to give 23 | * properties speaking names in the UI instead of the name the property has in the code 24 | * 25 | * The JsonIgnore-attribute tells the JsonSerializer if it is used by the application to ignore this attribute during serialization 26 | * and deserialization. If the application doesn't use the JsonSerializer, the attribute is still defined but never used 27 | */ 28 | [JsonIgnore] 29 | public Guid Id { get; set; } 30 | 31 | public QuizQuestionAnswer CorrectAnswer { get { return this.Answers.Single(_answer => _answer.IsCorrect); } } 32 | } 33 | 34 | public class QuizQuestionAnswer 35 | { 36 | public bool IsCorrect { get; set; } 37 | public string Answer { get; set; } 38 | [JsonIgnore] 39 | public Guid Id { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Algorithms/Sorting/InsertionSort.cs: -------------------------------------------------------------------------------- 1 | namespace LunarDoggo.Algorithms.Sorting 2 | { 3 | public class InsertionSort : ISortingAlgorithm where T : IComparable 4 | { 5 | //Insertion sort is one of the most basic sorting algorithms out there. The basic principle is 6 | //to iterate over the provided array from left to right and in each iteration step move all 7 | //items to the left that are greater than the current item one cell to the right, while 8 | //inserting the current item back into the array at the correct index. 9 | //InsertionSort has a worst-case and average-case time complexity of O(n^2), whereas, in the 10 | //best-case, the algorithm terminates after O(n) operations (for example, if the array is already 11 | //sorted in ascending order) 12 | //Additionally InsertionSort is an in situ algorithm that's stable, meaning that the sorting needs 13 | //only O(1) additional storage for the algorithm (in situ) and all groups of items that are equal 14 | //are kept in the same order 15 | public void Sort(T[] values) 16 | { 17 | //i starts at 1, as sorting only makes sense if there at least two values to be sorted 18 | for (int i = 1; i < values.Length; i++) 19 | { 20 | T key = values[i]; 21 | int index = i - 1; 22 | 23 | //Move values[index] to the right if it's greater than key. This results in moving all 24 | //items that are to the left of key and are greater than key one cell to the right. 25 | while(index >= 0 && values[index].CompareTo(key) > 0) 26 | { 27 | values[index + 1] = values[index]; 28 | index--; 29 | } 30 | //Lastly the value contained in "key" has to be inserted back into the array, so that 31 | //the array contains the same items after every step, but now the first i cells are sorted 32 | values[index + 1] = key; 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/game_questions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "question": "1 + 1 is:", 4 | "answers": [ 5 | { 6 | "answer": "4", 7 | "isCorrect": false 8 | }, 9 | { 10 | "answer": "2", 11 | "isCorrect": true 12 | }, 13 | { 14 | "answer": "-7", 15 | "isCorrect": false 16 | } 17 | ] 18 | }, 19 | { 20 | "question": "What is the smalles country in the world?", 21 | "answers": [ 22 | { 23 | "answer": "Vatican City State", 24 | "isCorrect": true 25 | }, 26 | { 27 | "answer": "Andorra", 28 | "isCorrect": false 29 | }, 30 | { 31 | "answer": "Lichtenstein", 32 | "isCorrect": false 33 | } 34 | ] 35 | }, 36 | { 37 | "question": "Which is the hottest planet of the solar system?", 38 | "answers": [ 39 | { 40 | "answer": "Jupiter", 41 | "isCorrect": false 42 | }, 43 | { 44 | "answer": "Venus", 45 | "isCorrect": true 46 | }, 47 | { 48 | "answer": "Mercury", 49 | "isCorrect": false 50 | } 51 | ] 52 | }, 53 | { 54 | "question": "Who discovered the radioactive elements \"polonium\" and \"radium\"?", 55 | "answers": [ 56 | { 57 | "answer": "Antoine Henri Becquerel", 58 | "isCorrect": false 59 | }, 60 | { 61 | "answer": "Niels Bohr", 62 | "isCorrect": false 63 | }, 64 | { 65 | "answer": "Marie Curie", 66 | "isCorrect": true 67 | } 68 | ] 69 | }, 70 | { 71 | "question": "Which solar system planet has the lowest overall density?", 72 | "answers": [ 73 | { 74 | "answer": "Saturn", 75 | "isCorrect": true 76 | }, 77 | { 78 | "answer": "Jupiter", 79 | "isCorrect": false 80 | }, 81 | { 82 | "answer": "Neptune", 83 | "isCorrect": false 84 | } 85 | ] 86 | }, 87 | { 88 | "question": "The solar system object \"Pluto\" is classified as a:", 89 | "answers": [ 90 | { 91 | "answer": "Planet", 92 | "isCorrect": false 93 | }, 94 | { 95 | "answer": "Dwarf planet", 96 | "isCorrect": true 97 | }, 98 | { 99 | "answer": "Comet", 100 | "isCorrect": false 101 | } 102 | ] 103 | } 104 | ] -------------------------------------------------------------------------------- /Datastructures/Graphs/README.md: -------------------------------------------------------------------------------- 1 | # Graphs 2 | In the field of graph theory, a _**graph**_ is an abstract structure that represents connections between objects. A graph at least consists of a Tuple _G=(V,E)_ of Vertices (V) and Edges (E). 3 | 4 | Graphs have different properties you should know before trying to understand the algorithms that use this datastructure, as every algorithm only works with special kinds of graphs. This project will mainly focus on simple graphs: 5 | * A graph is either a **simple graph** or a **multi graph**. In simple graphs there may only be one edge between a given pair of vertices and three cannot be an edge from a vertex to itself (loop), whereas multi graphs allow for both an arbitrary number of edges between a given pair of vertices and loops. 6 | * A graph is either **directed** or **undirected**. Whereas edges in undirected graphs can be traversed in any direction, in directed graphs there may be edges that only allow for one-way traversal 7 | * A graph is either **weighted** or **unweighted**. A weighted graph uses a function _c(e)_ to assign a number/weight to every edge of the graph, the notation usually changes to _G=(V,E,c(e))_. 8 | * A graph is either **cyclic** or **acyclic**. Depending on if the graph is _directed_ or _undirected_, this property has different meanings: 9 | * An _undirected_ graph is acyclic if there is no pair of vertices _u,v_ in _V_, so that there is more than one distinct path from _u_ to _v_ or vice versa 10 | * A _directed_ graph is acyclic if there is vertex _v_ in _V_ for which there is a directed path of length greater than one that starts in _v_ and ends in _v_ 11 | * An _undirected_ graph is called **connected** if there is a path from every Vertex _u_ in _V_ to every other Vertex _v_ in _V_. If a graph isn't connected, it's called **disconnected** 12 | * An _undirected_ graph is called **complete** if there is an edge _{u,v}_ between every pair of Vertices _u,v_ in _V_ 13 | * A **bipartite** graph is a graph where the set of vertices _V_ can be divided into two non-empty, disjunct subsets _S_ and _T_ of _V_ where there is no edge connecting any two vertices in _S_ and there is no edge connecting any two vertices in _T_. 14 | * A **planar** graph is a graph that can be drawn _in a plane_ without crossing any edges except at their start/end vertex 15 | 16 | For this project specifically you should also keep in mind that, as the focus lies on simple graphs, most graphs will at most have O(|V|^2) edges which facilitates determine the time complexity of graph algorithms. -------------------------------------------------------------------------------- /Datastructures/Graphs/Edge.cs: -------------------------------------------------------------------------------- 1 | namespace LunarDoggo.Datastructures.Graphs 2 | { 3 | //This class also has to be generic, as Vertex is already generic and this class depends on Vertex 4 | //Implementing IEquatable> helps to compare different instances of Edge for equal values 5 | public class Edge 6 | { 7 | /// 8 | public Edge(Vertex from, Vertex to, bool bidirectional) 9 | { 10 | //this check helps to avoid NullReferenceExceptions down the line 11 | if (from is null || to is null) 12 | { 13 | throw new ArgumentNullException("None of the vertices of an edge can be null!"); 14 | } 15 | 16 | this.IsBidirectional = bidirectional; 17 | this.From = from; 18 | this.To = to; 19 | } 20 | 21 | /// 22 | /// Returns whether this edge is bidirecional (i.e. if it's undirected) 23 | /// 24 | public bool IsBidirectional { get; } 25 | /// 26 | /// Returns the the edge starts at 27 | /// 28 | public Vertex From { get; } 29 | /// 30 | /// Returns the the edge ends at 31 | /// 32 | public Vertex To { get; } 33 | 34 | //Equals() is overriden because HashSets are used to store edges and therefore it's easier to avoid 35 | //duplicate entries if edges containing the same values are considered equal instead of relying on 36 | //reference equality 37 | public override bool Equals(object? obj) 38 | { 39 | //If the provided object is an edge all edge properties are compared. As there can be multiple vertices containing the same 40 | //value, two vertices are considered distinct, even if they contain the same value. As a result the Equals() method of 41 | //Vertex isn't overriden with a custom implementation 42 | return obj is Edge edge && edge.From == this.From && edge.To == this.To && edge.IsBidirectional == this.IsBidirectional; 43 | } 44 | 45 | //As the Equals method is overriden, GetHashCode has to be overriden as well 46 | public override int GetHashCode() 47 | { 48 | //Since dotnet core 2.1 there is HashCode.Combine() which facilitates creating hash codes from multiple objects 49 | return HashCode.Combine(this.From, this.To, this.IsBidirectional); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // Allgemeine Informationen über eine Assembly werden über die folgenden 8 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 9 | // die einer Assembly zugeordnet sind. 10 | [assembly: AssemblyTitle("TicTacToe")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("TicTacToe")] 15 | [assembly: AssemblyCopyright("Copyright © 2021")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly 20 | // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von 21 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. 22 | [assembly: ComVisible(false)] 23 | 24 | //Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie 25 | //ImCodeVerwendeteKultur in der .csproj-Datei 26 | //in einer fest. Wenn Sie in den Quelldateien beispielsweise Deutsch 27 | //(Deutschland) verwenden, legen Sie auf \"de-DE\" fest. Heben Sie dann die Auskommentierung 28 | //des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile, 29 | //sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher 36 | //(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird, 37 | // oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.) 38 | ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs 39 | //(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird, 40 | // designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.) 41 | )] 42 | 43 | 44 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 45 | // 46 | // Hauptversion 47 | // Nebenversion 48 | // Buildnummer 49 | // Revision 50 | // 51 | // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, 52 | // indem Sie "*" wie unten gezeigt eingeben: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /Datastructures/Graphs/IGraph.cs: -------------------------------------------------------------------------------- 1 | namespace LunarDoggo.Datastructures.Graphs 2 | { 3 | public interface IGraph 4 | { 5 | /// 6 | /// Returns all vertices contained in this graph 7 | /// 8 | IEnumerable> Vertices { get; } 9 | /// 10 | /// Returns all edges contained in this graph 11 | /// 12 | IEnumerable> Edges { get; } 13 | 14 | /// 15 | /// Removes the provided from this graph 16 | /// 17 | void RemoveVertex(Vertex vertex); 18 | /// 19 | /// Adds a new vertex containing the provided to the graph and returns the 20 | /// newly created vertex 21 | /// 22 | Vertex AddVertex(T value); 23 | 24 | /// 25 | /// Removes an existing Edge from to from the graph 26 | /// 27 | void RemoveEdge(Vertex from, Vertex to); 28 | } 29 | 30 | //Unweighted graphs can also be described as graphs where every edge has the same weight of a constant c. 31 | //This project uses two different interfaces to represent graphs noneteless, as unweighted graphs would 32 | //need to implement a parameter "weight" when adding edges, that the graph doesn't need and therefore 33 | //shouldn't implement 34 | 35 | /// 36 | /// Represents an unweighted graph that contains vertices containing values of type T 37 | /// 38 | public interface IUnweightedGraph : IGraph 39 | { 40 | /// 41 | /// Adds a new Edge from to to the graph. If the edge is 42 | /// directed or undirected depends on the implementation used 43 | /// 44 | /// 45 | Edge AddEdge(Vertex from, Vertex to); 46 | } 47 | 48 | /// 49 | /// Represents a weighted graph that contains vertices containing values of type T 50 | /// 51 | public interface IWeightedGraph : IGraph 52 | { 53 | /// 54 | /// Adds a new Edge from to with a weight of 55 | /// to the graph. If the edge is directed or undirected depends on the implementation used 56 | /// 57 | /// 58 | Edge AddEdge(Vertex from, Vertex to, float weight); 59 | /// 60 | /// Returns the weight of the provided 61 | /// 62 | /// 63 | float GetWeight(Edge edge); 64 | } 65 | } -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/Visuals/ConsoleVisualizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LunarDoggo.QuizGame.Visuals 4 | { 5 | public class ConsoleVisualizer : IVisualizer 6 | { 7 | public ConsoleVisualizer() 8 | { 9 | //this call hides the white underscore indicator of the cursor 10 | Console.CursorVisible = false; 11 | } 12 | 13 | public void DrawNoQuestions() 14 | { 15 | Console.WriteLine("No questions were loaded, please enter some questions into the json file in the applications folder.\n\nReload game? (Y/N)"); 16 | } 17 | 18 | public void DrawAnswerStatus(bool correct, QuizQuestionAnswer correctAnswer) 19 | { 20 | if (correct) 21 | { 22 | Console.WriteLine("Your answer is correct. Continue with \"enter\"."); 23 | } 24 | else 25 | { 26 | Console.WriteLine("Your answer isn't correct. The correct answer is: \"{0}\". Continue with \"enter\".", correctAnswer.Answer); 27 | } 28 | } 29 | 30 | public void DrawQuizQuestion(QuizQuestion question, Guid highlitedAnswerId) 31 | { 32 | Console.Clear(); 33 | Console.WriteLine(question.Question); 34 | Console.WriteLine(); 35 | foreach (QuizQuestionAnswer answer in question.Answers) 36 | { 37 | this.DrawQuizQuestionAnswer(answer, answer.Id == highlitedAnswerId); 38 | } 39 | Console.WriteLine(); 40 | Console.WriteLine(); 41 | } 42 | 43 | private void DrawQuizQuestionAnswer(QuizQuestionAnswer answer, bool highlited) 44 | { 45 | Console.SetCursorPosition(1, Console.CursorTop); 46 | //you can write on line conditional statements in the format: {boolean expression} ? {action when the condition is met} : {action when the condition isn't met} 47 | Console.WriteLine("({0}) {1}", highlited ? "*" : " ", answer.Answer); 48 | //in this case, the previous line could also be written as: 49 | //if(highlighted) { Console.WriteLine("({0}) {1}", "*", answer.Answer); } else { Console.WriteLine("({0}) {1}", " ", answer.Answer); } 50 | } 51 | 52 | public void DrawGameStart(int totalQuestionCount) 53 | { 54 | Console.Clear(); 55 | Console.WriteLine("{0} question{1} {2} loaded, press \"enter\" to start the game.", totalQuestionCount, totalQuestionCount > 1 ? "s" : "", totalQuestionCount > 1 ? "were" : "was"); 56 | } 57 | 58 | public void DrawGameResult(int totalQuestionCount, int correctAnswersCount) 59 | { 60 | Console.WriteLine("You got {0} out of {1} question right. Continue with \"enter\".", correctAnswersCount, totalQuestionCount); 61 | Console.WriteLine(); 62 | } 63 | 64 | public void DrawPlayAgain() 65 | { 66 | Console.WriteLine("Do you like to play again? (Y/N)"); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/Program.cs: -------------------------------------------------------------------------------- 1 | using LunarDoggo.QuizGame.Visuals; 2 | using System.Collections.Generic; 3 | using LunarDoggo.QuizGame.IO; 4 | using System.Linq; 5 | using System; 6 | 7 | namespace LunarDoggo.QuizGame 8 | { 9 | public class Program 10 | { 11 | //The declaration with the interface IVisualizer instead of declaring it as a ConsoleVisualizer has the advantage that we, 12 | //if we were to implement another visualizer for, example with OpenGL, we could swap it without rewriting the application 13 | public static IVisualizer Visualizer { get; } = new ConsoleVisualizer(); 14 | 15 | private static void Main() 16 | { 17 | bool run; 18 | 19 | do 20 | { 21 | //First load the questions from the datasource, if the questions change between the do-while-loop-iteration, 22 | //the changes are reflected in the next run of the loop 23 | IEnumerable questions = Program.GetQuestions(); 24 | //if questions were loaded, start the game, otherwise prompt the user to update the question-datasource 25 | if (questions.Any()) //Note: .Any() is part of the extension methods from System.Linq and returns whether there are any entries in the questions collection 26 | { 27 | Program.RunGameLoop(questions); 28 | } 29 | else 30 | { 31 | Program.Visualizer.DrawNoQuestions(); 32 | } 33 | 34 | //If the user presses the "Y"-Key, we want to run the loop again, otherwise, the application terminates 35 | run = Console.ReadKey().Key == ConsoleKey.Y; 36 | } while (run); 37 | } 38 | 39 | /// 40 | /// Instantiate and run the with the provided s 41 | /// 42 | private static void RunGameLoop(IEnumerable questions) 43 | { 44 | GameLoop gameLoop = new GameLoop(Program.Visualizer, questions); 45 | //while the game isn't finished, we want to draw to the screen run updates to the gamestate and process user input 46 | while (!gameLoop.IsFinished) 47 | { 48 | gameLoop.DoTick(); 49 | } 50 | //when the game is finished, we want to ask the user if they want to play again 51 | Program.Visualizer.DrawPlayAgain(); 52 | } 53 | 54 | /// 55 | /// Load all questions from the datasource 56 | /// 57 | private static IEnumerable GetQuestions() 58 | { 59 | string filePath = ".\\game_questions.json"; 60 | //if we were to implement another datasource (e.g. MySQLQuizQuestionSerializer) we could swap it here 61 | IQuizQuestionSerializer serializer = new FileQuizQuestionSerializer(filePath); 62 | return serializer.DeserializeQuestions(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Concepts/Big O notation.md: -------------------------------------------------------------------------------- 1 | # Landau Notation 2 | Landau notation (or big O notation) describes describes the growth of a particular function. In computer science it's often used to analyze and classify algorithms according to their so called "time complexity" and "space complexity". 3 | 4 | # Symbols 5 | The following symbols are used to denote the growth of a function **f**: 6 | - **O(g(n))** (big O): means that the function **f** grows as fast or slower than **g** for big **n** 7 | - **Θ(g(n))** (big Theta): means that the function **f** grows exactly as fast as **g** for big **n** 8 | - **Ω(g(n))** (big Omega): means that the function **f** grows at least as fast as **g** for big **n** 9 | - **o(g(n))** (small O): means that the function **f** grows slower than **g** for big **n** 10 | - **ω(g(n))** (small omega): means that the function **f** grows faster than **g** for big **n** 11 | 12 | Big O is most commonly used in practice, but Θ and Ω also occur sometimes. The other two (o, ω) are used quite rarely in algorithm analysis. Some important things to note are that: 13 | 1. all of these notations only make sense if **n** approaches infinity, as, for example, the time difference between the execution of two algorithms is almost zero for a small dataset in practice and there may be cases where **O(f(n)) > O(g(n))**, but **f(n) < g(n)** for small **n** values 14 | 2. there is a certain order of which function grows faster as another one, such as **O(1) < O(n) < O(n * log(n)) < O(n^2) < O(2^n)** 15 | 3. an algorithm is most commonly considered efficient if it has a polynomial worst case time complexity. The biggest exponent of the function is irrelevant for that definition, **O(n)** is efficient, as well as **O(n^10000000)** 16 | 4. there are rules for combinding multiple big **O** (or one of the other notations, as long as all symbols match) notations into one: 17 | - multiplicative constants can be ignored: **O(n) = O(2n)** 18 | - **O(a) + O(b) = O(a + b)**, if **O(a) > O(b)**, **O(b)** can be omitted, if **O(a) < O(b)**, **O(a)** can be omitted, if **O(a) = O(b)**, either one can be omitted. You can see this rule in action when using graphs, as a time complexity of **O(|V| + |E|)** could be reduced to **O(|V|^2)**, as **O(|E|) < O(|V|^2)** in general, but there are graphs where **O(|E|) = O(|V|)**, so it's sometimes better to keep both around to make the upper bound more strict 19 | - **O(a) * O(b) = O(a * b)**, this rule is for example used when analyzing loops. If the body of a loop has a time complexity of **O(a)** and the loop runs **O(b)** times, there are **O(b)** occurrences of **O(a)** in the analysis, so you would multiply them 20 | 5. You can analyze the best- average- and worst-case time/space complexity separately, for example **InsertionSort** has a best case time complexity of **O(n)** where **n** is the amount of items in the sorted array, but the average- and worst-case time complexity is **O(n^2)** 21 | 22 | Concrete examples and further clarification for points **1.** and **2.** can be found on [libretexts.org](https://eng.libretexts.org/Bookshelves/Computer_Science/Programming_Languages/Think_Python_-_How_to_Think_Like_a_Computer_Scientist_(Downey)/13%3A_Appendix_B-_Analysis_of_Algorithms/13.01%3A_Order_of_Growth) -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Dieser Code wurde von einem Tool generiert. 4 | // Laufzeitversion: 4.0.30319.42000 5 | // 6 | // Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn 7 | // der Code erneut generiert wird. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | namespace TicTacToe.Properties 13 | { 14 | /// 15 | /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. 16 | /// 17 | // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse 18 | // über ein Tool wie ResGen oder Visual Studio automatisch generiert. 19 | // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen 20 | // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu. 21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 24 | internal class Resources 25 | { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() 33 | { 34 | } 35 | 36 | /// 37 | /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. 38 | /// 39 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 40 | internal static global::System.Resources.ResourceManager ResourceManager 41 | { 42 | get 43 | { 44 | if ((resourceMan == null)) 45 | { 46 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TicTacToe.Properties.Resources", typeof(Resources).Assembly); 47 | resourceMan = temp; 48 | } 49 | return resourceMan; 50 | } 51 | } 52 | 53 | /// 54 | /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle 55 | /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden. 56 | /// 57 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 58 | internal static global::System.Globalization.CultureInfo Culture 59 | { 60 | get 61 | { 62 | return resourceCulture; 63 | } 64 | set 65 | { 66 | resourceCulture = value; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/Visuals/IVisualizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LunarDoggo.QuizGame.Visuals 4 | { 5 | /* 6 | * Interfaces in C# are like blueprints for classes, every class that "implements" this interface must also define all 7 | * methods and properties of this interface as public members. 8 | * Interfaces can be used to define common methods and properties of multiple classes in order to be able to change 9 | * the instance of a concrete class in the source code without having to rewrite the application. 10 | * In the real world interfaces are for example used, when you have multiple datasources like databases, files, ... 11 | * or rendering-libraries like DirectX, OpenGL, Vulcan, ... which can be swapped in and out at runtime 12 | * 13 | * In this case, all classes that implement IQuizQuestionSerializer must declare the following public methods as voids: 14 | * DrawAnswerStatus(bool correct, QuizQuestionAnswer correctAnswer) 15 | * DrawQuizQuestion(QuizQuestion question, Guid highlitedAnswerId) 16 | * DrawGameResult(int totalQuestionCount, int correctAnswersCount) 17 | * DrawGameStart(int totalQuestionCount) 18 | * DrawNoQuestions() 19 | * DrawPlayAgain() 20 | */ 21 | public interface IVisualizer 22 | { 23 | /// 24 | /// Draws if the answer the user gave was correct or wrong 25 | /// 26 | /// bool-indicator if the last given answer was correct 27 | /// answer to be displayed if correct is set to false 28 | void DrawAnswerStatus(bool correct, QuizQuestionAnswer correctAnswer); 29 | 30 | /// 31 | /// Draws a to the display and highlights the currenctly selected 32 | /// where equals 33 | /// 34 | /// question to be shown 35 | /// to be highlighted 36 | void DrawQuizQuestion(QuizQuestion question, Guid highlitedAnswerId); 37 | 38 | /// 39 | /// After the game is finished, this method draws the overall result 40 | /// 41 | /// Count of all asked questions 42 | /// Cound of questions the user got correct 43 | void DrawGameResult(int totalQuestionCount, int correctAnswersCount); 44 | 45 | /// 46 | /// Before the game starts, this method draws the count of answers loaded from the file 47 | /// 48 | void DrawGameStart(int totalQuestionCount); 49 | 50 | /// 51 | /// When no questions could be loaded from the file, this method tells the user to update the json question file 52 | /// 53 | void DrawNoQuestions(); 54 | 55 | /// 56 | /// When the game is finished, this method asks the user if they want to play another round of the game 57 | /// 58 | void DrawPlayAgain(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.QuizGame/IO/FileQuizQuestionSerializer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json; 3 | using System.IO; 4 | using System; 5 | using System.Text.Json.Serialization; 6 | 7 | namespace LunarDoggo.QuizGame.IO 8 | { 9 | /* 10 | * In this case, FileQuizQuestionSerializer implements the interface IQuizQuestionSerializer so that other 11 | * serializers (for example database) can be implemented to swap between the implementations 12 | */ 13 | public class FileQuizQuestionSerializer : IQuizQuestionSerializer 14 | { 15 | private readonly string filePath; 16 | 17 | /// Absolute or relative file path to the quiz question json file 18 | public FileQuizQuestionSerializer(string filePath) 19 | { 20 | this.filePath = filePath; 21 | } 22 | 23 | public IEnumerable DeserializeQuestions() 24 | { 25 | string content = this.GetFileContent(this.filePath); 26 | IEnumerable questions = this.DeserializeJson(content); 27 | this.SetGuids(questions); 28 | return questions; 29 | } 30 | 31 | /// 32 | ///We don't trust the user to correctly set the Ids of the and . In order to prevent duplicate Ids 33 | ///this method assigns a unique to every and its s 34 | /// 35 | private void SetGuids(IEnumerable questions) 36 | { 37 | foreach (QuizQuestion question in questions) 38 | { 39 | //Guid.NewGuid() generates a new random Guid 40 | question.Id = Guid.NewGuid(); 41 | foreach (QuizQuestionAnswer answer in question.Answers) 42 | { 43 | answer.Id = Guid.NewGuid(); 44 | } 45 | } 46 | } 47 | 48 | private IEnumerable DeserializeJson(string content) 49 | { 50 | JsonSerializerOptions options = new JsonSerializerOptions() 51 | { 52 | DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, //if a property has the value "null", it will be ignored 53 | ReadCommentHandling = JsonCommentHandling.Skip, //when the json content contains comments, they will be ignored 54 | PropertyNameCaseInsensitive = true, //the casing of propertynames will be ignored for the deserialization 55 | AllowTrailingCommas = true //if the json content contains a lonely ",", it will be ignored 56 | }; 57 | 58 | //System.Text.Json.JsonSerializer deserializes the content string into a QuizQuestion array 59 | return JsonSerializer.Deserialize(content, options); 60 | } 61 | 62 | private string GetFileContent(string filePath) 63 | { 64 | //Check if the file exists, if not, return an empty string to prevent a FileNotFoundException, otherwise return the files content 65 | //Note that file access violations (e. g. another application has the file locked) are not handled and will lead to an exception 66 | if (File.Exists(filePath)) 67 | { 68 | return File.ReadAllText(filePath); 69 | } 70 | return String.Empty; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.FileSystemTree/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.IO; 5 | using System; 6 | 7 | namespace LunarDoggo.FileSystemTree 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | string baseDirectoryPath = Program.GetBaseDirectoryPath(); 14 | DirectoryInfo baseDirectory = new DirectoryInfo(baseDirectoryPath); 15 | 16 | FileSystemTreeItem fileSystemTree = Program.GetFileSystemTree(baseDirectory); 17 | 18 | Program.OutputFileSystemTreeLevel(0, fileSystemTree); 19 | } 20 | 21 | private static void OutputFileSystemTreeLevel(int indentationLevel, FileSystemTreeItem item) 22 | { 23 | //for each indentationlevel we add two spaces 24 | string indentation = new string(Enumerable.Repeat(' ', indentationLevel * 2).ToArray()); 25 | 26 | //combine the indentation with the current tree items name and type 27 | Console.WriteLine(indentation + item.Name + " (" + item.Type + ")"); 28 | 29 | //if the current tree item has any children, recursively print them and 30 | //their children to the console with the corresponding indentatino level 31 | if (item.Children != null && item.Children.Count() > 0) 32 | { 33 | foreach (FileSystemTreeItem child in item.Children) 34 | { 35 | Program.OutputFileSystemTreeLevel(indentationLevel + 1, child); 36 | } 37 | } 38 | } 39 | 40 | /// 41 | /// Recursive Method to get the file system structure as a tree 42 | /// 43 | private static FileSystemTreeItem GetFileSystemTree(DirectoryInfo baseDirectory) 44 | { 45 | //Read all subdirectories and files from the current baseDirectory 46 | DirectoryInfo[] subdirectories = baseDirectory.GetDirectories(); 47 | FileInfo[] files = baseDirectory.GetFiles(); 48 | 49 | List children = new List(); 50 | 51 | //First recursively add all subdirectories with its children to the current tree item 52 | foreach (DirectoryInfo subdirectory in subdirectories) 53 | { 54 | //add all tree items from 55 | children.Add(Program.GetFileSystemTree(subdirectory)); 56 | } 57 | 58 | //Lastly add all files of the current tree item 59 | foreach (FileInfo file in files) 60 | { 61 | children.Add(new FileSystemTreeItem(file.Name, FileSystemTreeItemType.File, null)); 62 | } 63 | 64 | return new FileSystemTreeItem(baseDirectory.Name, FileSystemTreeItemType.Directory, children.ToImmutableArray()); 65 | } 66 | 67 | /// 68 | /// Get the base directory path from user input 69 | /// 70 | private static string GetBaseDirectoryPath() 71 | { 72 | string path; 73 | do 74 | { 75 | Console.Clear(); //Clear the console window 76 | Console.Write("Please enter a valid directory path: "); 77 | path = Console.ReadLine(); 78 | 79 | //While the user input is not a valid path and therefore doesn't exist, continue to prompt for a valid directory path 80 | } while (!Directory.Exists(path)); 81 | return path; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Datastructures/Collections/Stack.cs: -------------------------------------------------------------------------------- 1 | using LunarDoggo.Datastructures.Exceptions; 2 | 3 | namespace LunarDoggo.Datastructures.Collections 4 | { 5 | //A stack is a so called LIFO (last in, first out) data structure that can be imagined as a pile of objects 6 | //stacked on one and another. If you want to put something on the pile you put it on the top, and if you 7 | //want to retrieve an object that's in the middle of the stack you have to remove all the objects that are 8 | //on top of the object to be retrieved. 9 | //The most primitive implementation uses an array that's not resized over the stack's lifetime. If the stack 10 | //runs full and another object is added, an exception is thrown signifying that no more items can be pushed 11 | //onto the stack 12 | public class Stack 13 | { 14 | //-1 means that there are no items in the cache yet 15 | private int currentIndex = -1; 16 | private readonly T[] cache; 17 | 18 | public Stack(int capacity) 19 | { 20 | //The initialization of the stack has a time complexity of O(capacity), as C# not only allocates a certain memory 21 | //range, but also sets all cells of the array to the default value of type T 22 | 23 | //As the array will never be resized or reallocated, the capacity of the stack has to be provided on initialization 24 | this.cache = new T[capacity]; 25 | } 26 | 27 | /// 28 | /// Pushes another item of type onto the stack 29 | /// 30 | /// 31 | public void Push(T item) 32 | { 33 | //Push has a time complexity of O(1), as only constant time operations are used sequentially 34 | if (currentIndex >= this.cache.Length - 1) 35 | { 36 | throw new OverflowException("The stack is already full"); 37 | } 38 | 39 | this.currentIndex++; 40 | this.cache[this.currentIndex] = item; 41 | } 42 | 43 | /// 44 | /// Removes the item on top of the stack from the stack and returns the previously contained value 45 | /// 46 | /// 47 | public T Pop() 48 | { 49 | //Pop has a time complexity of O(1), as only constant time operations are used sequentially 50 | T output = this.Peek(); 51 | //usually the cells of removed values aren't reset to the default value of T, but this could 52 | //result in security issues, as sensitive deleted data isn't garbage collected as soon as possible 53 | this.cache[this.currentIndex] = default; 54 | return output; 55 | } 56 | 57 | /// 58 | /// Returns the item that's on top of the stack 59 | /// 60 | /// 61 | public T Peek() 62 | { 63 | //Peek has a time complexity of O(1), as only constant time operations are used sequentially 64 | if (this.IsEmpty) 65 | { 66 | throw new UnderflowException("The stack is empty"); 67 | } 68 | 69 | return this.cache[this.currentIndex]; 70 | } 71 | 72 | /// 73 | /// Returns whether the stack is empty 74 | /// 75 | public bool IsEmpty 76 | { 77 | //IsEmpty has a time complexity of O(1), as only constant time operations are used sequentially 78 | get => this.currentIndex < 0; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Algorithms/Graphs/Pathfinding/BreadthFirstSearch.cs: -------------------------------------------------------------------------------- 1 | using LunarDoggo.Datastructures.Graphs; 2 | 3 | namespace LunarDoggo.Algorithms.Graphs.Pathfinding 4 | { 5 | //BFS is a basic pathfinding algorithm that works on unweighted graphs. It doesn't matter if the graph is directed 6 | //or undirected. The time complexity of BFS is O(|V| + |E|), as the algorithm processes every vertex and iterates over every edge in the graph exactly once 7 | //In simple graphs |E| is bounded by O(|V|^2), so in such cases, one could use O(|V|^2) as the time complexity 8 | public class BreadthFirstSearch 9 | { 10 | public void Run(IGraph graph, Vertex start) 11 | { 12 | if (graph is null) 13 | { 14 | throw new ArgumentNullException("The graph the DFS should be run on cannot be null"); 15 | } 16 | 17 | this.Initialize(graph, start); 18 | 19 | //BFS is usually implemented in a way that doesn't work on disconnected graphs. BFS can therefore be 20 | //used to find all vertices contained in a connected component of the graph. 21 | //BFS additionally is implemented iteratively using a queue. One could imagine the execution as a wave that propagates from the starting vertex to all reachable vertices of the graph 22 | Queue> queue = new Queue>(); 23 | queue.Enqueue(start); 24 | while (queue.Count > 0) 25 | { 26 | Vertex current = queue.Dequeue(); 27 | foreach (Vertex vertex in current.Adjacent) 28 | { 29 | //If a processed adjacent vertex is found, it doesn't have to be processed again, as the distance from the start cannot be lower 30 | //than the currently set distance 31 | if (!vertex.Value.Processed) 32 | { 33 | vertex.Value.Distance = current.Value.Distance + 1; 34 | vertex.Value.Predecessor = current; 35 | vertex.Value.Processed = true; 36 | } 37 | } 38 | } 39 | } 40 | 41 | private void Initialize(IGraph graph, Vertex start) 42 | { 43 | //Every vertex is initialized with the maximum possible distance to signify that the distance is invalid. 44 | foreach (Vertex vertex in graph.Vertices) 45 | { 46 | vertex.Value = new BFSVertex() 47 | { 48 | Distance = Int32.MaxValue, 49 | Predecessor = null, 50 | Processed = false 51 | }; 52 | } 53 | 54 | //The starting vertex, is guaranteed to be reachable from the start with a distance of 0 edges. The start also 55 | //doesn't have a predecessor, as it is an end vertex of every found start-vertex-path 56 | start.Value.Processed = true; 57 | start.Value.Distance = 0; 58 | } 59 | } 60 | 61 | public class BFSVertex 62 | { 63 | /// 64 | /// Returns whether this vertex has already been processed. The processed flag has to be set by the algorithm 65 | /// 66 | public bool Processed { get; set; } 67 | /// 68 | /// Returns the predecessor of this vertex on the path from the starting vertex 69 | /// 70 | public Vertex Predecessor { get; set; } 71 | /// 72 | /// Returns the distance in edges of this vertex to the start vertex 73 | /// 74 | public int Distance { get; set; } 75 | } 76 | } -------------------------------------------------------------------------------- /Datastructures/Graphs/UndirectedUnweightedGraph.cs: -------------------------------------------------------------------------------- 1 | namespace LunarDoggo.Datastructures.Graphs 2 | { 3 | public class UndirectedUnweightedGraph : IUnweightedGraph 4 | { 5 | //Using HashSets for storing the vertices and edges, again, facilitates managing the collections more easily, 6 | //as it makes removing and checking for entries easier while avoiding duplicate entries 7 | private HashSet> vertices = new HashSet>(); 8 | private HashSet> edges = new HashSet>(); 9 | 10 | //If the original HashSet was returned, it would be possible to modify the original collection of vertices/edges 11 | //therefore the LINQ method ToArray() is called to return a copy of the original sets 12 | public IEnumerable> Vertices { get => this.vertices.ToArray(); } 13 | public IEnumerable> Edges { get => this.edges.ToArray(); } 14 | 15 | private int lastId = 0; 16 | 17 | public Edge AddEdge(Vertex from, Vertex to) 18 | { 19 | //this lock ensures thread safety when adding edges, as multithreaded Add operations without locks can lead to null 20 | //entries in the collection 21 | lock (this.edges) 22 | { 23 | //The ArgumentNullException advertised in the definition of AddEdge in IUnweightedGraph will be thrown by the 24 | //constructor of Edge, therefore it isn't necessary to check from and to for null values here 25 | Edge edge = new Edge(from, to, true); 26 | 27 | //As the edge and adjacencies are stored in HashSets, it isn't necessary to check if it already exists 28 | this.edges.Add(edge); 29 | from.AddAdjacency(to); 30 | to.AddAdjacency(from); 31 | 32 | return edge; 33 | } 34 | } 35 | 36 | public Vertex AddVertex(T value) 37 | { 38 | //lock is used to ensure thread safety when incrementing lastId. The lock is set on vertices because 39 | //locks can only be set on reference types and lastId, as an Int32, is a ValueType 40 | lock (this.vertices) 41 | { 42 | Vertex vertex = new Vertex(this.lastId, value); 43 | //If an exception ocurrs when adding a vertex, the increment to lastId will not happen, which is intended behavior 44 | this.vertices.Add(vertex); 45 | this.lastId++; 46 | return vertex; 47 | } 48 | } 49 | 50 | public void RemoveEdge(Vertex from, Vertex to) 51 | { 52 | lock (this.edges) 53 | { 54 | //As edges that contain the same values are considered equal and all edges are stored in a HashSet, 55 | //edges can be removed by removing a new and equal edge from edges 56 | Edge edge = new Edge(from, to, true); 57 | this.edges.Remove(edge); 58 | //The adjacency lists of the vertices also have to be updated 59 | from.RemoveAdjacency(to); 60 | to.RemoveAdjacency(from); 61 | } 62 | } 63 | 64 | public void RemoveVertex(Vertex vertex) 65 | { 66 | lock (this.vertices) 67 | { 68 | this.vertices.Remove(vertex); 69 | //the provided vertex is only removed from the adjacency lists of the remaining vertices without clearing 70 | //its own adjacency list, as it is no longer part of the graph and will likely be garbage collected soon 71 | foreach (Vertex v in this.vertices) 72 | { 73 | v.RemoveAdjacency(vertex); 74 | } 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /Datastructures/Trees/Tree.cs: -------------------------------------------------------------------------------- 1 | namespace LunarDoggo.Datastructures.Trees 2 | { 3 | //Trees are a special kind of graph: they're connected, undirected, acyclic and unweighted. In general trees konsist of 4 | //Individual vertices (thereafter "TreeItems") that may have an arbitrary amount of children 5 | //The traversal of trees is similar to that of doubly linked lists with the difference that each item may have an arbitrary 6 | //amount of successors instead of a maximum of one. 7 | 8 | //Note: one could also declare a class called Tree, but it would only contain a reference to the root and maybe 9 | // some operations that aren't considered standard for trees, so instead one would store a reference to the root 10 | // TreeItem of the tree in the code using the tree 11 | 12 | //A TreeItem is a single vertex in the tree. It contains a value and stores references to an arbitrary amount of child 13 | //TreeItems. To ensure that there cannot be a cycle in the tree, the AddChild method takes an instance of type T instead 14 | //of a TreeItem instance 15 | public class TreeItem 16 | { 17 | //Using a HashSet instead of a List is advantageous for this use case, as it usually doesn't take O(n) time to find 18 | //a single item. As every child is an independent object, it's unlikely that two different children come into 19 | //conflict (a set is characterized by only containing unique objects). Add and Remove operations on HashSets have 20 | //a time complexity of O(n), though most operations will take constant time, if the hashing algorithm used is 21 | //sufficiently evenly distributed (this should be the case with the implementation of the standard library) 22 | private readonly HashSet> children = new HashSet>(); 23 | 24 | public TreeItem(T value) : this(value, null) 25 | { } 26 | 27 | //This constructor is declared as private to prevent users from creating cycles 28 | private TreeItem(T value, TreeItem parent) 29 | { 30 | this.Parent = parent; 31 | this.Value = value; 32 | } 33 | 34 | /// 35 | /// Adds a new TreeItem containing the provided value to the children of this TreeItem 36 | /// 37 | public void AddChild(T value) 38 | { 39 | //The AddChild operation could be implemented in O(1) time using a List, but the amortized time complexity 40 | //using .NET's HashSet should also be O(1) 41 | //again: to prevent cycles in the tree from happening, the user isn't allowed to pass 42 | //TreeItem instances directly 43 | this.children.Add(new TreeItem(value)); 44 | } 45 | 46 | /// 47 | /// Removes a child from the tree if it is present 48 | /// 49 | public void RemoveChild(TreeItem child) 50 | { 51 | //The RemoveChild operation has a time complexity of O(n) regardless of if a List or HashSet is used, though 52 | //using .NET's HashSet it's likely to have a amortized time complexity of O(1) 53 | this.children.Remove(child); 54 | } 55 | 56 | /// 57 | /// Deletes this TreeItem from the tree 58 | /// 59 | public void Delete() 60 | { 61 | if(this.Parent != null) 62 | { 63 | this.Parent.RemoveChild(this); 64 | } 65 | } 66 | 67 | /// 68 | /// Returns a collection of all children of this TreeItem 69 | /// 70 | public IEnumerable> Children { get => this.children.AsEnumerable(); } 71 | /// 72 | /// Returns the Value stored in this TreeItem 73 | /// 74 | public T Value { get; set; } 75 | /// 76 | /// Returns the parent TreeItem of this TreeItem 77 | /// 78 | public TreeItem Parent { get; private set; } 79 | } 80 | } -------------------------------------------------------------------------------- /Datastructures/Collections/LinkedList.cs: -------------------------------------------------------------------------------- 1 | namespace LunarDoggo.Datastructures.Collections 2 | { 3 | //A doubly linked list ist a data structure that is composed of single items that have a value and a reference to 4 | //the previous item and the next item in the list. The list itself only stores a reference to the the current head 5 | //(i.e. the first item) of the list. 6 | //If an item has to be inserted, a new item is created, linked and set as the new head. If one would want to insert 7 | //items at the end of the list, one would have to keep a reference to the tail of the list and add the new item after 8 | //that. 9 | //In practice array-based lists are preferred over linked lists in most cases, as following so many references is less 10 | //efficient than reading values from an array. 11 | //Linked lists don't need a delete operation, as the links only consist of references between items, if one would want 12 | //to remove an item from the list, one must only reassign the the next reference of the item's previous item and the 13 | //previous reference of the item's next item in O(1) time 14 | public class LinkedList where T : class //T must be a class because otherwise the "!=" operator isn't defined for generic T's 15 | { 16 | //The only thing to be done on initialization is to assign a new field of type LinkedListItem that represents the 17 | //head and is initialized with null 18 | private LinkedListItem head; 19 | 20 | /// 21 | /// Searches for the first item in the linked list that contains the provided and returns the 22 | /// list item if it exists 23 | /// 24 | public LinkedListItem Search(T value) 25 | { 26 | //The search operation has a time complexity of O(n) where n is the number of items in the list, as in the worst case 27 | //every item in the list has to be checked if it contains the searched value 28 | 29 | //If head is null, the loop won't run and null is returned. If the value isn't contained in the list, Search also returns 30 | //null after checking every single item. Otherwise there must be an item containing the searched value, that's found after 31 | //at most O(n) checks 32 | LinkedListItem current = head; 33 | while (current != null && current.Value != value) 34 | { 35 | current = current.Next; 36 | } 37 | return current; 38 | } 39 | 40 | /// 41 | /// Inserts a new list item at the beginning of the linked list 42 | /// 43 | public LinkedListItem Insert(T value) 44 | { 45 | //New items are inserted at the front of the list, therefore the previous reference of this.head has to be updated and 46 | //the new item has to be set as the new head 47 | LinkedListItem item = new LinkedListItem(value); 48 | item.Next = this.head; 49 | if (this.head != null) 50 | { 51 | this.head.Previous = item; 52 | } 53 | this.head = item; 54 | return item; 55 | } 56 | } 57 | 58 | public class LinkedListItem 59 | { 60 | public LinkedListItem(T value) 61 | { 62 | this.Value = value; 63 | } 64 | 65 | /// 66 | /// Gets or sets the reference to the item that's preceeding the current item in the linked list 67 | /// 68 | public LinkedListItem Previous { get; set; } 69 | /// 70 | /// Gets or sets the reference to item that's following the current item in the linked list 71 | /// 72 | public LinkedListItem Next { get; set; } 73 | /// 74 | /// Returns the value contained in the current list item 75 | /// 76 | public T Value { get; } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Projects/LunarDoggo.TicTacToe/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 14 | 15 | 16 | 17 | 18 | 20 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 48 |