Compare commits

..

40 Commits

Author SHA1 Message Date
Rémi LAVERGNE a03ccb76e9 Ajout de la vidéo
continuous-integration/drone/push Build is passing Details
continuous-integration/drone Build is passing Details
11 months ago
Rémi LAVERGNE 4ea6ec094b Merge pull request 'v0.9 - Application MAUI' (#112) from dev into master
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
11 months ago
Rémi LAVERGNE bc26c9184d Mise à jour du README
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE 6509cbcdd1 Bug de Rules.cs
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/pr Build is failing Details
11 months ago
Rémi LAVERGNE e414771027 Bug de Rules.cs
continuous-integration/drone/push Build is failing Details
11 months ago
Rémi LAVERGNE aab53a614e Bug de Rules.cs
continuous-integration/drone/push Build is failing Details
11 months ago
Rémi LAVERGNE a5ea118e4a Bug de Rules.cs
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE cd2c35c481 Code Smells de Map.cs
continuous-integration/drone/push Build is passing Details
11 months ago
Remi NEVEU 170e5c5a66 Suppression d'un code smell
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE 5a597d8323 Code Smells de Player.cs
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE e113ee2ac6 Code Smells de Rules.cs
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE 0d3c541c4b Code Smells de Rules.cs
continuous-integration/drone/push Build is failing Details
11 months ago
Rémi LAVERGNE 8b54be4818 Code Smells de Rules.cs
continuous-integration/drone/push Build is failing Details
11 months ago
Rémi LAVERGNE 66cf3c37b2 Actualisation de LastPlayed
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE 9d6b2af796 🛠️ Encore plus de tests
11 months ago
Remi NEVEU c11ccba67d Merge branch 'dev' of https://codefirst.iut.uca.fr/git/remi.lavergne/Trek-12 into dev
continuous-integration/drone/push Build is passing Details
11 months ago
Remi NEVEU 68d29bc5a5 Suppression de code commenter et fonction EveryAdjacentCells mit nullable pour faire baisser les codes smells
11 months ago
Remi NEVEU 3104b66a39 Changement de la méthode AddToRopePath en enlever le second paramètre, qui était inutilisé
11 months ago
Rémi LAVERGNE b98b2172ce Merge SQLite into dev (#111)
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE d8962f4cb1 Suppression de deux tests qui ne servaient plus
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE 60c8f76e01 Merge branch 'dev' of codefirst.iut.uca.fr:remi.lavergne/Trek-12 into dev
continuous-integration/drone/push Build is failing Details
11 months ago
Rémi LAVERGNE 103fd02652 ⚙️ Correction de bugs dans le jeu
11 months ago
Remi NEVEU c95295575e Ajout d'un test et suppression de quelques codes smells
continuous-integration/drone/push Build is passing Details
11 months ago
Remi NEVEU 7fe5289475 Ajout de quelques tests
continuous-integration/drone/push Build is passing Details
11 months ago
Remi NEVEU c562f9cbb5 suppression d'une mauvaise modification
continuous-integration/drone/push Build is passing Details
11 months ago
Remi NEVEU 38a9c8a8e7 Correction de tous les tests et fusion de ce qu'a fait Lucas
continuous-integration/drone/push Build is passing Details
11 months ago
Remi NEVEU 37d57b37fb première correction des tests mais je vais tout recommencer à mon git pull
11 months ago
Rémi LAVERGNE 62ff6c130f Merge PageBoard into dev (#110)
continuous-integration/drone/push Build is failing Details
11 months ago
Rémi LAVERGNE 3fbe28accf Quelques modification pour continuer une partie non terminée
continuous-integration/drone/push Build is failing Details
11 months ago
Rémi LAVERGNE 1f723b64f1 🚧 Correction de bugs et modification de la solution pour publication
continuous-integration/drone/push Build is failing Details
11 months ago
Lucas DUFLOT a9f4a82a5e Un debut de jeu, mais encore des problemes...
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/pr Build is failing Details
11 months ago
Rémi LAVERGNE d63bc44634 Merge pull request 'ConsoleApp' (#109) from ConsoleApp into dev
continuous-integration/drone/push Build is failing Details
11 months ago
Rémi LAVERGNE 70c4b9c3b2 Correction de tests
continuous-integration/drone/push Build is failing Details
11 months ago
Lucas DUFLOT 2685063b5e rien change
continuous-integration/drone/push Build was killed Details
continuous-integration/drone/pr Build was killed Details
11 months ago
Rémi LAVERGNE cfa4a18b93 Mise à jour de 'README.md'
continuous-integration/drone/push Build is passing Details
11 months ago
Lucas DUFLOT 2595ac686f ✔ Chemins de corde
continuous-integration/drone/push Build was killed Details
11 months ago
Rémi LAVERGNE 6d791f4737 Ajout de la LICENCE
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE 9fef1b7fff Supprimer 'LICENSE'
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE 1323dcc53f Ajout de la licence sur le dépôt
continuous-integration/drone/push Build is passing Details
11 months ago
Rémi LAVERGNE e4e14adf45 v0.8 - Application Console
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
11 months ago

@ -0,0 +1,15 @@
**© 2024 - Tous droits réservés.**
Les éléments de conception et de documentation regroupent:
- Les diagrammes
- Les éléments de design
- Tout écrit réalisé dans le cadre de l'application et présent sur ce même [wiki](https://codefirst.iut.uca.fr/git/remi.lavergne/Trek-12/wiki).
Le terme "code" tel que définit constitue tout ou partie de texte permettant la formation, le fonctionnement et le lancement de l'application et présent dans le [dépôt CodeFirst](https://codefirst.iut.uca.fr/git/remi.lavergne/Trek-12).
Tous les éléments de conception et de documentation, ainsi que le code dans son intégralité sont la propriété des utilisateurs enregistrés sous les comptes CodeFirst/Gitea suivants: @remi.lavergne, @remi.neveu & @lucas.duflot.
Le jeu de société du nom "Trek 12" ainsi que tous ses logos associés sont la propriété de [🪓 LUMBERJACKS [Studio]](https://lumberjacks-studio.com/fr/trek12/)
**Utilisation et distribution :** Toute reproduction, distribution, ou utilisation non autorisée des éléments protégés est strictement interdite sans l'autorisation écrite préalable des propriétaires respectifs. Les utilisateurs peuvent demander des autorisations spécifiques en contactant les propriétaires via leurs comptes mentionnés.
**Avis de non-responsabilité :** Ce copyright ne s'étend pas aux éléments tiers utilisés sous licence. Toutes les marques commerciales et logos appartiennent à leurs propriétaires respectifs. Les propriétaires des comptes mentionnés ne sauraient être tenus responsables de l'utilisation abusive des éléments protégés par des tiers.

@ -1,4 +1,4 @@
![Static Badge](https://img.shields.io/badge/Trek12-En_Production-red) ![Static Badge](https://img.shields.io/badge/Trek12-Disponible_au_public-yellow)
<details> <details>
<summary>Sonarcube Ratings</summary> <summary>Sonarcube Ratings</summary>
@ -27,4 +27,29 @@ Auteurs:
<br> <br>
> ### **📕 Toute la documentation est présente sur le [Wiki](https://codefirst.iut.uca.fr/git/remi.lavergne/Trek-12/wiki) !** > ### **📼 Vidéo de présentation sur [Opencast](https://opencast.dsi.uca.fr/paella/ui/watch.html?id=b08a0497-0fc3-420f-a98d-5f5a2b226252).**
> ### **📕 Toute la conception et le fonctionnement est présent sur le [Wiki](https://codefirst.iut.uca.fr/git/remi.lavergne/Trek-12/wiki) !**
> ### **📄 Documentation du code sur [CodeDoc](https://codefirst.iut.uca.fr/documentation/remi.lavergne/Trek-12/doxygen/index.html).**
<br>
*Persistance locale en XML ou JSON disponible. La persistance en SQLite est créée mais nécessite encore du développement pour fonctionner.*<br/>
*Pour changer de mode de persistance, se rendre dans le fichier App.xaml.cs*
<br><br>
## 📦 Générer un exécutable
Pour générer un exécutable, il suffit de lancer la commande suivante dans le terminal :
```bash
# Pour un exécutable MSIX (Windows Store):
dotnet publish -f net8.0-windows10.0.19041.0 -p:WindowsPackageType=MSIX
# Ou pour un exécutable "classique":
dotnet publish -c Release -r win-x64 --self-contained
```
<br>
***Avant de fork le projet ou autre, merci de lire attentivement la [LICENCE](LICENSE.md)***

@ -1,414 +1,416 @@
// See https://aka.ms/new-console-template for more information // See https://aka.ms/new-console-template for more information
using Models; using Models;
using Models.Events; using Models.Events;
using Models.Game; using Models.Game;
using Models.Interfaces; using Models.Interfaces;
using DataContractPersistence; using DataContractPersistence;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace ConsoleApp; namespace ConsoleApp;
class Program class Program
{ {
static Game Game { get; set; } static Game Game { get; set; }
/// <summary> /// <summary>
/// Main function of the console app /// Main function of the console app
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
static void Main(string[] args) static void Main(string[] args)
{ {
Console.WriteLine("Enter your pseudo:"); Console.WriteLine("Enter your pseudo:");
string? pseudo = Console.ReadLine(); string? pseudo = Console.ReadLine();
if (pseudo != null) if (pseudo != null)
{ {
IPersistence persistence = new DataContractXml(); IPersistence persistence = new DataContractXml();
Player player = new Player(pseudo, "test.png"); Player player = new Player(pseudo, "test.png");
Map map = new Map("Dunai","background"); Map map = new Map("Dunai","background");
Game = new Game(persistence); Game = new Game(persistence);
// Abonnement aux événements // Abonnement aux événements
Game.GameStarted += OnGameStarted!; Game.GameStarted += OnGameStarted!;
Game.GameEnded += OnGameEnded!; Game.GameEnded += OnGameEnded!;
Game.BoardUpdated += OnBoardUpdated!; Game.BoardUpdated += OnBoardUpdated!;
Game.DiceRolled += OnDiceRolled!; Game.DiceRolled += OnDiceRolled!;
Game.OperationChosen += OnOperationChosen!; Game.OperationChosen += OnOperationChosen!;
Game.CellChosen += OnCellChosen!; Game.CellChosen += OnCellChosen!;
Game.PlayerChooseOp += OnPlayerSelectionOp!; Game.PlayerChooseOp += OnPlayerSelectionOp!;
Game.PlayerOption += OnPlayerOption!; Game.PlayerOption += OnPlayerOption!;
Game.PlayerChooseCell += OnPlayerSelectionCell!; Game.PlayerChooseCell += OnPlayerSelectionCell!;
// Initialisation // Initialisation
Game.InitializeGame(map, player); Game.InitializeGame(map, player);
} Game.GameLoop();
}
}
}
static void OnPlayerSelectionCell(Object sender, PlayerChooseCellEventArgs e)
{ static void OnPlayerSelectionCell(Object sender, PlayerChooseCellEventArgs e)
int row, column; {
while (true) int row, column;
{ while (true)
Console.ForegroundColor = ConsoleColor.Cyan; {
Console.WriteLine("Enter the position of the cell you want to play"); Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Enter the row number (0-6)"); Console.WriteLine("Enter the position of the cell you want to play");
Console.ResetColor(); Console.WriteLine("Enter the row number (0-6)");
if (!int.TryParse(Console.ReadLine(), out row) || row < 0 || row >= 7) Console.ResetColor();
{ if (!int.TryParse(Console.ReadLine(), out row) || row < 0 || row >= 7)
Console.ForegroundColor= ConsoleColor.Red; {
Console.WriteLine("Invalid row number. Please enter a number between 0 and 6."); Console.ForegroundColor= ConsoleColor.Red;
Console.ResetColor(); Console.WriteLine("Invalid row number. Please enter a number between 0 and 6.");
continue; Console.ResetColor();
} continue;
Console.ForegroundColor = ConsoleColor.Cyan; }
Console.WriteLine("Enter the column number (0-6)"); Console.ForegroundColor = ConsoleColor.Cyan;
Console.ResetColor(); Console.WriteLine("Enter the column number (0-6)");
if (!int.TryParse(Console.ReadLine(), out column) || column < 0 || column >= 7) Console.ResetColor();
{ if (!int.TryParse(Console.ReadLine(), out column) || column < 0 || column >= 7)
Console.ForegroundColor = ConsoleColor.Red; {
Console.WriteLine("Invalid column number. Please enter a number between 0 and 6."); Console.ForegroundColor = ConsoleColor.Red;
Console.ResetColor(); Console.WriteLine("Invalid column number. Please enter a number between 0 and 6.");
continue; Console.ResetColor();
} continue;
}
Game.PlayerCell = new Cell(row, column);
break; Game.PlayerCell = new Cell(row, column);
} break;
} }
}
static void OnPlayerOption(object sender, PlayerOptionEventArgs e)
{ static void OnPlayerOption(object sender, PlayerOptionEventArgs e)
Console.WriteLine(); {
if(e.Turn != 1) Console.WriteLine();
{ if (e.Turn != 1)
IEnumerable<Cell> PlayedCellsQuery = {
IEnumerable<Cell> PlayedCellsQuery =
from cell in e.Board from cell in e.Board
where cell.Valid == true where cell.Valid == true
where cell.Value != null where cell.Value != null
select cell; select cell;
foreach (var item in e.Board) foreach (var item in e.Board)
{ {
if (item.X == 6) if (item.X == 6)
Console.WriteLine(); Console.WriteLine();
if (!item.Valid) if (!item.Valid)
Console.Write(" "); Console.Write(" ");
else if (item.Value != null) else if (item.Value != null)
Console.Write($"{item.Value}"); Console.Write($"{item.Value}");
else else
{ {
foreach (var item1 in PlayedCellsQuery) foreach (var item1 in PlayedCellsQuery)
{ {
if (Math.Abs(item.X - item1.X) <= 1 && Math.Abs(item.Y - item1.Y) <= 1) if (Math.Abs(item.X - item1.X) <= 1 && Math.Abs(item.Y - item1.Y) <= 1)
{ {
Console.ForegroundColor = ConsoleColor.Cyan; Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write($"{e.Resultat}"); Console.Write($"{e.Resultat}");
Console.ResetColor(); Console.ResetColor();
} }
}
} }
} }
return; }
} return;
foreach (var item in e.Board) }
{ foreach (var item in e.Board)
if (!item.Valid) {
Console.Write(" "); if (!item.Valid)
else Console.Write(" ");
{ else
Console.ForegroundColor = ConsoleColor.Cyan; {
Console.Write($"{e.Resultat}"); Console.ForegroundColor = ConsoleColor.Cyan;
Console.ResetColor(); Console.Write($"{e.Resultat}");
Console.ResetColor();
}
if (item.X == 6) }
Console.WriteLine(); if (item.X == 6)
} Console.WriteLine();
Console.WriteLine(); }
Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine();
Console.WriteLine("Choose an Available cell."); Console.ForegroundColor = ConsoleColor.Cyan;
Console.ResetColor(); Console.WriteLine("Choose an Available cell.");
} Console.ResetColor();
}
static void OnPlayerSelectionOp(object sender, PlayerChooseOperationEventArgs e)
{ static void OnPlayerSelectionOp(object sender, PlayerChooseOperationEventArgs e)
Console.WriteLine(); {
DisplayOperationTable(((Game)sender).UsedMap.OperationGrid.ToList()); Console.WriteLine();
Console.WriteLine(); DisplayOperationTable(((Game)sender).UsedMap.OperationGrid.ToList());
Console.WriteLine("0. Lower | 1. Higher | 2. Substraction | 3. Addition | 4. Multiplication"); Console.WriteLine();
string? op = Console.ReadLine(); Console.WriteLine("0. Lower | 1. Higher | 2. Substraction | 3. Addition | 4. Multiplication");
while (op != "0" && op != "1" && op != "2" && op != "3" && op != "4") string? op = Console.ReadLine();
{ while (op != "0" && op != "1" && op != "2" && op != "3" && op != "4")
Console.ForegroundColor = ConsoleColor.Red; {
Console.WriteLine("Invalid operation. Please choose again."); Console.ForegroundColor = ConsoleColor.Red;
Console.ResetColor(); Console.WriteLine("Invalid operation. Please choose again.");
op = Console.ReadLine(); Console.ResetColor();
} op = Console.ReadLine();
int test = Convert.ToInt32(op); }
Game.PlayerOperation = (Operation)test; int test = Convert.ToInt32(op);
Game.PlayerOperation = (Operation)test;
}
}
/// <summary>
/// Handles the event when the game has started. /// <summary>
/// </summary> /// Handles the event when the game has started.
/// <param name="sender"></param> /// </summary>
/// <param name="e"></param> /// <param name="sender"></param>
static void OnGameStarted(object sender, GameStartedEventArgs e) /// <param name="e"></param>
{ static void OnGameStarted(object sender, GameStartedEventArgs e)
Console.WriteLine($"The game has started! Player: {e.CurrentPlayer.Pseudo}"); {
} Console.WriteLine($"The game has started! Player: {e.CurrentPlayer.Pseudo}");
}
/// <summary>
/// Handles the event when the game has ended. /// <summary>
/// </summary> /// Handles the event when the game has ended.
/// <param name="sender"></param> /// </summary>
/// <param name="e"></param> /// <param name="sender"></param>
static void OnGameEnded(object sender, GameEndedEventArgs e) /// <param name="e"></param>
{ static void OnGameEnded(object sender, GameEndedEventArgs e)
Console.WriteLine($"The game has ended! Player: {e.CurrentPlayer.Pseudo}"); {
Console.WriteLine($"Points: {e.Point}"); Console.WriteLine($"The game has ended! Player: {e.CurrentPlayer.Pseudo}");
} Console.WriteLine($"Points: {e.Point}");
}
/// <summary>
/// Handles the event when the board is updated. /// <summary>
/// </summary> /// Handles the event when the board is updated.
/// <param name="sender"></param> /// </summary>
/// <param name="e"></param> /// <param name="sender"></param>
static void OnBoardUpdated(object sender, BoardsUpdateEventArgs e) /// <param name="e"></param>
{ static void OnBoardUpdated(object sender, BoardsUpdateEventArgs e)
foreach (var item in e.Boards) {
{ foreach (var item in e.Boards)
if (!item.Valid) {
Console.Write(" "); if (!item.Valid)
else if (item.Value != null) Console.Write(" ");
Console.Write($"{item.Value}"); else if (item.Value != null)
else Console.Write("O"); Console.Write($"{item.Value}");
if (item.X == 6) else Console.Write("O");
Console.WriteLine(); if (item.X == 6)
} Console.WriteLine();
} }
}
/// <summary>
/// Handles the event when the dice are rolled. /// <summary>
/// </summary> /// Handles the event when the dice are rolled.
/// <param name="sender"></param> /// </summary>
/// <param name="e"></param> /// <param name="sender"></param>
static void OnDiceRolled(object sender, DiceRolledEventArgs e) /// <param name="e"></param>
{ static void OnDiceRolled(object sender, DiceRolledEventArgs e)
// Console.Clear(); {
Console.WriteLine($"Dice 1: {e.Dice1Value} | Dice 2: {e.Dice2Value}"); // Console.Clear();
Console.WriteLine(); Console.WriteLine($"Dice 1: {e.Dice1Value} | Dice 2: {e.Dice2Value}");
Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine();
Console.WriteLine("Choose an operation."); Console.ForegroundColor = ConsoleColor.Cyan;
Console.ResetColor(); Console.WriteLine("Choose an operation.");
} Console.ResetColor();
}
/// <summary>
/// Handles the event when an operation is chosen by the player. /// <summary>
/// </summary> /// Handles the event when an operation is chosen by the player.
/// <param name="sender"></param> /// </summary>
/// <param name="e"></param> /// <param name="sender"></param>
static void OnOperationChosen(object sender, OperationChosenEventArgs e) /// <param name="e"></param>
{ static void OnOperationChosen(object sender, OperationChosenEventArgs e)
Console.WriteLine($"Operation: {e.Operation}, Result: {e.Result}"); {
DisplayOperationTable(((Game)sender).UsedMap.OperationGrid.ToList()); Console.WriteLine($"Operation: {e.Operation}, Result: {e.Result}");
Cell playerChoice = GetPlayerChoice(); DisplayOperationTable(((Game)sender).UsedMap.OperationGrid.ToList());
bool test = ((Game)sender).HandlePlayerChoice(playerChoice, e.Result); Cell playerChoice = GetPlayerChoice();
if(!test) bool test = ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
{ if(!test)
Console.WriteLine("Invalid cell. Please choose again."); {
Console.WriteLine(); Console.WriteLine("Invalid cell. Please choose again.");
Console.WriteLine(); Console.WriteLine();
DisplayBoard(((Game)sender).UsedMap); Console.WriteLine();
OnOperationChosen(sender, e); DisplayBoard(((Game)sender).UsedMap);
} OnOperationChosen(sender, e);
}
/*
try /*
{ try
((Game)sender).HandlePlayerChoice(playerChoice, e.Result); {
} ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
catch (InvalidCellCoordinatesException err) }
{ catch (InvalidCellCoordinatesException err)
Console.WriteLine(err.Message); {
playerChoice = GetPlayerChoice(); Console.WriteLine(err.Message);
((Game)sender).HandlePlayerChoice(playerChoice, e.Result); playerChoice = GetPlayerChoice();
} ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
catch (InvalidCellException err) }
{ catch (InvalidCellException err)
Console.WriteLine(err.Message); {
playerChoice = GetPlayerChoice(); Console.WriteLine(err.Message);
((Game)sender).HandlePlayerChoice(playerChoice, e.Result); playerChoice = GetPlayerChoice();
} ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
catch (InvalidPlaceResultException err) }
{ catch (InvalidPlaceResultException err)
Console.WriteLine(err.Message); {
playerChoice = GetPlayerChoice(); Console.WriteLine(err.Message);
((Game)sender).HandlePlayerChoice(playerChoice, e.Result); playerChoice = GetPlayerChoice();
} ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
*/ }
} */
}
/// <summary>
/// Handles the event when a cell is chosen by the player. /// <summary>
/// </summary> /// Handles the event when a cell is chosen by the player.
/// <param name="sender"></param> /// </summary>
/// <param name="e"></param> /// <param name="sender"></param>
static void OnCellChosen(object sender, CellChosenEventArgs e) /// <param name="e"></param>
{ static void OnCellChosen(object sender, CellChosenEventArgs e)
Console.WriteLine($"Cell chosen: ({e.Cell.X}, {e.Cell.Y}) with result: {e.Result}"); {
DisplayBoard(((Game)sender).UsedMap); Console.WriteLine($"Cell chosen: ({e.Cell.X}, {e.Cell.Y}) with result: {e.Result}");
} DisplayBoard(((Game)sender).UsedMap);
}
/// <summary>
/// Displays the game board. /// <summary>
/// </summary> /// Displays the game board.
/// <param name="map">Used map to display</param> /// </summary>
static void DisplayBoard(Map map) /// <param name="map">Used map to display</param>
{ static void DisplayBoard(Map map)
int cpt = 0; {
for (int i = 0; i < map.Boards.Count; i++) int cpt = 0;
{ for (int i = 0; i < map.Boards.Count; i++)
if (cpt % 6 == 0) {
{ if (cpt % 6 == 0)
Console.Write("| "); {
} Console.Write("| ");
}
if (map.Boards[i].Value.HasValue)
{ if (map.Boards[i].Value.HasValue)
Console.Write(map.Boards[i].Value?.ToString().PadLeft(2)); {
} Console.Write(map.Boards[i].Value?.ToString().PadLeft(2));
else }
{ else
Console.Write(" O"); {
} Console.Write(" O");
}
cpt++;
if (cpt % 6 == 0) cpt++;
{ if (cpt % 6 == 0)
Console.Write(" |"); {
Console.WriteLine(); Console.Write(" |");
} Console.WriteLine();
} }
} }
}
/// <summary>
/// Displays the operation table. /// <summary>
/// </summary> /// Displays the operation table.
/// <param name="operationTable">The operation table to display.</param> /// </summary>
static void DisplayOperationTable(List<OperationCell> operationTable) /// <param name="operationTable">The operation table to display.</param>
{ static void DisplayOperationTable(List<OperationCell> operationTable)
Console.ForegroundColor = ConsoleColor.Yellow; {
foreach ( var cell in operationTable) Console.ForegroundColor = ConsoleColor.Yellow;
{ foreach ( var cell in operationTable)
{
if (cell.X == 0 && cell.Y == 0)
Console.Write("Lower => "); if (cell.X == 0 && cell.Y == 0)
if (cell.X == 0 && cell.Y == 1) Console.Write("Lower => ");
Console.Write("Higher => "); if (cell.X == 0 && cell.Y == 1)
if (cell.X == 0 && cell.Y == 2) Console.Write("Higher => ");
Console.Write("Substraction => "); if (cell.X == 0 && cell.Y == 2)
if (cell.X == 0 && cell.Y == 3) Console.Write("Substraction => ");
Console.Write("Addition => "); if (cell.X == 0 && cell.Y == 3)
if (cell.X == 0 && cell.Y == 4) Console.Write("Addition => ");
Console.Write("Multiplication => "); if (cell.X == 0 && cell.Y == 4)
if (cell.IsChecked) Console.Write("Multiplication => ");
Console.Write("X | "); if (cell.IsChecked)
if (!cell.IsChecked) Console.Write("X | ");
Console.Write(" | "); if (!cell.IsChecked)
if (cell.X == 3) Console.Write(" | ");
Console.WriteLine(); if (cell.X == 3)
} Console.WriteLine();
Console.ResetColor(); }
} Console.ResetColor();
}
/// <summary>
/// Gets the cell chosen by the player. /// <summary>
/// </summary> /// Gets the cell chosen by the player.
/// <returns>The cell chosen by the player.</returns> /// </summary>
static Cell GetPlayerChoice() /// <returns>The cell chosen by the player.</returns>
{ static Cell GetPlayerChoice()
int row, column; {
while (true) int row, column;
{ while (true)
Console.WriteLine("Enter the position of the cell you want to play"); {
Console.WriteLine("Enter the row number (0-5)"); Console.WriteLine("Enter the position of the cell you want to play");
if (!int.TryParse(Console.ReadLine(), out row) || row < 0 || row >= 6) Console.WriteLine("Enter the row number (0-5)");
{ if (!int.TryParse(Console.ReadLine(), out row) || row < 0 || row >= 6)
Console.WriteLine("Invalid row number. Please enter a number between 0 and 5."); {
continue; Console.WriteLine("Invalid row number. Please enter a number between 0 and 5.");
} continue;
}
Console.WriteLine("Enter the column number (0-5)");
if (!int.TryParse(Console.ReadLine(), out column) || column < 0 || column >= 6) Console.WriteLine("Enter the column number (0-5)");
{ if (!int.TryParse(Console.ReadLine(), out column) || column < 0 || column >= 6)
Console.WriteLine("Invalid column number. Please enter a number between 0 and 5."); {
continue; Console.WriteLine("Invalid column number. Please enter a number between 0 and 5.");
} continue;
}
return new Cell(row, column);
} return new Cell(row, column);
} }
}
/// <summary>
/// Gets the operation chosen by the player. /// <summary>
/// </summary> /// Gets the operation chosen by the player.
/// <returns></returns> /// </summary>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <returns></returns>
static Operation GetPlayerOperation(object? sender) /// <exception cref="ArgumentOutOfRangeException"></exception>
{ static Operation GetPlayerOperation(object? sender)
DisplayOperationOptions(); {
string? op = Console.ReadLine(); DisplayOperationOptions();
while (op != "1" && op != "2" && op != "3" && op != "4" && op != "5") string? op = Console.ReadLine();
{ while (op != "1" && op != "2" && op != "3" && op != "4" && op != "5")
Console.WriteLine("Invalid operation. Please choose again."); {
op = Console.ReadLine(); Console.WriteLine("Invalid operation. Please choose again.");
} op = Console.ReadLine();
int test = Convert.ToInt32(op); }
int test = Convert.ToInt32(op);
while(((Game)sender).UsedMap.CheckOperationPossible(test-1))
{ while(((Game)sender).UsedMap.CheckOperationPossible(test-1))
Console.WriteLine("Invalid operation. Please choose again."); {
Console.WriteLine(); Console.WriteLine("Invalid operation. Please choose again.");
op = Console.ReadLine(); Console.WriteLine();
while (op != "1" && op != "2" && op != "3" && op != "4" && op != "5") op = Console.ReadLine();
{ while (op != "1" && op != "2" && op != "3" && op != "4" && op != "5")
Console.WriteLine("Invalid operation. Please choose again."); {
op = Console.ReadLine(); Console.WriteLine("Invalid operation. Please choose again.");
} op = Console.ReadLine();
test = Convert.ToInt32(op); }
} test = Convert.ToInt32(op);
}
return op switch
{ return op switch
"1" => Operation.ADDITION, {
"2" => Operation.SUBTRACTION, "1" => Operation.ADDITION,
"3" => Operation.MULTIPLICATION, "2" => Operation.SUBTRACTION,
"4" => Operation.LOWER, "3" => Operation.MULTIPLICATION,
"5" => Operation.HIGHER, "4" => Operation.LOWER,
_ => throw new ArgumentOutOfRangeException() "5" => Operation.HIGHER,
}; _ => throw new ArgumentOutOfRangeException()
} };
}
/// <summary>
/// Displays the operation options for the player to choose from. /// <summary>
/// </summary> /// Displays the operation options for the player to choose from.
static void DisplayOperationOptions() /// </summary>
{ static void DisplayOperationOptions()
Console.WriteLine("Choose an operation:"); {
Console.WriteLine("1: Addition (+)"); Console.WriteLine("Choose an operation:");
Console.WriteLine("2: Subtraction (-)"); Console.WriteLine("1: Addition (+)");
Console.WriteLine("3: Multiplication (*)"); Console.WriteLine("2: Subtraction (-)");
Console.WriteLine("4: Lower Dice (less)"); Console.WriteLine("3: Multiplication (*)");
Console.WriteLine("5: Higher Dice (high)"); Console.WriteLine("4: Lower Dice (less)");
} Console.WriteLine("5: Higher Dice (high)");
}
} }

@ -1,4 +1,6 @@
using System.Runtime.Serialization; using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace Models.Game namespace Models.Game
{ {
@ -6,7 +8,7 @@ namespace Models.Game
/// The Cell class represents a cell in the application. /// The Cell class represents a cell in the application.
/// </summary> /// </summary>
[DataContract] [DataContract]
public class Cell : Position, IEquatable<Cell> public class Cell : Position, IEquatable<Cell>, INotifyPropertyChanged
{ {
/// <summary> /// <summary>
/// The value of the cell. /// The value of the cell.
@ -22,6 +24,8 @@ namespace Models.Game
throw new Exception("La valeur doit être supérieure à 0"); throw new Exception("La valeur doit être supérieure à 0");
} }
this._value = value; this._value = value;
OnPropertyChanged();
} }
} }
@ -76,5 +80,13 @@ namespace Models.Game
if (this.X == other.X && this.Y == other.Y) return true; if (this.X == other.X && this.Y == other.Y) return true;
return false; return false;
} }
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
} }
} }

