diff --git a/Memory.Cmd/Memory.Cmd.csproj b/Memory.Cmd/Memory.Cmd.csproj
new file mode 100644
index 0000000..4613569
--- /dev/null
+++ b/Memory.Cmd/Memory.Cmd.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/Memory.Cmd/Program.cs b/Memory.Cmd/Program.cs
new file mode 100644
index 0000000..bfe26a0
--- /dev/null
+++ b/Memory.Cmd/Program.cs
@@ -0,0 +1,29 @@
+using Memory.Logic;
+
+namespace Memory.Cmd
+{
+ internal class Program
+ {
+ static void Main()
+ {
+ Game game = new();
+ Renderer renderer = new(game);
+ while (!game.IsFinished())
+ {
+ renderer.Render();
+ Console.Write("Enter card number: ");
+ try
+ {
+ game.ClickCard(game.Cards[int.Parse(Console.ReadLine()!) - 1]);
+ }
+ catch (Exception)
+ {
+ Console.WriteLine("Invalid card number given.");
+ Console.ReadLine();
+ }
+ Console.Clear();
+ }
+ renderer.Render();
+ }
+ }
+}
diff --git a/Memory.Cmd/Renderer.cs b/Memory.Cmd/Renderer.cs
new file mode 100644
index 0000000..22008b6
--- /dev/null
+++ b/Memory.Cmd/Renderer.cs
@@ -0,0 +1,94 @@
+using Memory.Logic;
+using System;
+using System.Reflection;
+
+namespace Memory.Cmd
+{
+ internal class Renderer(Game game)
+ {
+ private readonly Game game = game;
+
+ private static string FormatNumber(int number)
+ {
+ string num = "";
+ int padding = Game.DECKSIZE.ToString().Length - number.ToString().Length;
+ for (int i = 0; i < padding; i++)
+ {
+ num += '0';
+ }
+ num += number;
+ return num;
+ }
+
+ private static void DrawCard(Card card, int index, int column, int row)
+ {
+ string num = FormatNumber(card.ID);
+ string cardNr = FormatNumber(index);
+ int cardWidth = Game.DECKSIZE.ToString().Length + 4;
+ for (int i = 0; i < Game.GRIDSIZE; i++)
+ {
+ Console.CursorLeft += (cardWidth + 1) * column;
+ Console.CursorTop = i + ((Game.GRIDSIZE + 1) * row);
+ for (int j = 0; j < cardWidth; j++)
+ {
+ if (i == 0)
+ {
+ Console.Write('#');
+ }
+ else if (i == Game.GRIDSIZE - 1)
+ {
+ if (j > 1 && j < cardWidth - 2)
+ {
+ Console.Write(cardNr[j - 2]);
+ }
+ else
+ {
+ Console.Write('#');
+ }
+ }
+ else if (j == 0 || j == cardWidth - 1)
+ {
+ Console.Write('#');
+ }
+ else if (i == Game.GRIDSIZE / 2 && j > 1 && j < cardWidth - 2)
+ {
+ if (card.Selected())
+ {
+ Console.Write(num[j - 2]);
+ }
+ else
+ {
+ Console.Write('*');
+ }
+ }
+ else
+ {
+ Console.Write(' ');
+ }
+ }
+ Console.Write('\n');
+ }
+ }
+
+ public void Render()
+ {
+ for (int i = 0; i < game.Cards.Count; i++)
+ {
+ Card card = game.Cards[i];
+ if (!card.Completed)
+ {
+ if (card.Selected())
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ }
+ else
+ {
+ Console.ForegroundColor= ConsoleColor.Red;
+ }
+ DrawCard(game.Cards[i], i + 1, i % Game.GRIDSIZE, i / Game.GRIDSIZE);
+ Console.ForegroundColor = ConsoleColor.White;
+ }
+ }
+ }
+ }
+}
diff --git a/Memory.Gui/App.xaml b/Memory.Gui/App.xaml
new file mode 100644
index 0000000..14a3829
--- /dev/null
+++ b/Memory.Gui/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/Memory.Gui/App.xaml.cs b/Memory.Gui/App.xaml.cs
new file mode 100644
index 0000000..3ee6ed3
--- /dev/null
+++ b/Memory.Gui/App.xaml.cs
@@ -0,0 +1,14 @@
+using System.Configuration;
+using System.Data;
+using System.Windows;
+
+namespace Memory.Gui
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+
+}
diff --git a/Memory.Gui/AssemblyInfo.cs b/Memory.Gui/AssemblyInfo.cs
new file mode 100644
index 0000000..b0ec827
--- /dev/null
+++ b/Memory.Gui/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/src/MainWindow.xaml b/Memory.Gui/MainWindow.xaml
similarity index 81%
rename from src/MainWindow.xaml
rename to Memory.Gui/MainWindow.xaml
index ba19bae..19c03b9 100644
--- a/src/MainWindow.xaml
+++ b/Memory.Gui/MainWindow.xaml
@@ -1,9 +1,9 @@
-
diff --git a/src/MainWindow.xaml.cs b/Memory.Gui/MainWindow.xaml.cs
similarity index 95%
rename from src/MainWindow.xaml.cs
rename to Memory.Gui/MainWindow.xaml.cs
index 9e21445..9cc8b5b 100644
--- a/src/MainWindow.xaml.cs
+++ b/Memory.Gui/MainWindow.xaml.cs
@@ -9,7 +9,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
-namespace Memory
+namespace Memory.Gui
{
///
/// Interaction logic for MainWindow.xaml
diff --git a/src/Memory.csproj b/Memory.Gui/Memory.Gui.csproj
similarity index 64%
rename from src/Memory.csproj
rename to Memory.Gui/Memory.Gui.csproj
index 0c3364d..e3e33e3 100644
--- a/src/Memory.csproj
+++ b/Memory.Gui/Memory.Gui.csproj
@@ -1,13 +1,11 @@
- Exe
+ WinExe
net8.0-windows
enable
enable
true
- Memory.Program
- true
diff --git a/src/Memory.csproj.user b/Memory.Gui/Memory.Gui.csproj.user
similarity index 64%
rename from src/Memory.csproj.user
rename to Memory.Gui/Memory.Gui.csproj.user
index 0c37011..644b0a6 100644
--- a/src/Memory.csproj.user
+++ b/Memory.Gui/Memory.Gui.csproj.user
@@ -1,6 +1,11 @@
+
+
+ Designer
+
+
Designer
diff --git a/Memory.Logic/Card.cs b/Memory.Logic/Card.cs
new file mode 100644
index 0000000..6f9acd9
--- /dev/null
+++ b/Memory.Logic/Card.cs
@@ -0,0 +1,20 @@
+namespace Memory.Logic
+{
+ public class Card(int id)
+ {
+ public int ID { get; } = id;
+ public bool IsChoice1 { get; set; } = false;
+ public bool IsChoice2 { get; set; } = false;
+ public bool Completed { get; set; } = false;
+
+ public bool Matches(Card card)
+ {
+ return ID == card.ID;
+ }
+
+ public bool Selected()
+ {
+ return IsChoice1 || IsChoice2;
+ }
+ }
+}
diff --git a/Memory.Logic/Game.cs b/Memory.Logic/Game.cs
new file mode 100644
index 0000000..e03e2a0
--- /dev/null
+++ b/Memory.Logic/Game.cs
@@ -0,0 +1,67 @@
+namespace Memory.Logic
+{
+ public class Game
+ {
+ public const int DECKSIZE = 10;
+ public const int GRIDSIZE = 5;
+ public List Cards { get; } = CreateDeck(DECKSIZE);
+
+ private static List CreateDeck(int pairs)
+ {
+ List cards = [];
+ for (int i = 1; i < pairs + 1; i++)
+ {
+ cards.Add(new(i));
+ cards.Add(new(i));
+ }
+ Random random = new();
+ return [..cards.OrderBy(card => random.Next())];
+ }
+
+ public Card? GetChoice1()
+ {
+ return Cards.FirstOrDefault(card => card.IsChoice1);
+ }
+
+ public Card? GetChoice2()
+ {
+ return Cards.FirstOrDefault(card => card.IsChoice2);
+ }
+
+ public bool IsFinished()
+ {
+ return Cards.All(card => card.Completed);
+ }
+
+ public void ClickCard(Card card)
+ {
+ Card? choice1 = GetChoice1();
+ Card? choice2 = GetChoice2();
+ if (!card.Completed)
+ {
+ if ((choice1 == null && choice2 == null) || (choice1 != null && choice2 != null))
+ {
+ if (choice1 != null)
+ {
+ choice1.IsChoice1 = false;
+ }
+ if (choice2 != null)
+ {
+ choice2.IsChoice2 = false;
+ }
+ card.IsChoice1 = true;
+ }
+ else if (choice1 != null && choice2 == null && choice1 != card)
+ {
+ card.IsChoice2 = true;
+ if (choice1.Matches(card))
+ {
+ choice1.Completed = true;
+ card.Completed = true;
+ // handle score etc
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Memory.Logic/Memory.Logic.csproj b/Memory.Logic/Memory.Logic.csproj
new file mode 100644
index 0000000..fa71b7a
--- /dev/null
+++ b/Memory.Logic/Memory.Logic.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/Memory.sln b/Memory.sln
index f4b10de..a76a0b0 100644
--- a/Memory.sln
+++ b/Memory.sln
@@ -3,7 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34701.34
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Memory", "src/Memory.csproj", "{8380EF7C-6F0D-488A-9B88-409696E4565F}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Memory.Logic", "Memory.Logic\Memory.Logic.csproj", "{2490BF43-EFD6-4BE0-B231-860EB3508360}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Memory.Gui", "Memory.Gui\Memory.Gui.csproj", "{6E520079-0F1A-434A-82F8-56D3D5B57645}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Memory.Cmd", "Memory.Cmd\Memory.Cmd.csproj", "{36DBAAC0-3FEC-4C5C-8330-C1BD2D08BD05}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,10 +15,18 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {8380EF7C-6F0D-488A-9B88-409696E4565F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {8380EF7C-6F0D-488A-9B88-409696E4565F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {8380EF7C-6F0D-488A-9B88-409696E4565F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {8380EF7C-6F0D-488A-9B88-409696E4565F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2490BF43-EFD6-4BE0-B231-860EB3508360}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2490BF43-EFD6-4BE0-B231-860EB3508360}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2490BF43-EFD6-4BE0-B231-860EB3508360}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2490BF43-EFD6-4BE0-B231-860EB3508360}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6E520079-0F1A-434A-82F8-56D3D5B57645}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6E520079-0F1A-434A-82F8-56D3D5B57645}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6E520079-0F1A-434A-82F8-56D3D5B57645}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6E520079-0F1A-434A-82F8-56D3D5B57645}.Release|Any CPU.Build.0 = Release|Any CPU
+ {36DBAAC0-3FEC-4C5C-8330-C1BD2D08BD05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {36DBAAC0-3FEC-4C5C-8330-C1BD2D08BD05}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {36DBAAC0-3FEC-4C5C-8330-C1BD2D08BD05}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {36DBAAC0-3FEC-4C5C-8330-C1BD2D08BD05}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Program.cs b/src/Program.cs
deleted file mode 100644
index 4c17aa1..0000000
--- a/src/Program.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Windows;
-
-namespace Memory
-{
- internal partial class Program
- {
- [STAThread]
- public static void Main()
- {
- Application app = new();
- MainWindow mainWindow = new();
- app.Run(mainWindow);
- }
- }
-}
\ No newline at end of file