Add comments
This commit is contained in:
@ -6,6 +6,7 @@ namespace Memory.Cmd
|
|||||||
{
|
{
|
||||||
private readonly Game game = game;
|
private readonly Game game = game;
|
||||||
|
|
||||||
|
// Add 0 padding to numbers so they have the same width
|
||||||
private string FormatNumber(int number)
|
private string FormatNumber(int number)
|
||||||
{
|
{
|
||||||
string num = "";
|
string num = "";
|
||||||
@ -20,11 +21,14 @@ namespace Memory.Cmd
|
|||||||
|
|
||||||
private void DrawCard(Card card, int index, int column, int row)
|
private void DrawCard(Card card, int index, int column, int row)
|
||||||
{
|
{
|
||||||
|
// Format both the card index and the card number
|
||||||
string num = FormatNumber(card.ID);
|
string num = FormatNumber(card.ID);
|
||||||
string cardNr = FormatNumber(index);
|
string cardNr = FormatNumber(index);
|
||||||
int cardWidth = game.DeckSize.ToString().Length + 4;
|
int cardWidth = game.DeckSize.ToString().Length + 4;
|
||||||
|
// Double for loop for drawing characters both vertically and horizontally
|
||||||
for (int i = 0; i < game.GridSize; i++)
|
for (int i = 0; i < game.GridSize; i++)
|
||||||
{
|
{
|
||||||
|
// Set the cursor position so cards don't overlap
|
||||||
Console.CursorLeft += (cardWidth + 1) * column;
|
Console.CursorLeft += (cardWidth + 1) * column;
|
||||||
Console.CursorTop = i + (game.GridSize + 1) * row;
|
Console.CursorTop = i + (game.GridSize + 1) * row;
|
||||||
for (int j = 0; j < cardWidth; j++)
|
for (int j = 0; j < cardWidth; j++)
|
||||||
@ -50,6 +54,7 @@ namespace Memory.Cmd
|
|||||||
}
|
}
|
||||||
else if (i == game.GridSize / 2 && j > 1 && j < cardWidth - 2)
|
else if (i == game.GridSize / 2 && j > 1 && j < cardWidth - 2)
|
||||||
{
|
{
|
||||||
|
// Write the card number if it is selected otherwise hide it with star symbols
|
||||||
if (card.Selected())
|
if (card.Selected())
|
||||||
{
|
{
|
||||||
Console.Write(num[j - 2]);
|
Console.Write(num[j - 2]);
|
||||||
@ -71,11 +76,13 @@ namespace Memory.Cmd
|
|||||||
public void Redraw()
|
public void Redraw()
|
||||||
{
|
{
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
|
// Loop over all cards to draw them individually
|
||||||
for (int i = 0; i < game.Cards.Count; i++)
|
for (int i = 0; i < game.Cards.Count; i++)
|
||||||
{
|
{
|
||||||
Card card = game.Cards[i];
|
Card card = game.Cards[i];
|
||||||
if (!card.Completed)
|
if (!card.Completed)
|
||||||
{
|
{
|
||||||
|
// Set the color of the card based on if it's selected or not
|
||||||
if (card.Selected())
|
if (card.Selected())
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
@ -92,6 +99,7 @@ namespace Memory.Cmd
|
|||||||
|
|
||||||
public void WriteScores()
|
public void WriteScores()
|
||||||
{
|
{
|
||||||
|
// Print the players score to the console then loop over highscores to print those aswell
|
||||||
Console.WriteLine($"Your score: {game.Scoring.Points}\nTop 10 Highscores:");
|
Console.WriteLine($"Your score: {game.Scoring.Points}\nTop 10 Highscores:");
|
||||||
List<Score> highscores = game.ScoreHandler.GetTopScores();
|
List<Score> highscores = game.ScoreHandler.GetTopScores();
|
||||||
for (int i = 0; i < highscores.Count; i++)
|
for (int i = 0; i < highscores.Count; i++)
|
||||||
@ -101,6 +109,7 @@ namespace Memory.Cmd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ask for the player's name with checks if the name is valid
|
||||||
public static string GetPlayerName()
|
public static string GetPlayerName()
|
||||||
{
|
{
|
||||||
Console.Write("Enter your name: ");
|
Console.Write("Enter your name: ");
|
||||||
@ -113,6 +122,7 @@ namespace Memory.Cmd
|
|||||||
return name!;
|
return name!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ask if the player wants to play again
|
||||||
public static bool ShouldReplay()
|
public static bool ShouldReplay()
|
||||||
{
|
{
|
||||||
Console.Write("Game Finished. Do you want to play again? (Y/N): ");
|
Console.Write("Game Finished. Do you want to play again? (Y/N): ");
|
||||||
|
@ -12,6 +12,7 @@ namespace Memory.Cmd
|
|||||||
{
|
{
|
||||||
Game game = new(new ScoreHandler(), name, 10);
|
Game game = new(new ScoreHandler(), name, 10);
|
||||||
CmdGame cmdGame = new(game);
|
CmdGame cmdGame = new(game);
|
||||||
|
// While the game isn't finished ask for a card index then attempt to click the card
|
||||||
while (!game.IsFinished())
|
while (!game.IsFinished())
|
||||||
{
|
{
|
||||||
cmdGame.Redraw();
|
cmdGame.Redraw();
|
||||||
@ -24,6 +25,7 @@ namespace Memory.Cmd
|
|||||||
}
|
}
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
cmdGame.WriteScores();
|
cmdGame.WriteScores();
|
||||||
|
// Ask if the player wants to play again, if not break out of the loop and the program is finished
|
||||||
if (!CmdGame.ShouldReplay())
|
if (!CmdGame.ShouldReplay())
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -7,12 +7,24 @@ namespace Memory.Data
|
|||||||
{
|
{
|
||||||
public const string URI = "Data Source=Scores.db;Version=3;";
|
public const string URI = "Data Source=Scores.db;Version=3;";
|
||||||
|
|
||||||
private bool IsTop10(int points)
|
// Ensure the database and table exist upon ScoreHandler creation
|
||||||
|
public ScoreHandler()
|
||||||
|
{
|
||||||
|
using SQLiteConnection connection = new(URI);
|
||||||
|
connection.Open();
|
||||||
|
using SQLiteCommand command = new("CREATE TABLE IF NOT EXISTS Scores(ID INTEGER PRIMARY KEY, Name TEXT, Points INTEGER)", connection);
|
||||||
|
command.ExecuteNonQuery();
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the score is higher than 10th place
|
||||||
|
private static bool IsTop10(int points)
|
||||||
{
|
{
|
||||||
using SQLiteConnection connection = new(URI);
|
using SQLiteConnection connection = new(URI);
|
||||||
connection.Open();
|
connection.Open();
|
||||||
using SQLiteCommand command = new("SELECT Points FROM Scores ORDER BY Points DESC LIMIT 1 OFFSET 9", connection);
|
using SQLiteCommand command = new("SELECT Points FROM Scores ORDER BY Points DESC LIMIT 1 OFFSET 9", connection);
|
||||||
using SQLiteDataReader reader = command.ExecuteReader();
|
using SQLiteDataReader reader = command.ExecuteReader();
|
||||||
|
// If there aren't atleast 10 highscores, return true by default
|
||||||
if (!reader.Read())
|
if (!reader.Read())
|
||||||
{
|
{
|
||||||
connection.Close();
|
connection.Close();
|
||||||
@ -23,15 +35,7 @@ namespace Memory.Data
|
|||||||
return points > lowest;
|
return points > lowest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScoreHandler()
|
// Get the top 10 highscores
|
||||||
{
|
|
||||||
using SQLiteConnection connection = new(URI);
|
|
||||||
connection.Open();
|
|
||||||
using SQLiteCommand command = new("CREATE TABLE IF NOT EXISTS Scores(ID INTEGER PRIMARY KEY, Name TEXT, Points INTEGER)", connection);
|
|
||||||
command.ExecuteNonQuery();
|
|
||||||
connection.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Score> GetTopScores()
|
public List<Score> GetTopScores()
|
||||||
{
|
{
|
||||||
List<Score> scores = [];
|
List<Score> scores = [];
|
||||||
@ -47,6 +51,7 @@ namespace Memory.Data
|
|||||||
return scores;
|
return scores;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write the new score to the database
|
||||||
public bool WriteScore(Score score)
|
public bool WriteScore(Score score)
|
||||||
{
|
{
|
||||||
if (IsTop10(score.Points))
|
if (IsTop10(score.Points))
|
||||||
|
@ -19,6 +19,7 @@ namespace Memory.Gui
|
|||||||
private Game? game;
|
private Game? game;
|
||||||
private int _deckSize = 5;
|
private int _deckSize = 5;
|
||||||
|
|
||||||
|
// Property with propertychanged listener to update it in the ui
|
||||||
public int DeckSize { get => _deckSize; set
|
public int DeckSize { get => _deckSize; set
|
||||||
{
|
{
|
||||||
_deckSize = value;
|
_deckSize = value;
|
||||||
@ -36,6 +37,7 @@ namespace Memory.Gui
|
|||||||
|
|
||||||
private void StartGame(object sender, RoutedEventArgs args)
|
private void StartGame(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
|
// Check if the name is valid, otherwise display error
|
||||||
string name = Name.Text;
|
string name = Name.Text;
|
||||||
if (name.Length > 32 || name.Length < 2)
|
if (name.Length > 32 || name.Length < 2)
|
||||||
{
|
{
|
||||||
@ -43,6 +45,7 @@ namespace Memory.Gui
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Hide startscreen and show gamescreen and create a grid and draw the cards
|
||||||
game = new(new ScoreHandler(), name, DeckSize);
|
game = new(new ScoreHandler(), name, DeckSize);
|
||||||
ErrorLabel.Visibility = Visibility.Hidden;
|
ErrorLabel.Visibility = Visibility.Hidden;
|
||||||
StartScreen.Visibility = Visibility.Hidden;
|
StartScreen.Visibility = Visibility.Hidden;
|
||||||
@ -53,10 +56,12 @@ namespace Memory.Gui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Callback functions for changing the size of the deck
|
||||||
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
private void Decrease(object sender, RoutedEventArgs args) => DeckSize = Math.Max(DeckSize - 1, 2);
|
private void Decrease(object sender, RoutedEventArgs args) => DeckSize = Math.Max(DeckSize - 1, 2);
|
||||||
private void Increase(object sender, RoutedEventArgs args) => DeckSize = Math.Min(DeckSize + 1, 10);
|
private void Increase(object sender, RoutedEventArgs args) => DeckSize = Math.Min(DeckSize + 1, 10);
|
||||||
|
|
||||||
|
// Draw the highscores
|
||||||
private void DrawScores()
|
private void DrawScores()
|
||||||
{
|
{
|
||||||
Highscores.Children.Clear();
|
Highscores.Children.Clear();
|
||||||
@ -77,6 +82,7 @@ namespace Memory.Gui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable the finish screen with scores
|
||||||
private void FinishGame()
|
private void FinishGame()
|
||||||
{
|
{
|
||||||
DrawScores();
|
DrawScores();
|
||||||
@ -84,6 +90,7 @@ namespace Memory.Gui
|
|||||||
FinishScreen.Visibility = Visibility.Visible;
|
FinishScreen.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw grid
|
||||||
private void CreateGrid()
|
private void CreateGrid()
|
||||||
{
|
{
|
||||||
Cards.ColumnDefinitions.Clear();
|
Cards.ColumnDefinitions.Clear();
|
||||||
@ -121,11 +128,13 @@ namespace Memory.Gui
|
|||||||
{
|
{
|
||||||
Cards.Children.Clear();
|
Cards.Children.Clear();
|
||||||
Deck grid = Game.GetGridSize(DeckSize);
|
Deck grid = Game.GetGridSize(DeckSize);
|
||||||
|
// Loop over cards to draw them
|
||||||
for (int i = 0; i < game!.Cards.Count; i++)
|
for (int i = 0; i < game!.Cards.Count; i++)
|
||||||
{
|
{
|
||||||
Card card = game.Cards[i];
|
Card card = game.Cards[i];
|
||||||
if (!card.Completed)
|
if (!card.Completed)
|
||||||
{
|
{
|
||||||
|
// Draw card with image if card isn't completed
|
||||||
Image image = new()
|
Image image = new()
|
||||||
{
|
{
|
||||||
Source = new BitmapImage(new($"pack://application:,,,/images/{card.ID}.png")),
|
Source = new BitmapImage(new($"pack://application:,,,/images/{card.ID}.png")),
|
||||||
@ -138,11 +147,12 @@ namespace Memory.Gui
|
|||||||
Background = new SolidColorBrush(card.Selected() ? Color.FromRgb(0, 255, 0) : Color.FromRgb(255, 0, 0)),
|
Background = new SolidColorBrush(card.Selected() ? Color.FromRgb(0, 255, 0) : Color.FromRgb(255, 0, 0)),
|
||||||
Padding = new Thickness(0)
|
Padding = new Thickness(0)
|
||||||
};
|
};
|
||||||
|
// Set the card in the correct grid position
|
||||||
Grid.SetColumn(button, i % grid.Columns);
|
Grid.SetColumn(button, i % grid.Columns);
|
||||||
Grid.SetRow(button, i / grid.Columns);
|
Grid.SetRow(button, i / grid.Columns);
|
||||||
button.Click += (object sender, RoutedEventArgs args) =>
|
button.Click += (object sender, RoutedEventArgs args) =>
|
||||||
{
|
{
|
||||||
|
// Onclick check if game is finished
|
||||||
game.ClickCard(card);
|
game.ClickCard(card);
|
||||||
if (!game.IsFinished())
|
if (!game.IsFinished())
|
||||||
{
|
{
|
||||||
|
@ -15,11 +15,13 @@
|
|||||||
public int Attempts { get; set; } = 0;
|
public int Attempts { get; set; } = 0;
|
||||||
public Score Scoring { get; } = new(player, 0);
|
public Score Scoring { get; } = new(player, 0);
|
||||||
|
|
||||||
|
// Formula to calculate score
|
||||||
public void CalculateScore(long endTime)
|
public void CalculateScore(long endTime)
|
||||||
{
|
{
|
||||||
Scoring.Points = (int)(Math.Pow(DeckSize * 2, 2) / ((endTime - StartTime) / 1000.0 * Attempts) * 1000.0);
|
Scoring.Points = (int)(Math.Pow(DeckSize * 2, 2) / ((endTime - StartTime) / 1000.0 * Attempts) * 1000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the optimal grid size for the current amount of cards
|
||||||
public static Deck GetGridSize(int deckSize)
|
public static Deck GetGridSize(int deckSize)
|
||||||
{
|
{
|
||||||
for (int i = (int)Math.Sqrt(deckSize * 2); i > 0; i--)
|
for (int i = (int)Math.Sqrt(deckSize * 2); i > 0; i--)
|
||||||
@ -32,6 +34,7 @@
|
|||||||
return new(1, deckSize * 2);
|
return new(1, deckSize * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a random set of cards
|
||||||
public static List<Card> CreateDeck(int pairs)
|
public static List<Card> CreateDeck(int pairs)
|
||||||
{
|
{
|
||||||
List<Card> cards = [];
|
List<Card> cards = [];
|
||||||
@ -65,6 +68,7 @@
|
|||||||
Card? choice2 = GetChoice2();
|
Card? choice2 = GetChoice2();
|
||||||
if (!card.Completed)
|
if (!card.Completed)
|
||||||
{
|
{
|
||||||
|
// Set the card to choice1 or choice2 depending on the context
|
||||||
if ((choice1 == null && choice2 == null) || (choice1 != null && choice2 != null))
|
if ((choice1 == null && choice2 == null) || (choice1 != null && choice2 != null))
|
||||||
{
|
{
|
||||||
if (choice1 != null)
|
if (choice1 != null)
|
||||||
@ -83,6 +87,7 @@
|
|||||||
Attempts++;
|
Attempts++;
|
||||||
if (choice1.Matches(card))
|
if (choice1.Matches(card))
|
||||||
{
|
{
|
||||||
|
// If card matches, mark as complete and check if the game is finished
|
||||||
choice1.Completed = true;
|
choice1.Completed = true;
|
||||||
card.Completed = true;
|
card.Completed = true;
|
||||||
if (IsFinished())
|
if (IsFinished())
|
||||||
|
Reference in New Issue
Block a user