@ -24,6 +24,8 @@ namespace Models.Game
[DataContract, SQLite.Table("Games")] [DataContract, SQLite.Table("Games")]
public class Game : INotifyPropertyChanged public class Game : INotifyPropertyChanged
{ {
public bool IsPreviousGameNotFinished { get; private set; }
[PrimaryKey, AutoIncrement] [PrimaryKey, AutoIncrement]
public int Id { get; set; } public int Id { get; set; }
@ -110,13 +112,34 @@ namespace Models.Game
public Dice Dice2 { get; private set; } public Dice Dice2 { get; private set; }
[DataMember] [DataMember]
public int Turn { get; private set; } public int Turn { get; set; }
[Ignore] [Ignore]
public Operation PlayerOperation { get; set; } public Operation PlayerOperation { get; set; }
private Cell _playerCell;
[Ignore] [Ignore]
public Cell PlayerCell { get; set; } public Cell PlayerCell {
get => _playerCell;
set
{
_playerCell = value;
OnPropertyChanged(nameof(PlayerCell));
}
}
private int _resultat;
public int Resultat {
get => _resultat;
set
{
_resultat = value;
OnPropertyChanged(nameof(Resultat));
}
}
public bool DiceRolledFlag { get; private set; }
public bool OperationChosenFlag { get; private set; }
[Ignore] [Ignore]
public Rules.Rules GameRules { get; } public Rules.Rules GameRules { get; }
@ -149,25 +172,45 @@ namespace Models.Game
Maps.Add(map); Maps.Add(map);
} }
/// <summary>
/// Adds a new best score to the list of best scores. Or updates it if it already exists.
/// </summary>
/// <param name="finalScore">The final score of the game.</param>
public void AddBestScore(int finalScore) public void AddBestScore(int finalScore)
{ {
BestScore bs = new BestScore(UsedMap.Name, CurrentPlayer, 1, finalScore); BestScore bs = new BestScore(UsedMap.Name, CurrentPlayer, 1, finalScore);
foreach (var score in BestScores) var existingScore = BestScores.FirstOrDefault(score => score.Equals(bs));
{
if (!bs.Equals(score)) continue;
score.IncrGamesPlayed(); if (existingScore != null)
score.UpdateScore(finalScore); {
return; existingScore.IncrGamesPlayed();
existingScore.UpdateScore(finalScore);
}
else
{
BestScores.Add(bs);
} }
BestScores.Add(bs); // Sorting the best scores
BestScores.OrderByDescending(p => p.Score); List<BestScore> sortedScores = BestScores.OrderByDescending(score => score.Score).ToList();
for (int i = 0; i < sortedScores.Count; i++)
{
if (!BestScores[i].Equals(sortedScores[i]))
{
BestScores.Move(BestScores.IndexOf(sortedScores[i]), i);
}
}
} }
/// <summary>
/// Removes a player from the list of players.
/// </summary>
/// <param name="playerName"></param>
/// <returns>True if the player was removed successfully, false otherwise.</returns>
public bool RemovePlayer(string playerName) public bool RemovePlayer(string playerName)
{ {
Player player = Players.FirstOrDefault(p => p.Pseudo == playerName); Player? player = Players.FirstOrDefault(p => p.Pseudo == playerName);
if (player == null) if (player == null)
{ {
return false; return false;
@ -177,6 +220,12 @@ namespace Models.Game
return true; return true;
} }
/// <summary>
/// Modifies the pseudo of a player.
/// </summary>
/// <param name="pseudo"></param>
/// <param name="newpseudo"></param>
/// <returns></returns>
public bool ModifyPlayer(string pseudo, string newpseudo) public bool ModifyPlayer(string pseudo, string newpseudo)
{ {
foreach (var index in Players) foreach (var index in Players)
@ -192,6 +241,10 @@ namespace Models.Game
return false; return false;
} }
/// <summary>
/// Removes a game from the list of games.
/// </summary>
/// <param name="playerName"></param>
public void CheckAndRemoveBestScoresDependencies(string playerName) public void CheckAndRemoveBestScoresDependencies(string playerName)
{ {
List<BestScore> bs = new List<BestScore>(); List<BestScore> bs = new List<BestScore>();
@ -207,7 +260,12 @@ namespace Models.Game
BestScores.Remove(score); BestScores.Remove(score);
} }
} }
/// <summary>
/// Modifies the pseudo of a player in the best scores.
/// </summary>
/// <param name="playerName"></param>
/// <param name="newPlayerName"></param>
public void CheckAndChangeBestScoresDependencies(string playerName, string newPlayerName) public void CheckAndChangeBestScoresDependencies(string playerName, string newPlayerName)
{ {
foreach (var bestScore in BestScores) foreach (var bestScore in BestScores)
@ -227,6 +285,10 @@ namespace Models.Game
} }
foreach (var game in data.Item2) foreach (var game in data.Item2)
{ {
if (game.IsRunning)
{
IsPreviousGameNotFinished = true;
}
Games.Add(game); Games.Add(game);
} }
foreach (var map in data.Item3) foreach (var map in data.Item3)
@ -274,7 +336,11 @@ namespace Models.Game
{ {
Dice1.Roll(); Dice1.Roll();
Dice2.Roll(); Dice2.Roll();
DiceRolledFlag = true;
OperationChosenFlag = false;
DiceRolled?.Invoke(this, new DiceRolledEventArgs(Dice1.Value, Dice2.Value)); DiceRolled?.Invoke(this, new DiceRolledEventArgs(Dice1.Value, Dice2.Value));
OnPropertyChanged(nameof(Dice1));
OnPropertyChanged(nameof(Dice2));
} }
/// <summary> /// <summary>
@ -340,8 +406,19 @@ namespace Models.Game
select cell; select cell;
foreach (var item in ValidCell) foreach (var item in ValidCell)
{ {
if(item.X == playerChoice.X && item.Y == playerChoice.Y) if (item.X == playerChoice.X && item.Y == playerChoice.Y)
{
if (result > 12 || (result > 6 && item.IsDangerous == true))
{
item.SetPenalty();
PlayerCell.SetPenalty();
}
item.Value = result; item.Value = result;
OnPropertyChanged(nameof(UsedMap.Boards));
return;
}
} }
} }
@ -350,35 +427,32 @@ namespace Models.Game
/// </summary> /// </summary>
/// <param name="playerChoice"></param> /// <param name="playerChoice"></param>
/// <param name="adjacentes"></param> /// <param name="adjacentes"></param>
private void AddToRopePath(Cell playerChoice,List<Cell> adjacentes) private void AddToRopePath(Cell playerChoice)
{ {
int index =0;
foreach (var cells in adjacentes.Where(cells => cells.Value - playerChoice.Value == 1 || cells.Value - playerChoice.Value == -1)) if(Turn==1) return;
{ int index = 0;
// Le cas si il n'existe aucun chemin de corde
if (UsedMap.RopePaths.Count == 0)
{
// Creer un nouveau chemin de corde avec la cellule choisi par le joueur et celle adjacente
UsedMap.RopePaths.Add(new List<Cell> {playerChoice, cells});
}
// A modifier dans le cas ou il est possible de fusionner deux chemins de corde
if (GameRules.IsInRopePaths(playerChoice, UsedMap.RopePaths, index)) break;
// Le cas si il existe des chemins de corde IEnumerable<Cell> ValidCell =
from cell in UsedMap.Boards
where cell.Value != null && cell.Valid == true && cell != playerChoice
select cell;
// Est-ce que la cellule adjacentes fait parti d'un chemin de corde foreach (var item in ValidCell)
if (!GameRules.IsInRopePaths(cells,UsedMap.RopePaths,index)) {
{ if (!GameRules.IsCellAdjacent(playerChoice, item))
UsedMap.RopePaths.Add(new List<Cell> { playerChoice, cells }); continue;
if (!((playerChoice.Value - item.Value) == 1 || (playerChoice.Value - item.Value) == -1))
continue; continue;
if (!GameRules.IsInRopePaths(item,UsedMap.RopePaths,index))
{
UsedMap.RopePaths.Add(new List<Cell> { playerChoice, item });
return;
} }
if (!GameRules.AsValue(playerChoice, UsedMap.RopePaths, index))
if (!GameRules.AsValue(playerChoice,UsedMap.RopePaths,index))
{ {
UsedMap.RopePaths[index].Add(playerChoice); UsedMap.RopePaths[index].Add(playerChoice);
return;
} }
} }
} }
@ -388,16 +462,30 @@ namespace Models.Game
/// </summary> /// </summary>
public void InitializeGame(Map map, Player player, bool startImmediately = true) public void InitializeGame(Map map, Player player, bool startImmediately = true)
{ {
var runningGames = Games.Where(g => g.IsRunning).ToList();
foreach (var game in runningGames)
{
Games.Remove(game);
}
OnPropertyChanged(nameof(Games));
UsedMap = map; UsedMap = map;
CurrentPlayer = player; CurrentPlayer = player;
Turn = 1; Turn = 1;
Dice1 = new Dice(); Dice1 = new Dice();
Dice2 = new Dice(1); Dice2 = new Dice(1);
IsPreviousGameNotFinished = false;
OnPropertyChanged(nameof(UsedMap));
OnPropertyChanged(nameof(CurrentPlayer));
OnPropertyChanged(nameof(Turn));
if (startImmediately) if (startImmediately)
{ {
StartGame(); StartGame();
} }
SaveData();
} }
/// <summary> /// <summary>
@ -407,7 +495,8 @@ namespace Models.Game
{ {
IsRunning = true; IsRunning = true;
GameStarted?.Invoke(this, new GameStartedEventArgs(CurrentPlayer)); GameStarted?.Invoke(this, new GameStartedEventArgs(CurrentPlayer));
GameLoop();
SaveData();
} }
/// <summary> /// <summary>
@ -422,19 +511,15 @@ namespace Models.Game
/// <summary> /// <summary>
/// The main game loop that runs while the game is active. /// The main game loop that runs while the game is active.
/// </summary> /// </summary>
private void GameLoop() public void GameLoop()
{ {
int res = 0,turn = 1;
Cell cell;
while (IsRunning) while (IsRunning)
{ {
RollAllDice(); RollAllDice();
res = PlayerChooseOperation(); Resultat = PlayerChooseOperation();
PlayerOption?.Invoke(this,new PlayerOptionEventArgs(UsedMap.Boards.ToList(),res,turn));
PlayerSelectionCell(); PlayerSelectionCell();
PlaceResult(PlayerCell,res);
BoardUpdated?.Invoke(this, new BoardsUpdateEventArgs(UsedMap.Boards.ToList())); BoardUpdated?.Invoke(this, new BoardsUpdateEventArgs(UsedMap.Boards.ToList()));
turn++; Turn++;
} }
} }
@ -445,6 +530,8 @@ namespace Models.Game
{ {
PlayerChooseOp?.Invoke(this, new PlayerChooseOperationEventArgs(PlayerOperation)); PlayerChooseOp?.Invoke(this, new PlayerChooseOperationEventArgs(PlayerOperation));
} }
PlayerOption?.Invoke(this, new PlayerOptionEventArgs(UsedMap.Boards.ToList(), ResultOperation(PlayerOperation), Turn));
OperationChosenFlag = true;
return ResultOperation(PlayerOperation); return ResultOperation(PlayerOperation);
} }
@ -456,6 +543,9 @@ namespace Models.Game
PlayerChooseCell?.Invoke(this, new PlayerChooseCellEventArgs(PlayerCell)); PlayerChooseCell?.Invoke(this, new PlayerChooseCellEventArgs(PlayerCell));
} }
MarkOperationAsChecked(PlayerOperation); MarkOperationAsChecked(PlayerOperation);
PlaceResult(PlayerCell, Resultat);
DiceRolledFlag = false;
OperationChosenFlag = false;
} }
/// <summary> /// <summary>
@ -465,6 +555,7 @@ namespace Models.Game
public void HandlePlayerOperation(Operation operation) public void HandlePlayerOperation(Operation operation)
{ {
int result = ResultOperation(operation); int result = ResultOperation(operation);
OperationChosenFlag = true;
OperationChosen?.Invoke(this, new OperationChosenEventArgs(operation, result)); OperationChosen?.Invoke(this, new OperationChosenEventArgs(operation, result));
} }
@ -480,26 +571,17 @@ namespace Models.Game
if (cell.X < 0 || cell.X >= UsedMap.Boards.Count / 6 || cell.Y < 0 || cell.Y >= 6) if (cell.X < 0 || cell.X >= UsedMap.Boards.Count / 6 || cell.Y < 0 || cell.Y >= 6)
{ {
return false; return false;
//throw new InvalidCellCoordinatesException("Invalid cell coordinates. Please choose again.");
} }
if (!GameRules.IsCellValid(cell, UsedMap.Boards.ToList())) if (!GameRules.IsCellValid(cell, UsedMap.Boards.ToList()))
{ {
return false; return false;
//throw new InvalidCellException("Cell is not valid. Please choose again.");
} }
bool res = true;
if (!res)
{
return false;
//throw new InvalidPlaceResultException("Cell is not valid for place result. Please choose again.");
}
GameRules.IsZoneValidAndAddToZones(cell, UsedMap); GameRules.IsZoneValidAndAddToZones(cell, UsedMap);
AddToRopePath(cell, GameRules.EveryAdjacentCells(cell, UsedMap.Boards.ToList())); AddToRopePath(cell);
CellChosen?.Invoke(this, new CellChosenEventArgs(cell, result)); CellChosen?.Invoke(this, new CellChosenEventArgs(cell, result));
return true; return true;
//BoardUpdated?.Invoke(this, EventArgs.Empty);
} }
/// <summary> /// <summary>
@ -522,7 +604,7 @@ namespace Models.Game
foreach (var cells in Boards) foreach (var cells in Boards)
if (cells.Penalty) if (cells.Penalty)
{ {
if (cells.Valid == false || cells.Value == null) if (!cells.Valid || cells.Value == null)
continue; continue;
result += 3; result += 3;
} }
@ -533,7 +615,7 @@ namespace Models.Game
{ {
foreach (var cells in Boards) foreach (var cells in Boards)
{ {
if (cells == null || cells.Value == null || cells.Valid == false) if (cells == null || cells.Value == null || !cells.Valid)
continue; continue;
if (!UsedMap.IsCellInZones(cells) && !UsedMap.IsCellInRopePath(cells)) if (!UsedMap.IsCellInZones(cells) && !UsedMap.IsCellInRopePath(cells))
cells.SetPenalty(); cells.SetPenalty();
@ -547,7 +629,7 @@ namespace Models.Game
{ {
points += GameRules.ScoreRopePaths(UsedMap.RopePaths[i]); points += GameRules.ScoreRopePaths(UsedMap.RopePaths[i]);
} }
points += CalculusOfPenalty(UsedMap.Boards); points -= CalculusOfPenalty(UsedMap.Boards);
return points ?? 0; return points ?? 0;
} }

@ -23,7 +23,8 @@ namespace Models.Game
[DataMember] [DataMember]
[Ignore] [Ignore]
public ReadOnlyObservableCollection<Cell> Boards { get; private set; } public ReadOnlyObservableCollection<Cell> Boards { get; private set; }
ObservableCollection<Cell> board = new ObservableCollection<Cell>();
private readonly ObservableCollection<Cell> _board = new ObservableCollection<Cell>();
/// <summary> /// <summary>
/// It is the backgrond image of the map /// It is the backgrond image of the map
@ -36,7 +37,8 @@ namespace Models.Game
/// </summary> /// </summary>
[DataMember] [DataMember]
public ReadOnlyObservableCollection<OperationCell> OperationGrid { get; private set; } public ReadOnlyObservableCollection<OperationCell> OperationGrid { get; private set; }
ObservableCollection<OperationCell> operationGrid = new ObservableCollection<OperationCell>();
private readonly ObservableCollection<OperationCell> _operationGrid = new ObservableCollection<OperationCell>();
/// <summary> /// <summary>
/// It is a list of a list containing user's rope paths in the current game /// It is a list of a list containing user's rope paths in the current game
@ -53,24 +55,35 @@ namespace Models.Game
/// <summary> /// <summary>
/// Initializes a new instance of the Map class. /// Initializes a new instance of the Map class.
/// </summary> /// </summary>
/// <param name="name"></param>
/// <param name="background">The background of the map.</param> /// <param name="background">The background of the map.</param>
public Map(string name, string background) public Map(string name, string background)
{ {
Name = name; Name = name;
Background = background; Background = background;
Boards = new ReadOnlyObservableCollection<Cell>(board); Boards = new ReadOnlyObservableCollection<Cell>(_board);
InitializeBoards(board); InitializeBoards(_board);
OperationGrid = new ReadOnlyObservableCollection<OperationCell>(operationGrid); OperationGrid = new ReadOnlyObservableCollection<OperationCell>(_operationGrid);
InitializeOperationGrid(operationGrid); InitializeOperationGrid(_operationGrid);
RopePaths = new List<List<Cell>>(); RopePaths = new List<List<Cell>>();
Zones = new List<List<Cell>>(); Zones = new List<List<Cell>>();
} }
/// <summary> /// <summary>
/// SQLite constructor /// SQLite constructor
/// </summary> /// </summary>
public Map() { } public Map() { }
/// <summary>
/// Clone the map to avoid reference problems.
/// </summary>
/// <returns></returns>
public Map Clone()
{
Map map = new Map(Name, Background);
return map;
}
/// <summary> /// <summary>
/// Initializes the boards of the map. /// Initializes the boards of the map.
/// </summary> /// </summary>
@ -128,26 +141,12 @@ namespace Models.Game
public bool IsCellInZones(Cell cell) public bool IsCellInZones(Cell cell)
{ {
foreach (var zone in Zones) return Zones.Any(zone => zone.Contains(cell));
{
if (zone.Contains(cell))
{
return true;
}
}
return false;
} }
public bool IsCellInRopePath(Cell cell) public bool IsCellInRopePath(Cell cell)
{ {
foreach (var path in RopePaths) return RopePaths.Any(path => path.Contains(cell));
{
if (path.Contains(cell))
{
return true;
}
}
return false;
} }
} }
} }

@ -22,7 +22,7 @@ namespace Models.Game
if (isChecked == value) if (isChecked == value)
return; return;
isChecked = value; isChecked = value;
OnPropertyChanged("IsChecked"); OnPropertyChanged(nameof(IsChecked));
} }
} }

@ -15,9 +15,9 @@ namespace Models.Game
[DataContract, SQLite.Table("Players")] [DataContract, SQLite.Table("Players")]
public class Player : INotifyPropertyChanged public class Player : INotifyPropertyChanged
{ {
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = null) void OnPropertyChanged([CallerMemberName] string? propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
@ -63,9 +63,6 @@ namespace Models.Game
/// <param name="profilePicture">The profile picture of the player.</param> /// <param name="profilePicture">The profile picture of the player.</param>
public Player(string pseudo, string profilePicture) public Player(string pseudo, string profilePicture)
{ {
//char[] trim = { ' ', '\n', '\t' };
//Pseudo = pseudo.Trim();
//Pseudo = Pseudo.TrimEnd(trim);
Pseudo = pseudo; Pseudo = pseudo;
ProfilePicture = profilePicture; ProfilePicture = profilePicture;
CreationDate = DateTime.Now.ToString("dd/MM/yyyy"); CreationDate = DateTime.Now.ToString("dd/MM/yyyy");

@ -25,6 +25,8 @@ namespace Models.Rules
{ {
if (!IsCellEmpty(playerChoicePosition)) return false; if (!IsCellEmpty(playerChoicePosition)) return false;
if (!playerChoicePosition.Valid) return false;
if (EveryAdjacentCells(playerChoicePosition, cells).Count == 1) return false; if (EveryAdjacentCells(playerChoicePosition, cells).Count == 1) return false;
return true; return true;
@ -42,15 +44,13 @@ namespace Models.Rules
} }
public bool IsInRopePaths (Cell adjacente,List<List<Cell>> ropePaths,int index) public bool IsInRopePaths (Cell adjacente,List<List<Cell>> ropePaths, int index)
{ {
foreach (List<Cell> path in ropePaths) foreach (List<Cell> path in ropePaths)
{ {
if (path.Contains(adjacente)) if (!path.Contains(adjacente)) continue;
{ index=ropePaths.IndexOf(path);
index=ropePaths.IndexOf(path); return true;
return true;
}
} }
return false; return false;
} }
@ -70,7 +70,7 @@ namespace Models.Rules
IEnumerable<Cell> PlayedCellsQuery = IEnumerable<Cell> PlayedCellsQuery =
from cell in cells from cell in cells
where cell.Valid == true where cell.Valid
select cell; select cell;
foreach (var cell in PlayedCellsQuery) foreach (var cell in PlayedCellsQuery)
@ -90,7 +90,7 @@ namespace Models.Rules
{ {
if (chosenCell == null ||chosenCell.Value == null) return; if (chosenCell == null ||chosenCell.Value == null) return;
List<Cell> adjacentCells = new List<Cell>(); List<Cell> adjacentCells;
adjacentCells = EveryAdjacentCells(chosenCell, map.Boards.ToList()); adjacentCells = EveryAdjacentCells(chosenCell, map.Boards.ToList());
@ -108,8 +108,6 @@ namespace Models.Rules
} }
} }
} }
return;
} }
public bool IsValueInZones(Cell chosenCell, List<List<Cell>> zones) public bool IsValueInZones(Cell chosenCell, List<List<Cell>> zones)
@ -154,7 +152,6 @@ namespace Models.Rules
return; return;
} }
} }
return;
} }
public void NewZoneIsCreated(Cell firstCell, Cell secondCell, Map map) public void NewZoneIsCreated(Cell firstCell, Cell secondCell, Map map)
@ -166,7 +163,7 @@ namespace Models.Rules
map.Zones.Add(newZone); map.Zones.Add(newZone);
} }
public List<Cell> EveryAdjacentCells(Cell choosenCell, List<Cell> cells) public List<Cell> EveryAdjacentCells(Cell? choosenCell, List<Cell> cells)
{ {
List<Cell> adjacentCells = new List<Cell>(); List<Cell> adjacentCells = new List<Cell>();

@ -69,5 +69,67 @@ namespace Tests
Assert.Equal(15, bestScore.Score); Assert.Equal(15, bestScore.Score);
} }
[Fact]
public void IdGetter_ReturnsCorrectId()
{
var myMap = new Map("Dunai", "Dunai.png");
var myPlayer = new Player("John", "pp.png");
var bestScore = new BestScore(myMap.Name, myPlayer, 5, 10);
bestScore.Id = 1;
Assert.Equal(1, bestScore.Id);
}
[Fact]
public void Equals_WithEqualBestScores_ReturnsTrue()
{
var myMap = new Map("Dunai", "Dunai.png");
var myPlayer = new Player("John", "pp.png");
var bestScore1 = new BestScore(myMap.Name, myPlayer, 5, 10);
var bestScore2 = new BestScore(myMap.Name, myPlayer, 5, 10);
Assert.True(bestScore1.Equals(bestScore2));
}
[Fact]
public void Equals_WithDifferentBestScores_ReturnsFalse()
{
var myMap1 = new Map("Dunai", "Dunai.png");
var myMap2 = new Map("Amazon", "Amazon.png");
var myPlayer = new Player("John", "pp.png");
var bestScore1 = new BestScore(myMap1.Name, myPlayer, 5, 10);
var bestScore2 = new BestScore(myMap2.Name, myPlayer, 5, 10);
Assert.False(bestScore1.Equals(bestScore2));
}
[Fact]
public void GetHashCode_WithEqualBestScores_ReturnsSameHashCode()
{
var myMap = new Map("Dunai", "Dunai.png");
var myPlayer = new Player("John", "pp.png");
var bestScore1 = new BestScore(myMap.Name, myPlayer, 5, 10);
var bestScore2 = new BestScore(myMap.Name, myPlayer, 5, 10);
Assert.Equal(bestScore1.GetHashCode(), bestScore2.GetHashCode());
}
[Fact]
public void GetHashCode_WithDifferentBestScores_ReturnsDifferentHashCodes()
{
var myMap1 = new Map("Dunai", "Dunai.png");
var myMap2 = new Map("Amazon", "Amazon.png");
var myPlayer = new Player("John", "pp.png");
var bestScore1 = new BestScore(myMap1.Name, myPlayer, 5, 10);
var bestScore2 = new BestScore(myMap2.Name, myPlayer, 5, 10);
Assert.NotEqual(bestScore1.GetHashCode(), bestScore2.GetHashCode());
}
} }
} }

@ -135,25 +135,6 @@ public class GameTests
Assert.Equal(player, _game.CurrentPlayer); Assert.Equal(player, _game.CurrentPlayer);
} }
[Fact]
public void InitializeGame_ShouldInitializeGameAndTriggerEventWhenStarted()
{
var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
bool eventTriggered = false;
_game.GameEnded += (sender, args) =>
{
eventTriggered = true;
};
_game.InitializeGame(map, player, true);
Assert.True(eventTriggered);
Assert.False(_game.IsRunning);
Assert.Equal(map, _game.UsedMap);
Assert.Equal(player, _game.CurrentPlayer);
}
[Theory] [Theory]
[InlineData(Operation.ADDITION, 3, 4, 7)] [InlineData(Operation.ADDITION, 3, 4, 7)]
[InlineData(Operation.SUBTRACTION, 6, 4, 2)] [InlineData(Operation.SUBTRACTION, 6, 4, 2)]
@ -191,7 +172,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
Assert.Equal(map, _game.UsedMap); Assert.Equal(map, _game.UsedMap);
} }
@ -202,7 +183,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
Assert.Equal(player, _game.CurrentPlayer); Assert.Equal(player, _game.CurrentPlayer);
} }
@ -213,7 +194,7 @@ public class GameTests
Player player = new Player("test_player", "DefaultProfilePicture"); Player player = new Player("test_player", "DefaultProfilePicture");
Map map = new Map("test_name", "test_background.png"); Map map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
Assert.NotNull(_game.Dice1); Assert.NotNull(_game.Dice1);
Assert.NotNull(_game.Dice2); Assert.NotNull(_game.Dice2);
@ -233,7 +214,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
// Use of reflection to call private method // Use of reflection to call private method
var methodInfo = typeof(Game).GetMethod("MarkOperationAsChecked", BindingFlags.NonPublic | BindingFlags.Instance); var methodInfo = typeof(Game).GetMethod("MarkOperationAsChecked", BindingFlags.NonPublic | BindingFlags.Instance);
@ -266,17 +247,21 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
Assert.NotNull(_game.GameRules); Assert.NotNull(_game.GameRules);
_game.UsedMap.Boards[0].Value = 1; _game.UsedMap.Boards[0].Value = 1;
_game.UsedMap.Boards[1].Value = 2; _game.UsedMap.Boards[1].Value = 2;
_game.UsedMap.Boards[0].Valid = true;
_game.UsedMap.Boards[1].Valid = true;
_game.UsedMap.Boards[2].Valid = true;
var methodInfo = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance); var methodInfo = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo); Assert.NotNull(methodInfo);
var cell = new Cell(0, 2); _game.PlayerCell = new Cell(2, 0);
cell.Value = 3; _game.PlayerCell.Value = 3;
methodInfo.Invoke(_game, new object[] { cell, 3 }); methodInfo.Invoke(_game, new object[] { _game.PlayerCell, 3 });
//_game.UsedMap.Boards[2].Value = _game.PlayerCell.Value;
Assert.Equal(3, _game.UsedMap.Boards[2].Value); Assert.Equal(3, _game.UsedMap.Boards[2].Value);
} }
@ -287,10 +272,13 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
var cell = new Cell(0, 1); var cell = new Cell(1, 0);
cell.Valid = true;
_game.UsedMap.Boards[0].Valid = true;
_game.UsedMap.Boards[0].Value = 1; _game.UsedMap.Boards[0].Value = 1;
_game.UsedMap.Boards[1].Valid = true;
bool result = _game.HandlePlayerChoice(cell, 1); bool result = _game.HandlePlayerChoice(cell, 1);
Assert.True(result); Assert.True(result);
} }
@ -301,7 +289,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
var cell = new Cell(0, 7); var cell = new Cell(0, 7);
cell.Value = 1; cell.Value = 1;
@ -315,7 +303,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
var cell = new Cell(0, 0); var cell = new Cell(0, 0);
cell.Value = 1; cell.Value = 1;
@ -324,25 +312,6 @@ public class GameTests
Assert.False(result); Assert.False(result);
} }
[Fact]
public void ShouldTriggerEventWhenEnded()
{
var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
bool eventTriggered = false;
_game.GameEnded += (sender, args) =>
{
eventTriggered = true;
};
_game.InitializeGame(map, player, true);
Assert.True(eventTriggered);
Assert.False(_game.IsRunning);
Assert.Equal(map, _game.UsedMap);
Assert.Equal(player, _game.CurrentPlayer);
}
[Fact] [Fact]
public void RemovePlayerTest_ShouldRemovePlayer() public void RemovePlayerTest_ShouldRemovePlayer()
{ {
@ -366,15 +335,17 @@ public class GameTests
{ {
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
_game.UsedMap.Boards[1].Valid = true;
_game.UsedMap.Boards[2].Valid = true;
_game.UsedMap.Boards[1].Value = 5; _game.UsedMap.Boards[1].Value = 5;
var methodInfo = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance); var methodInfo = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo); Assert.NotNull(methodInfo);
var cell = new Cell(0, 2); _game.PlayerCell = new Cell(2, 0);
cell.Value = 14; _game.PlayerCell.Value = 14;
methodInfo.Invoke(_game, new object[] { cell, 14 }); methodInfo.Invoke(_game, new object[] { _game.PlayerCell, 14 });
Assert.True(_game.UsedMap.Boards[2].Penalty); Assert.True(_game.UsedMap.Boards[2].Penalty);
} }
@ -384,16 +355,20 @@ public class GameTests
{ {
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
_game.UsedMap.Boards[1].Valid = true;
_game.UsedMap.Boards[2].Valid = true;
_game.UsedMap.Boards[1].Value = 5; _game.UsedMap.Boards[1].Value = 5;
_game.UsedMap.Boards[2].IsDangerous = true; _game.UsedMap.Boards[2].IsDangerous = true;
var methodInfo = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance); var methodInfo = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo); Assert.NotNull(methodInfo);
var cell = new Cell(0, 2); _game.PlayerCell = new Cell(2, 0);
cell.Value = 7; _game.PlayerCell.Value = 7;
methodInfo.Invoke(_game, new object[] { cell, 7 }); methodInfo.Invoke(_game, new object[] { _game.PlayerCell, 7 });
Assert.True(_game.UsedMap.Boards[2].Penalty); Assert.True(_game.UsedMap.Boards[2].Penalty);
} }
@ -403,7 +378,7 @@ public class GameTests
{ {
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
_game.UsedMap.Boards[0].Valid = true; _game.UsedMap.Boards[0].Valid = true;
_game.UsedMap.Boards[3].Valid = true; _game.UsedMap.Boards[3].Valid = true;
@ -431,7 +406,7 @@ public class GameTests
{ {
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
_game.UsedMap.Boards[1].Value = 1; _game.UsedMap.Boards[1].Value = 1;
_game.UsedMap.Boards[2].Value = 2; _game.UsedMap.Boards[2].Value = 2;
@ -443,7 +418,7 @@ public class GameTests
foreach (var cells in _game.UsedMap.Boards.ToList()) foreach (var cells in _game.UsedMap.Boards.ToList())
{ {
methodInfo.Invoke(_game, new object[] { cells, _game.UsedMap.Boards.ToList() }); methodInfo.Invoke(_game, new object[] { cells });
} }
_game.PutPenaltyForLostCells(_game.UsedMap.Boards); _game.PutPenaltyForLostCells(_game.UsedMap.Boards);
@ -453,42 +428,114 @@ public class GameTests
} }
[Fact] [Fact]
public void CalculusOfPenalty_ReallyCalculusPenalty() public void CalculusOfPenalty_ReallyCalculusPenalty_ForZonesAndDangerousCellsAndOverTwelve()
{ {
var player = new Player("test_player", "DefaultProfilePicture"); var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png"); var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); _game.InitializeGame(map, player, false);
var methodInfo = typeof(Game).GetMethod("AddToRopePath", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo);
_game.UsedMap.Boards[0].Valid = true; _game.UsedMap.Boards[7].Valid = true;
_game.UsedMap.Boards[1].Valid = true; _game.UsedMap.Boards[8].Valid = true;
_game.UsedMap.Boards[2].Valid = true; _game.UsedMap.Boards[9].Valid = true;
_game.UsedMap.Boards[3].Valid = true; _game.UsedMap.Boards[10].Valid = true;
_game.UsedMap.Boards[11].Valid = true;
_game.UsedMap.Boards[12].Valid = true;
_game.UsedMap.Boards[10].Value = 2; // 1,3 // penalty
_game.UsedMap.Boards[7].Value = 5; // 1,0
_game.UsedMap.Boards[8].Value = 5; // 1,1
_game.UsedMap.Boards[9].Value = 5; // 1,2
var place = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(place);
_game.PlayerCell = new Cell(4, 1);
_game.PlayerCell.Value = 7;
_game.PlayerCell.Valid = true;
_game.PlayerCell.IsDangerous = true;
place.Invoke(_game, new object[] { _game.PlayerCell, 7 }); //One penalty
_game.PlayerCell = new Cell(5, 1);
_game.PlayerCell.Value = 14;
_game.PlayerCell.Valid = true;
place.Invoke(_game, new object[] { _game.PlayerCell, 14 });
foreach (var cells in _game.UsedMap.Boards.ToList())
{
_game.GameRules.IsZoneValidAndAddToZones(cells, _game.UsedMap);
}
_game.UsedMap.Boards[0].Value = 0;
methodInfo.Invoke(_game, new object[] { _game.UsedMap.Boards[0], _game.GameRules.EveryAdjacentCells(_game.UsedMap.Boards[0], _game.UsedMap.Boards.ToList()) });
_game.UsedMap.Boards[1].Value = 1;
methodInfo.Invoke(_game, new object[] { _game.UsedMap.Boards[1], _game.GameRules.EveryAdjacentCells(_game.UsedMap.Boards[1], _game.UsedMap.Boards.ToList()) });
_game.UsedMap.Boards[2].Value = 2;
methodInfo.Invoke(_game, new object[] { _game.UsedMap.Boards[2], _game.GameRules.EveryAdjacentCells(_game.UsedMap.Boards[2], _game.UsedMap.Boards.ToList()) });
_game.UsedMap.Boards[3].Value = 5;
_game.PutPenaltyForLostCells(_game.UsedMap.Boards); _game.PutPenaltyForLostCells(_game.UsedMap.Boards);
Assert.True(_game.UsedMap.Boards[3].Penalty); Assert.True(_game.UsedMap.Boards[11].Penalty);
Assert.Equal(9, _game.CalculusOfPenalty(_game.UsedMap.Boards));
}
[Fact]
public void CanIModifyAPlayer()
{
Game game = new Game();
Player player = new Player("test", "DefaultProfilePicture");
game.AddPlayer(player);
game.ModifyPlayer("test", "newName");
Assert.Equal("newName", game.Players[0].Pseudo);
}
Assert.Equal(3, _game.CalculusOfPenalty(_game.UsedMap.Boards)); [Fact]
public void CanIModifyANonExistentPlayer()
{
Game game = new Game();
var res = game.ModifyPlayer("nope", "newName");
Assert.False(res);
}
[Fact]
public void CanIRollDice()
{
_game.InitializeGame(new Map("test", "test.png"), new Player("test", "test.png"), false);
_game.RollAllDice();
Assert.NotNull(_game.Dice1);
Assert.NotNull(_game.Dice2);
Assert.True(_game.Dice1.Value >= 0 && _game.Dice1.Value <= 5 );
Assert.True(_game.Dice2.Value >= 1 && _game.Dice2.Value <= 6 );
} }
[Fact] [Fact]
public void CalculusOfPenalty_ReallyCalculusPenalty_ForZonesAndDangerousCellsAndOverTwelve() public void CanIStartGame()
{ {
var player = new Player("test_player", "DefaultProfilePicture"); _game.InitializeGame(new Map("test", "test.png"), new Player("test", "test.png"), false);
var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player); var start = typeof(Game).GetMethod("StartGame", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(start);
start.Invoke(_game, null);
Assert.True(_game.IsRunning);
}
[Fact]
public void CanIEndGame()
{
_game.InitializeGame(new Map("test", "test.png"), new Player("test", "test.png"), false);
var start = typeof(Game).GetMethod("StartGame", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(start);
start.Invoke(_game, null);
var end = typeof(Game).GetMethod("EndGame", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(end);
end.Invoke(_game, new object[] { 14 } );
Assert.False(_game.IsRunning);
}
[Fact]
public void CalculusOfPointsWorksWellOrNot()
{
_game.InitializeGame(new Map("test", "test.png"), new Player("test", "test.png"), false);
_game.UsedMap.Boards[7].Valid = true; _game.UsedMap.Boards[7].Valid = true;
_game.UsedMap.Boards[8].Valid = true; _game.UsedMap.Boards[8].Valid = true;
@ -497,24 +544,20 @@ public class GameTests
_game.UsedMap.Boards[11].Valid = true; _game.UsedMap.Boards[11].Valid = true;
_game.UsedMap.Boards[12].Valid = true; _game.UsedMap.Boards[12].Valid = true;
_game.UsedMap.Boards[10].Value = 2; // 1,3 // penalty _game.UsedMap.Boards[10].Value = 2; // penalty (- 3)
_game.UsedMap.Boards[7].Value = 5; // 1,0 _game.UsedMap.Boards[7].Value = 5; //5 + 2 = 7
_game.UsedMap.Boards[8].Value = 5; // 1,1 _game.UsedMap.Boards[8].Value = 5;
_game.UsedMap.Boards[9].Value = 5; // 1,2 _game.UsedMap.Boards[9].Value = 5;
var place = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance); var place = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(place); Assert.NotNull(place);
var cell = new Cell(1, 4); _game.PlayerCell = new Cell(4, 1);
cell.Value = 7; _game.PlayerCell.Value = 7;
cell.Valid = true; _game.PlayerCell.Valid = true;
cell.IsDangerous = true; _game.PlayerCell.IsDangerous = true;
place.Invoke(_game, new object[] { cell, 7 }); //One penalty place.Invoke(_game, new object[] { _game.PlayerCell, 7 }); //One penalty
var othercell = new Cell(1, 5);
cell.Value = 14;
cell.Valid = true;
place.Invoke(_game, new object[] { othercell, 14 });
foreach (var cells in _game.UsedMap.Boards.ToList()) foreach (var cells in _game.UsedMap.Boards.ToList())
@ -525,7 +568,127 @@ public class GameTests
_game.PutPenaltyForLostCells(_game.UsedMap.Boards); _game.PutPenaltyForLostCells(_game.UsedMap.Boards);
Assert.True(_game.UsedMap.Boards[11].Penalty); Assert.True(_game.UsedMap.Boards[11].Penalty);
Assert.Equal(9, _game.CalculusOfPenalty(_game.UsedMap.Boards));
Assert.Equal(1, _game.FinalCalculusOfPoints());
} }
[Fact]
public void CalculusOfPointsWorksWellOrNotForRopePathes()
{
_game.InitializeGame(new Map("test", "test.png"), new Player("test", "test.png"), false);
var methodInfo = typeof(Game).GetMethod("AddToRopePath", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo);
_game.Turn = 2;
_game.UsedMap.Boards[7].Valid = true;
_game.UsedMap.Boards[8].Valid = true;
_game.UsedMap.Boards[9].Valid = true;
_game.UsedMap.Boards[10].Valid = true;
_game.UsedMap.Boards[7].Value = 5; //7 + 2 = 9
methodInfo.Invoke(_game, new object[] { _game.UsedMap.Boards[7] });
_game.UsedMap.Boards[8].Value = 6;
methodInfo.Invoke(_game, new object[] { _game.UsedMap.Boards[8] });
_game.UsedMap.Boards[9].Value = 7;
methodInfo.Invoke(_game, new object[] { _game.UsedMap.Boards[9] });
_game.UsedMap.Boards[10].Value = 2; // penalty (- 3)
methodInfo.Invoke(_game, new object[] { _game.UsedMap.Boards[10] });
_game.PutPenaltyForLostCells(_game.UsedMap.Boards);
Assert.True(_game.UsedMap.Boards[10].Penalty);
Assert.Equal(6, _game.FinalCalculusOfPoints());
}
[Fact]
public void AddBestScore_AddsNewBestScoreToList()
{
var game = new Game(_mockPersistence.Object);
var player = new Player("John Doe", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
game.InitializeGame(map, player, false);
game.AddBestScore(100);
Assert.Single(game.BestScores);
Assert.Equal(100, game.BestScores[0].Score);
Assert.Equal(player, game.BestScores[0].ThePlayer);
Assert.Equal(map.Name, game.BestScores[0].MapName);
}
[Fact]
public void AddBestScore_UpdatesExistingBestScoreAndIncrementsGamesPlayed()
{
var game = new Game(_mockPersistence.Object);
var player = new Player("John Doe", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
game.InitializeGame(map, player, false);
game.AddBestScore(100);
game.AddBestScore(200);
Assert.Single(game.BestScores);
Assert.Equal(300, game.BestScores[0].Score);
Assert.Equal(2, game.BestScores[0].GamesPlayed);
Assert.Equal(player, game.BestScores[0].ThePlayer);
Assert.Equal(map.Name, game.BestScores[0].MapName);
}
[Fact]
public void AddBestScore_SortsBestScoresCorrectly()
{
var game = new Game(_mockPersistence.Object);
var player1 = new Player("John Doe", "DefaultProfilePicture");
var player2 = new Player("John Does", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
game.InitializeGame(map, player1, false);
game.AddBestScore(100);
game.InitializeGame(map, player2, false);
game.AddBestScore(200);
Assert.Equal(2, game.BestScores.Count);
Assert.Equal(200, game.BestScores[0].Score);
Assert.Equal(player2, game.BestScores[0].ThePlayer);
Assert.Equal(100, game.BestScores[1].Score);
Assert.Equal(player1, game.BestScores[1].ThePlayer);
}
[Fact]
public void CheckAndRemoveBestScoresDependencies_RemovesDependenciesCorrectly()
{
var game = new Game(_mockPersistence.Object);
var player = new Player("John Doe", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
game.InitializeGame(map, player, false);
game.AddBestScore(100);
game.CheckAndRemoveBestScoresDependencies(player.Pseudo);
Assert.DoesNotContain(game.BestScores, bs => bs.ThePlayer.Pseudo == player.Pseudo);
}
[Fact]
public void CheckAndChangeBestScoresDependencies_ChangesDependenciesCorrectly()
{
var game = new Game(_mockPersistence.Object);
var player = new Player("John Doe", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
game.InitializeGame(map, player, false);
game.AddBestScore(100);
game.CheckAndChangeBestScoresDependencies(player.Pseudo, "John Does");
Assert.All(game.BestScores, bs => Assert.NotEqual("John Doe", bs.ThePlayer.Pseudo));
Assert.Contains(game.BestScores, bs => bs.ThePlayer.Pseudo == "John Does");
}
} }

@ -27,7 +27,7 @@ public class MapTests
Assert.Equal(49, map.Boards.Count); Assert.Equal(49, map.Boards.Count);
for (int i = 0; i < 36; i++) for (int i = 0; i < 36; i++)
{ {
Assert.Equal(new Cell(i / 7, i % 7), map.Boards[i]); Assert.Equal(new Cell(i % 7, i / 7), map.Boards[i]);
} }
} }
@ -92,6 +92,17 @@ public class MapTests
var paths = new List<Cell> { cell }; var paths = new List<Cell> { cell };
map.RopePaths.Add(paths); map.RopePaths.Add(paths);
Assert.False(map.IsCellInRopePath(othercell)); Assert.False(map.IsCellInRopePath(othercell));
}
[Fact]
public void Clone_ReturnsNewMap()
{
var map = new Map("test_name", "test_background.png");
var clone = map.Clone();
Assert.NotEqual(map, clone);
Assert.Equal(map.Name, clone.Name);
Assert.Equal(map.Background, clone.Background);
} }
} }

@ -11,6 +11,7 @@ public class PlayerTests
var player = new Player(pseudo, profilePicture); var player = new Player(pseudo, profilePicture);
Assert.Equal(pseudo, player.Pseudo); Assert.Equal(pseudo, player.Pseudo);
Assert.Equal(profilePicture, player.ProfilePicture); Assert.Equal(profilePicture, player.ProfilePicture);
Assert.Null(player.LastPlayed);
} }
[Theory] [Theory]
@ -46,4 +47,15 @@ public class PlayerTests
Player player = new Player("test_pseudo", "DefaultProfilePicture"); Player player = new Player("test_pseudo", "DefaultProfilePicture");
Assert.False(player.Equals(new Cell(0, 0))); Assert.False(player.Equals(new Cell(0, 0)));
} }
[Fact]
public void UpdateLastPlayed_UpdatesLastPlayedDate()
{
var player = new Player("John Doe", "DefaultProfilePicture");
player.UpdateLastPlayed();
Assert.NotNull(player.LastPlayed);
Assert.Equal(DateTime.Now.ToString("dd/MM/yyyy"), player.LastPlayed);
}
} }

@ -44,6 +44,7 @@ public class RulesTests
{ {
Rules rules = new Rules(); Rules rules = new Rules();
Map map = new Map("test", "background"); Map map = new Map("test", "background");
map.Boards[0].Valid = true;
Cell selectedCell = map.Boards[0]; Cell selectedCell = map.Boards[0];
Assert.True(rules.IsCellValid(selectedCell, map.Boards.ToList())); Assert.True(rules.IsCellValid(selectedCell, map.Boards.ToList()));
} }
@ -179,6 +180,7 @@ public class RulesTests
Cell cell1 = new Cell(0, 0); Cell cell1 = new Cell(0, 0);
Cell cell2 = new Cell(0, 1); Cell cell2 = new Cell(0, 1);
cell2.Value = 12; cell2.Value = 12;
cell2.Valid = true;
List<Cell> cells = new List<Cell> { cell2 }; List<Cell> cells = new List<Cell> { cell2 };
Assert.True(rules.NearCellIsValid(cell1, cells)); Assert.True(rules.NearCellIsValid(cell1, cells));
} }

@ -5,15 +5,15 @@ VisualStudioVersion = 17.8.34408.163
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trek-12", "Trek-12\Trek-12.csproj", "{41EE7BF8-DDE6-4B00-9434-076589C0B419}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trek-12", "Trek-12\Trek-12.csproj", "{41EE7BF8-DDE6-4B00-9434-076589C0B419}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models", "Models\Models.csproj", "{807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Models", "Models\Models.csproj", "{807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp", "ConsoleApp\ConsoleApp.csproj", "{795F2C88-3C43-4795-9764-E52F7330888D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp", "ConsoleApp\ConsoleApp.csproj", "{795F2C88-3C43-4795-9764-E52F7330888D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{383C4215-C680-4C2E-BC7E-B62F0B164370}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{383C4215-C680-4C2E-BC7E-B62F0B164370}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataContractPersistence", "DataContractPersistence\DataContractPersistence.csproj", "{FC6A23C3-A1E3-4BF4-85B0-404D8574E190}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataContractPersistence", "DataContractPersistence\DataContractPersistence.csproj", "{FC6A23C3-A1E3-4BF4-85B0-404D8574E190}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stub", "Stub\Stub.csproj", "{49360F7D-C59D-4B4F-AF5A-73FF61D9EF9B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stub", "Stub\Stub.csproj", "{49360F7D-C59D-4B4F-AF5A-73FF61D9EF9B}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

@ -40,9 +40,9 @@ namespace Trek_12
/* Add the permanent maps if they are not already in the game */ /* Add the permanent maps if they are not already in the game */
if (Manager.Maps.Count == 0) if (Manager.Maps.Count == 0)
{ {
Manager.AddMap(new Map("Dunai","profile.jpg")); Manager.AddMap(new Map("Dunai","montagne2.png"));
Manager.AddMap(new Map("Kagkot","montagne1.png")); Manager.AddMap(new Map("Kagkot", "montagne3.png"));
Manager.AddMap(new Map("Dhaulagiri","tmp1.jpeg")); Manager.AddMap(new Map("Dhaulagiri", "montagne4.png"));
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 972 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks> <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks> <!--<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>-->
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET --> <!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> --> <!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
@ -38,6 +38,14 @@
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsOSPlatform('windows'))">
<TargetFrameworks>$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<WindowsPackageType>MSIX</WindowsPackageType>
<PackageCertificateThumbprint>404032fa5d4dc4c8bbf036505d2409963f355ebd</PackageCertificateThumbprint>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<!-- App Icon --> <!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\app_icon.png" /> <MauiIcon Include="Resources\AppIcon\app_icon.png" />
@ -47,7 +55,6 @@
<!-- Images --> <!-- Images -->
<MauiImage Include="Resources\Images\*" /> <MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
<!-- Custom Fonts --> <!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" /> <MauiFont Include="Resources\Fonts\*" />
@ -61,6 +68,9 @@
<None Remove="Resources\Images\back_arrow.png" /> <None Remove="Resources\Images\back_arrow.png" />
<None Remove="Resources\Images\checked.png" /> <None Remove="Resources\Images\checked.png" />
<None Remove="Resources\Images\maptest.png" /> <None Remove="Resources\Images\maptest.png" />
<None Remove="Resources\Images\montagne2.png" />
<None Remove="Resources\Images\montagne3.png" />
<None Remove="Resources\Images\montagne4.png" />
<None Remove="Resources\Images\user.png" /> <None Remove="Resources\Images\user.png" />
</ItemGroup> </ItemGroup>

@ -6,52 +6,70 @@
BackgroundColor="Bisque"> BackgroundColor="Bisque">
<Grid RowDefinitions="*,auto" ColumnDefinitions="auto,*,auto"> <Grid RowDefinitions="*,auto" ColumnDefinitions="auto,*,auto">
<HorizontalStackLayout> <Grid RowDefinitions="auto,auto"
<Frame BorderColor="DarkGray" Grid.Column="0"
HorizontalOptions="Center"
VerticalOptions="Center"
Margin="50,0,0,0">
<HorizontalStackLayout HorizontalOptions="Center"
Margin="0,20,0,0">
<Frame BorderColor="DarkGray"
HeightRequest="50" HeightRequest="50"
WidthRequest="50" WidthRequest="50"
Grid.Column="0" Grid.Column="0"
HorizontalOptions="Center" HorizontalOptions="Center"
VerticalOptions="Center" VerticalOptions="Center"
Padding="0"> Padding="0"
<Label Text="{Binding Dice1.Value}" BackgroundColor="Yellow"
FontSize="16" IsVisible="Hidden"
x:Name="YellowDice">
<Label Text="{Binding Dice1.Value}"
FontSize="Large"
VerticalOptions="Center" VerticalOptions="Center"
HorizontalOptions="Center" HorizontalOptions="Center"
TextColor="Black" TextColor="Black"
x:Name="Dice1"/> x:Name="Dice1"
</Frame> FontAttributes="Bold"/>
<Frame BorderColor="DarkGray" </Frame>
<Frame BorderColor="DarkGray"
HeightRequest="50" HeightRequest="50"
WidthRequest="50" WidthRequest="50"
Grid.Column="0" Grid.Column="0"
HorizontalOptions="Center" HorizontalOptions="Center"
VerticalOptions="Center" VerticalOptions="Center"
Padding="0"> Padding="0"
BackgroundColor="Red"
IsVisible="Hidden"
x:Name="RedDice">
<Label Text="{Binding Dice2.Value}" <Label Text="{Binding Dice2.Value}"
FontSize="16" FontSize="Large"
VerticalOptions="Center" VerticalOptions="Center"
HorizontalOptions="Center" HorizontalOptions="Center"
TextColor="Black" TextColor="Black"
x:Name="Dice2"/> x:Name="Dice2"
FontAttributes="Bold"/>
</Frame> </Frame>
</HorizontalStackLayout>
<Button Text="Roll" <Button Text="Roll"
HeightRequest="200" HeightRequest="25"
WidthRequest="200" WidthRequest="100"
Clicked="DiceButton_Clicked"/> Clicked="DiceButton_Clicked"
</HorizontalStackLayout> Grid.Row="1"
<Image Source="maptest.png" Aspect="AspectFit" Grid.ColumnSpan="2" Grid.RowSpan="3"/> Margin="0,50,0,0"
x:Name="RollButton"/>
</Grid>
<CollectionView ItemsSource="{Binding UsedMap.Boards}" <CollectionView ItemsSource="{Binding UsedMap.Boards}"
Grid.Row="1"
Grid.Column="1" Grid.Column="1"
SelectionMode="Single" SelectionMode="Single"
WidthRequest="350" WidthRequest="350"
HeightRequest="350" HeightRequest="350"
ItemsLayout="VerticalGrid,7" ItemsLayout="VerticalGrid,7"
BackgroundColor="Aqua"> x:Name="Board"
SelectionChanged="OnCellSelected">
<CollectionView.ItemTemplate> <CollectionView.ItemTemplate>
<DataTemplate> <DataTemplate x:Name="Cellule">
<Grid VerticalOptions="Center" HorizontalOptions="Center" HeightRequest="50" WidthRequest="50"> <Grid VerticalOptions="Center" HorizontalOptions="Center" HeightRequest="50" WidthRequest="50">
<Frame <Frame
@ -64,7 +82,15 @@
Opacity="0.7" Opacity="0.7"
VerticalOptions="Center" VerticalOptions="Center"
HorizontalOptions="Center" HorizontalOptions="Center"
Padding="0"> Padding="0"
x:Name="CellValid">
<Label Text="{Binding Value}"
x:Name="CellValue"
FontSize="Large"
VerticalOptions="Center"
HorizontalOptions="Center"
TextColor="Black"
FontAttributes="Bold"/>
<Frame.Triggers> <Frame.Triggers>
<DataTrigger TargetType="Frame" Binding="{Binding IsDangerous}" Value="True"> <DataTrigger TargetType="Frame" Binding="{Binding IsDangerous}" Value="True">
<Setter Property="BorderColor" Value="Black"/> <Setter Property="BorderColor" Value="Black"/>
@ -82,7 +108,7 @@
<!-- Operation Grid --> <!-- Operation Grid -->
<Grid Grid.Row="0" Grid.Column="2" <Grid Grid.Row="0" Grid.Column="2"
ColumnDefinitions="auto,*" ColumnDefinitions="auto,*"
RowDefinitions="*,auto"> RowDefinitions="auto,auto">
<!--Images des operations --> <!--Images des operations -->
<!--Grille de la partie--> <!--Grille de la partie-->
<CollectionView Grid.Column="1" <CollectionView Grid.Column="1"
@ -114,7 +140,8 @@
</CollectionView> </CollectionView>
<!--Les bouttons de selection d'operation--> <!--Les bouttons de selection d'operation-->
<HorizontalStackLayout Grid.Row="1" <HorizontalStackLayout Grid.Row="1"
Grid.ColumnSpan="2"> Grid.ColumnSpan="2"
VerticalOptions="Center">
<Button HeightRequest="50" <Button HeightRequest="50"
WidthRequest="100" WidthRequest="100"
x:Name="Lower" x:Name="Lower"

@ -1,5 +1,6 @@
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.VisualBasic;
namespace Trek_12.Views; namespace Trek_12.Views;
@ -10,10 +11,15 @@ public partial class PageBoard : ContentPage
{ {
public Game GameManager => (App.Current as App).Manager; public Game GameManager => (App.Current as App).Manager;
public int Result { get; set; }
public Cell ChoosenCell { get; set; }
public PageBoard() public PageBoard()
{ {
InitializeComponent(); InitializeComponent();
BindingContext = GameManager; BindingContext = GameManager;
GameManager.CurrentPlayer.UpdateLastPlayed();
GameManager.DiceRolled += TheGame_DiceRolled; GameManager.DiceRolled += TheGame_DiceRolled;
GameManager.DiceRolled += ResultAddition; GameManager.DiceRolled += ResultAddition;
@ -21,13 +27,59 @@ public partial class PageBoard : ContentPage
GameManager.DiceRolled += ResultHigher; GameManager.DiceRolled += ResultHigher;
GameManager.DiceRolled += ResultSubstraction; GameManager.DiceRolled += ResultSubstraction;
GameManager.DiceRolled += ResultMultiplication; GameManager.DiceRolled += ResultMultiplication;
GameManager.PlayerOption += GameManager_PlayerOption;
// We add this game to the list of games GameManager.CellChosen += HandleCellChosen;
GameManager.AddGame(GameManager); GameManager.AddGame(GameManager);
GameManager.OnPropertyChanged(nameof(GameManager.Games)); GameManager.OnPropertyChanged(nameof(GameManager.Games));
GameManager.SaveData(); GameManager.SaveData();
} }
private void HandleCellChosen(object sender, CellChosenEventArgs e)
{
YellowDice.IsVisible = false;
RedDice.IsVisible = false;
RollButton.IsEnabled = true;
}
private void ResetOperationButtonsAndDice()
{
Lower.IsVisible = false;
Higher.IsVisible = false;
Substraction.IsVisible = false;
Addition.IsVisible = false;
Multiplication.IsVisible = false;
RollButton.IsEnabled = true;
YellowDice.IsVisible = false;
RedDice.IsVisible = false;
}
private void SetOperationButtonState(Button selectedButton)
{
// Deselect all buttons
Lower.BackgroundColor = Colors.DarkSalmon;
Higher.BackgroundColor = Colors.DarkSalmon;
Substraction.BackgroundColor = Colors.DarkSalmon;
Addition.BackgroundColor = Colors.DarkSalmon;
Multiplication.BackgroundColor = Colors.DarkSalmon;
// Select the clicked button
selectedButton.BackgroundColor = Colors.LightCoral;
}
private void GameManager_PlayerOption(object? sender, PlayerOptionEventArgs e)
{
/* IEnumerable<Cell> PlayedCellsQuery =
from cell in e.Board
where cell.Valid == true
where cell.Value != null
select cell;*/
// prévisualisation des zone disponible, Je ne sais pas comment ca marche... 😵
}
private void ResultMultiplication(object? sender, DiceRolledEventArgs e) private void ResultMultiplication(object? sender, DiceRolledEventArgs e)
{ {
Multiplication.IsVisible = true; Multiplication.IsVisible = true;
@ -66,14 +118,16 @@ public partial class PageBoard : ContentPage
private void TheGame_DiceRolled(object? sender, Models.Events.DiceRolledEventArgs e) private void TheGame_DiceRolled(object? sender, Models.Events.DiceRolledEventArgs e)
{ {
YellowDice.IsVisible = true;
RedDice.IsVisible = true;
Dice1.Text = $"{e.Dice1Value}"; Dice1.Text = $"{e.Dice1Value}";
Dice2.Text = $"{e.Dice2Value}"; Dice2.Text = $"{e.Dice2Value}";
RollButton.IsEnabled = false;
} }
private void OnOperationCellSelected(object sender, SelectionChangedEventArgs e) private void OnOperationCellSelected(object sender, SelectionChangedEventArgs e)
{ {
Debug.WriteLine("OnOperationCellSelected"); // Debug if (e.CurrentSelection.Count > 0) // Si un élément est sélectionné
if (e.CurrentSelection.Count > 0) // Si un <20>l<EFBFBD>ment est s<>lectionn<6E>
{ {
var selectedCell = (OperationCell)e.CurrentSelection[0]; var selectedCell = (OperationCell)e.CurrentSelection[0];
if (selectedCell != null && !selectedCell.IsChecked) if (selectedCell != null && !selectedCell.IsChecked)
@ -81,38 +135,82 @@ public partial class PageBoard : ContentPage
selectedCell.Check(); selectedCell.Check();
Debug.WriteLine("OperationCell at ({0}, {1}) is checked", selectedCell.X, selectedCell.Y); // Debug Debug.WriteLine("OperationCell at ({0}, {1}) is checked", selectedCell.X, selectedCell.Y); // Debug
} }
((CollectionView)sender).SelectedItem = null; // D<EFBFBD>selectionne l'<27>l<EFBFBD>ment pour la CollectionView ((CollectionView)sender).SelectedItem = null; // Déselectionne l'élément pour la CollectionView
} }
} }
private void HigherClicked(object sender, EventArgs e) private void HigherClicked(object sender, EventArgs e)
{ {
GameManager.MarkOperationAsChecked(Operation.HIGHER); GameManager.PlayerOperation = Operation.HIGHER;
Higher.IsVisible = false; SetOperationButtonState((Button)sender);
Result = GameManager.ResultOperation(Operation.HIGHER);
GameManager.HandlePlayerOperation(Operation.HIGHER);
} }
private void LowerClicked(object sender, EventArgs e) private void LowerClicked(object sender, EventArgs e)
{ {
GameManager.MarkOperationAsChecked(Operation.LOWER); GameManager.PlayerOperation = Operation.LOWER;
SetOperationButtonState((Button)sender);
Result = GameManager.ResultOperation(Operation.LOWER);
GameManager.HandlePlayerOperation(Operation.LOWER);
} }
private void AdditionClicked(object sender, EventArgs e) private void AdditionClicked(object sender, EventArgs e)
{ {
GameManager.MarkOperationAsChecked(Operation.ADDITION); GameManager.PlayerOperation = Operation.ADDITION;
SetOperationButtonState((Button)sender);
Result = GameManager.ResultOperation(Operation.ADDITION);
GameManager.HandlePlayerOperation(Operation.ADDITION);
} }
private void SubstractionClicked(object sender, EventArgs e) private void SubstractionClicked(object sender, EventArgs e)
{ {
GameManager.MarkOperationAsChecked(Operation.SUBTRACTION); GameManager.PlayerOperation = Operation.SUBTRACTION;
SetOperationButtonState((Button)sender);
Result = GameManager.ResultOperation(Operation.SUBTRACTION);
GameManager.HandlePlayerOperation(Operation.SUBTRACTION);
} }
private void MultiplicationClicked(object sender, EventArgs e) private void MultiplicationClicked(object sender, EventArgs e)
{ {
GameManager.MarkOperationAsChecked(Operation.MULTIPLICATION); GameManager.PlayerOperation = Operation.MULTIPLICATION;
SetOperationButtonState((Button)sender);
Result = GameManager.ResultOperation(Operation.MULTIPLICATION);
GameManager.HandlePlayerOperation(Operation.MULTIPLICATION);
} }
private void DiceButton_Clicked(object sender, EventArgs e) private void DiceButton_Clicked(object sender, EventArgs e)
{ {
GameManager.RollAllDice(); GameManager.RollAllDice();
} }
private async void OnCellSelected(object sender, SelectionChangedEventArgs e)
{
if (!GameManager.DiceRolledFlag)
{
await DisplayAlert("Action Required", "You must roll the dice first.", "OK");
return;
}
if (!GameManager.OperationChosenFlag)
{
await DisplayAlert("Action Required", "You must choose an operation first.", "OK");
return;
}
if (e.CurrentSelection.Count > 0)
{
ChoosenCell = (Cell)e.CurrentSelection[0];
GameManager.PlayerCell = ChoosenCell;
GameManager.Resultat = Result;
OnPropertyChanged(nameof(GameManager.PlayerCell));
OnPropertyChanged(nameof(GameManager.Resultat));
GameManager.PlayerSelectionCell();
((CollectionView)sender).SelectedItem = null;
ResetOperationButtonsAndDice();
}
}
} }

@ -42,6 +42,16 @@
</DataTemplate> </DataTemplate>
</CollectionView.ItemTemplate> </CollectionView.ItemTemplate>
</CollectionView> </CollectionView>
<Button Text="Reprendre"
TextColor="White"
BackgroundColor="DarkRed"
FontAttributes="Bold"
FontSize="Large"
Grid.Row="2"
Margin="80"
HorizontalOptions="Center"
Clicked="ResumeButton_Clicked"
IsVisible="{Binding IsPreviousGameNotFinished}"/>
<Button Text="Retour" <Button Text="Retour"
FontAttributes="Bold" FontAttributes="Bold"
FontSize="Large" FontSize="Large"

@ -10,12 +10,14 @@ public partial class PageSelectMap : ContentPage
public Game SelectMapManager => (App.Current as App).Manager; public Game SelectMapManager => (App.Current as App).Manager;
private Map? _selectedMap; private Map? _selectedMap;
private bool isVisibleContinueButton = false;
protected override async void OnAppearing() protected override async void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
if (SelectMapManager.Games.Any(g => g.IsRunning)) if (SelectMapManager.Games.Any(g => g.IsRunning))
{ {
isVisibleContinueButton = true;
await DisplayAlert("Warning", "You've previously quit in the middle of a game.\nIf you start a new game, this one will be permanently lost.", "I understand"); await DisplayAlert("Warning", "You've previously quit in the middle of a game.\nIf you start a new game, this one will be permanently lost.", "I understand");
} }
@ -57,9 +59,26 @@ public partial class PageSelectMap : ContentPage
Player chosenPlayer = GetProfileByName(choosenPlayerName); Player chosenPlayer = GetProfileByName(choosenPlayerName);
SelectMapManager.InitializeGame(_selectedMap, chosenPlayer); var runningGames = SelectMapManager.Games.Where(g => g.IsRunning).ToList();
bool delete = false;
foreach (var game in runningGames)
{
SelectMapManager.Games.Remove(game);
delete = true;
}
if (delete)
{
await DisplayAlert("Game deleted", "The previous game has been deleted because you started a new one.", "OK");
SelectMapManager.OnPropertyChanged(nameof(SelectMapManager.Games));
SelectMapManager.SaveData();
}
SelectMapManager.InitializeGame(_selectedMap.Clone(), chosenPlayer);
if (SelectMapManager.UsedMap == _selectedMap && Equals(SelectMapManager.CurrentPlayer, chosenPlayer)) if (SelectMapManager.UsedMap != null && Equals(SelectMapManager.CurrentPlayer, chosenPlayer))
{ {
await Shell.Current.GoToAsync(nameof(PageBoard)); await Shell.Current.GoToAsync(nameof(PageBoard));
} }
@ -79,4 +98,17 @@ public partial class PageSelectMap : ContentPage
return SelectMapManager.Players.FirstOrDefault(p => p.Pseudo == pseudo); return SelectMapManager.Players.FirstOrDefault(p => p.Pseudo == pseudo);
} }
private async void ResumeButton_Clicked(object sender, EventArgs e)
{
Game game = SelectMapManager.Games.FirstOrDefault(g => g.IsRunning);
if (game == null)
{
await DisplayAlert("No game found", "No game found to resume. Please start a new game.", "OK");
return;
}
SelectMapManager.InitializeGame(game.UsedMap, game.CurrentPlayer, false);
await Shell.Current.GoToAsync(nameof(PageBoard));
}
} }
Loading…
Cancel
Save