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>
<summary>Sonarcube Ratings</summary>
@ -27,4 +27,29 @@ Auteurs:
<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
using Models;
using Models.Events;
using Models.Game;
using Models.Interfaces;
using DataContractPersistence;
using Microsoft.Extensions.Logging;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace ConsoleApp;
class Program
{
static Game Game { get; set; }
/// <summary>
/// Main function of the console app
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Console.WriteLine("Enter your pseudo:");
string? pseudo = Console.ReadLine();
if (pseudo != null)
{
IPersistence persistence = new DataContractXml();
Player player = new Player(pseudo, "test.png");
Map map = new Map("Dunai","background");
Game = new Game(persistence);
// Abonnement aux événements
Game.GameStarted += OnGameStarted!;
Game.GameEnded += OnGameEnded!;
Game.BoardUpdated += OnBoardUpdated!;
Game.DiceRolled += OnDiceRolled!;
Game.OperationChosen += OnOperationChosen!;
Game.CellChosen += OnCellChosen!;
Game.PlayerChooseOp += OnPlayerSelectionOp!;
Game.PlayerOption += OnPlayerOption!;
Game.PlayerChooseCell += OnPlayerSelectionCell!;
// Initialisation
Game.InitializeGame(map, player);
}
}
static void OnPlayerSelectionCell(Object sender, PlayerChooseCellEventArgs e)
{
int row, column;
while (true)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Enter the position of the cell you want to play");
Console.WriteLine("Enter the row number (0-6)");
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.ResetColor();
continue;
}
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Enter the column number (0-6)");
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.ResetColor();
continue;
}
Game.PlayerCell = new Cell(row, column);
break;
}
}
static void OnPlayerOption(object sender, PlayerOptionEventArgs e)
{
Console.WriteLine();
if(e.Turn != 1)
{
IEnumerable<Cell> PlayedCellsQuery =
// See https://aka.ms/new-console-template for more information
using Models;
using Models.Events;
using Models.Game;
using Models.Interfaces;
using DataContractPersistence;
using Microsoft.Extensions.Logging;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace ConsoleApp;
class Program
{
static Game Game { get; set; }
/// <summary>
/// Main function of the console app
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Console.WriteLine("Enter your pseudo:");
string? pseudo = Console.ReadLine();
if (pseudo != null)
{
IPersistence persistence = new DataContractXml();
Player player = new Player(pseudo, "test.png");
Map map = new Map("Dunai","background");
Game = new Game(persistence);
// Abonnement aux événements
Game.GameStarted += OnGameStarted!;
Game.GameEnded += OnGameEnded!;
Game.BoardUpdated += OnBoardUpdated!;
Game.DiceRolled += OnDiceRolled!;
Game.OperationChosen += OnOperationChosen!;
Game.CellChosen += OnCellChosen!;
Game.PlayerChooseOp += OnPlayerSelectionOp!;
Game.PlayerOption += OnPlayerOption!;
Game.PlayerChooseCell += OnPlayerSelectionCell!;
// Initialisation
Game.InitializeGame(map, player);
Game.GameLoop();
}
}
static void OnPlayerSelectionCell(Object sender, PlayerChooseCellEventArgs e)
{
int row, column;
while (true)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Enter the position of the cell you want to play");
Console.WriteLine("Enter the row number (0-6)");
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.ResetColor();
continue;
}
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Enter the column number (0-6)");
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.ResetColor();
continue;
}
Game.PlayerCell = new Cell(row, column);
break;
}
}
static void OnPlayerOption(object sender, PlayerOptionEventArgs e)
{
Console.WriteLine();
if (e.Turn != 1)
{
IEnumerable<Cell> PlayedCellsQuery =
from cell in e.Board
where cell.Valid == true
where cell.Value != null
select cell;
foreach (var item in e.Board)
{
if (item.X == 6)
Console.WriteLine();
if (!item.Valid)
Console.Write(" ");
else if (item.Value != null)
Console.Write($"{item.Value}");
else
{
foreach (var item1 in PlayedCellsQuery)
{
if (Math.Abs(item.X - item1.X) <= 1 && Math.Abs(item.Y - item1.Y) <= 1)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write($"{e.Resultat}");
Console.ResetColor();
}
}
}
}
return;
}
foreach (var item in e.Board)
{
if (!item.Valid)
Console.Write(" ");
else
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write($"{e.Resultat}");
Console.ResetColor();
}
if (item.X == 6)
Console.WriteLine();
}
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Choose an Available cell.");
Console.ResetColor();
}
static void OnPlayerSelectionOp(object sender, PlayerChooseOperationEventArgs e)
{
Console.WriteLine();
DisplayOperationTable(((Game)sender).UsedMap.OperationGrid.ToList());
Console.WriteLine();
Console.WriteLine("0. Lower | 1. Higher | 2. Substraction | 3. Addition | 4. Multiplication");
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.ResetColor();
op = Console.ReadLine();
}
int test = Convert.ToInt32(op);
Game.PlayerOperation = (Operation)test;
}
/// <summary>
/// Handles the event when the game has started.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnGameStarted(object sender, GameStartedEventArgs e)
{
Console.WriteLine($"The game has started! Player: {e.CurrentPlayer.Pseudo}");
}
/// <summary>
/// Handles the event when the game has ended.
/// </summary>
/// <param name="sender"></param>
/// <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}");
}
/// <summary>
/// Handles the event when the board is updated.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnBoardUpdated(object sender, BoardsUpdateEventArgs e)
{
foreach (var item in e.Boards)
{
if (!item.Valid)
Console.Write(" ");
else if (item.Value != null)
Console.Write($"{item.Value}");
else Console.Write("O");
if (item.X == 6)
Console.WriteLine();
}
}
/// <summary>
/// Handles the event when the dice are rolled.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnDiceRolled(object sender, DiceRolledEventArgs e)
{
// Console.Clear();
Console.WriteLine($"Dice 1: {e.Dice1Value} | Dice 2: {e.Dice2Value}");
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Choose an operation.");
Console.ResetColor();
}
/// <summary>
/// Handles the event when an operation is chosen by the player.
/// </summary>
/// <param name="sender"></param>
/// <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());
Cell playerChoice = GetPlayerChoice();
bool test = ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
if(!test)
{
Console.WriteLine("Invalid cell. Please choose again.");
Console.WriteLine();
Console.WriteLine();
DisplayBoard(((Game)sender).UsedMap);
OnOperationChosen(sender, e);
}
/*
try
{
((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
}
catch (InvalidCellCoordinatesException err)
{
Console.WriteLine(err.Message);
playerChoice = GetPlayerChoice();
((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
}
catch (InvalidCellException err)
{
Console.WriteLine(err.Message);
playerChoice = GetPlayerChoice();
((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
}
catch (InvalidPlaceResultException err)
{
Console.WriteLine(err.Message);
playerChoice = GetPlayerChoice();
((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
}
*/
}
/// <summary>
/// Handles the event when a cell is chosen by the player.
/// </summary>
/// <param name="sender"></param>
/// <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);
}
/// <summary>
/// Displays the game board.
/// </summary>
/// <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++)
{
if (cpt % 6 == 0)
{
Console.Write("| ");
}
if (map.Boards[i].Value.HasValue)
{
Console.Write(map.Boards[i].Value?.ToString().PadLeft(2));
}
else
{
Console.Write(" O");
}
cpt++;
if (cpt % 6 == 0)
{
Console.Write(" |");
Console.WriteLine();
}
}
}
/// <summary>
/// Displays the operation table.
/// </summary>
/// <param name="operationTable">The operation table to display.</param>
static void DisplayOperationTable(List<OperationCell> 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 == 1)
Console.Write("Higher => ");
if (cell.X == 0 && cell.Y == 2)
Console.Write("Substraction => ");
if (cell.X == 0 && cell.Y == 3)
Console.Write("Addition => ");
if (cell.X == 0 && cell.Y == 4)
Console.Write("Multiplication => ");
if (cell.IsChecked)
Console.Write("X | ");
if (!cell.IsChecked)
Console.Write(" | ");
if (cell.X == 3)
Console.WriteLine();
}
Console.ResetColor();
}
/// <summary>
/// Gets the cell chosen by the player.
/// </summary>
/// <returns>The cell chosen by the player.</returns>
static Cell GetPlayerChoice()
{
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)");
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("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;
}
return new Cell(row, column);
}
}
/// <summary>
/// Gets the operation chosen by the player.
/// </summary>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
static Operation GetPlayerOperation(object? sender)
{
DisplayOperationOptions();
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();
}
int test = Convert.ToInt32(op);
while(((Game)sender).UsedMap.CheckOperationPossible(test-1))
{
Console.WriteLine("Invalid operation. Please choose again.");
Console.WriteLine();
op = Console.ReadLine();
while (op != "1" && op != "2" && op != "3" && op != "4" && op != "5")
{
Console.WriteLine("Invalid operation. Please choose again.");
op = Console.ReadLine();
}
test = Convert.ToInt32(op);
}
return op switch
{
"1" => Operation.ADDITION,
"2" => Operation.SUBTRACTION,
"3" => Operation.MULTIPLICATION,
"4" => Operation.LOWER,
"5" => Operation.HIGHER,
_ => throw new ArgumentOutOfRangeException()
};
}
/// <summary>
/// Displays the operation options for the player to choose from.
/// </summary>
static void DisplayOperationOptions()
{
Console.WriteLine("Choose an operation:");
Console.WriteLine("1: Addition (+)");
Console.WriteLine("2: Subtraction (-)");
Console.WriteLine("3: Multiplication (*)");
Console.WriteLine("4: Lower Dice (less)");
Console.WriteLine("5: Higher Dice (high)");
}
where cell.Valid == true
where cell.Value != null
select cell;
foreach (var item in e.Board)
{
if (item.X == 6)
Console.WriteLine();
if (!item.Valid)
Console.Write(" ");
else if (item.Value != null)
Console.Write($"{item.Value}");
else
{
foreach (var item1 in PlayedCellsQuery)
{
if (Math.Abs(item.X - item1.X) <= 1 && Math.Abs(item.Y - item1.Y) <= 1)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write($"{e.Resultat}");
Console.ResetColor();
}
}
}
}
return;
}
foreach (var item in e.Board)
{
if (!item.Valid)
Console.Write(" ");
else
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write($"{e.Resultat}");
Console.ResetColor();
}
if (item.X == 6)
Console.WriteLine();
}
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Choose an Available cell.");
Console.ResetColor();
}
static void OnPlayerSelectionOp(object sender, PlayerChooseOperationEventArgs e)
{
Console.WriteLine();
DisplayOperationTable(((Game)sender).UsedMap.OperationGrid.ToList());
Console.WriteLine();
Console.WriteLine("0. Lower | 1. Higher | 2. Substraction | 3. Addition | 4. Multiplication");
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.ResetColor();
op = Console.ReadLine();
}
int test = Convert.ToInt32(op);
Game.PlayerOperation = (Operation)test;
}
/// <summary>
/// Handles the event when the game has started.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnGameStarted(object sender, GameStartedEventArgs e)
{
Console.WriteLine($"The game has started! Player: {e.CurrentPlayer.Pseudo}");
}
/// <summary>
/// Handles the event when the game has ended.
/// </summary>
/// <param name="sender"></param>
/// <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}");
}
/// <summary>
/// Handles the event when the board is updated.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnBoardUpdated(object sender, BoardsUpdateEventArgs e)
{
foreach (var item in e.Boards)
{
if (!item.Valid)
Console.Write(" ");
else if (item.Value != null)
Console.Write($"{item.Value}");
else Console.Write("O");
if (item.X == 6)
Console.WriteLine();
}
}
/// <summary>
/// Handles the event when the dice are rolled.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnDiceRolled(object sender, DiceRolledEventArgs e)
{
// Console.Clear();
Console.WriteLine($"Dice 1: {e.Dice1Value} | Dice 2: {e.Dice2Value}");
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Choose an operation.");
Console.ResetColor();
}
/// <summary>
/// Handles the event when an operation is chosen by the player.
/// </summary>
/// <param name="sender"></param>
/// <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());
Cell playerChoice = GetPlayerChoice();
bool test = ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
if(!test)
{
Console.WriteLine("Invalid cell. Please choose again.");
Console.WriteLine();
Console.WriteLine();
DisplayBoard(((Game)sender).UsedMap);
OnOperationChosen(sender, e);
}
/*
try
{
((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
}
catch (InvalidCellCoordinatesException err)
{
Console.WriteLine(err.Message);
playerChoice = GetPlayerChoice();
((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
}
catch (InvalidCellException err)
{
Console.WriteLine(err.Message);
playerChoice = GetPlayerChoice();
((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
}
catch (InvalidPlaceResultException err)
{
Console.WriteLine(err.Message);
playerChoice = GetPlayerChoice();
((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
}
*/
}
/// <summary>
/// Handles the event when a cell is chosen by the player.
/// </summary>
/// <param name="sender"></param>
/// <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);
}
/// <summary>
/// Displays the game board.
/// </summary>
/// <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++)
{
if (cpt % 6 == 0)
{
Console.Write("| ");
}
if (map.Boards[i].Value.HasValue)
{
Console.Write(map.Boards[i].Value?.ToString().PadLeft(2));
}
else
{
Console.Write(" O");
}
cpt++;
if (cpt % 6 == 0)
{
Console.Write(" |");
Console.WriteLine();
}
}
}
/// <summary>
/// Displays the operation table.
/// </summary>
/// <param name="operationTable">The operation table to display.</param>
static void DisplayOperationTable(List<OperationCell> 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 == 1)
Console.Write("Higher => ");
if (cell.X == 0 && cell.Y == 2)
Console.Write("Substraction => ");
if (cell.X == 0 && cell.Y == 3)
Console.Write("Addition => ");
if (cell.X == 0 && cell.Y == 4)
Console.Write("Multiplication => ");
if (cell.IsChecked)
Console.Write("X | ");
if (!cell.IsChecked)
Console.Write(" | ");
if (cell.X == 3)
Console.WriteLine();
}
Console.ResetColor();
}
/// <summary>
/// Gets the cell chosen by the player.
/// </summary>
/// <returns>The cell chosen by the player.</returns>
static Cell GetPlayerChoice()
{
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)");
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("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;
}
return new Cell(row, column);
}
}
/// <summary>
/// Gets the operation chosen by the player.
/// </summary>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
static Operation GetPlayerOperation(object? sender)
{
DisplayOperationOptions();
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();
}
int test = Convert.ToInt32(op);
while(((Game)sender).UsedMap.CheckOperationPossible(test-1))
{
Console.WriteLine("Invalid operation. Please choose again.");
Console.WriteLine();
op = Console.ReadLine();
while (op != "1" && op != "2" && op != "3" && op != "4" && op != "5")
{
Console.WriteLine("Invalid operation. Please choose again.");
op = Console.ReadLine();
}
test = Convert.ToInt32(op);
}
return op switch
{
"1" => Operation.ADDITION,
"2" => Operation.SUBTRACTION,
"3" => Operation.MULTIPLICATION,
"4" => Operation.LOWER,
"5" => Operation.HIGHER,
_ => throw new ArgumentOutOfRangeException()
};
}
/// <summary>
/// Displays the operation options for the player to choose from.
/// </summary>
static void DisplayOperationOptions()
{
Console.WriteLine("Choose an operation:");
Console.WriteLine("1: Addition (+)");
Console.WriteLine("2: Subtraction (-)");
Console.WriteLine("3: Multiplication (*)");
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
{
@ -6,7 +8,7 @@ namespace Models.Game
/// The Cell class represents a cell in the application.
/// </summary>
[DataContract]
public class Cell : Position, IEquatable<Cell>
public class Cell : Position, IEquatable<Cell>, INotifyPropertyChanged
{
/// <summary>
/// The value of the cell.
@ -22,6 +24,8 @@ namespace Models.Game
throw new Exception("La valeur doit être supérieure à 0");
}
this._value = value;
OnPropertyChanged();
}
}
@ -76,5 +80,13 @@ namespace Models.Game
if (this.X == other.X && this.Y == other.Y) return true;
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")]
public class Game : INotifyPropertyChanged
{
public bool IsPreviousGameNotFinished { get; private set; }
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
@ -110,13 +112,34 @@ namespace Models.Game
public Dice Dice2 { get; private set; }
[DataMember]
public int Turn { get; private set; }
public int Turn { get; set; }
[Ignore]
public Operation PlayerOperation { get; set; }
private Cell _playerCell;
[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]
public Rules.Rules GameRules { get; }
@ -149,25 +172,45 @@ namespace Models.Game
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)
{
BestScore bs = new BestScore(UsedMap.Name, CurrentPlayer, 1, finalScore);
foreach (var score in BestScores)
{
if (!bs.Equals(score)) continue;
var existingScore = BestScores.FirstOrDefault(score => score.Equals(bs));
score.IncrGamesPlayed();
score.UpdateScore(finalScore);
return;
if (existingScore != null)
{
existingScore.IncrGamesPlayed();
existingScore.UpdateScore(finalScore);
}
else
{
BestScores.Add(bs);
}
BestScores.Add(bs);
BestScores.OrderByDescending(p => p.Score);
// Sorting the best scores
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)
{
Player player = Players.FirstOrDefault(p => p.Pseudo == playerName);
Player? player = Players.FirstOrDefault(p => p.Pseudo == playerName);
if (player == null)
{
return false;
@ -177,6 +220,12 @@ namespace Models.Game
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)
{
foreach (var index in Players)
@ -192,6 +241,10 @@ namespace Models.Game
return false;
}
/// <summary>
/// Removes a game from the list of games.
/// </summary>
/// <param name="playerName"></param>
public void CheckAndRemoveBestScoresDependencies(string playerName)
{
List<BestScore> bs = new List<BestScore>();
@ -207,7 +260,12 @@ namespace Models.Game
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)
{
foreach (var bestScore in BestScores)
@ -227,6 +285,10 @@ namespace Models.Game
}
foreach (var game in data.Item2)
{
if (game.IsRunning)
{
IsPreviousGameNotFinished = true;
}
Games.Add(game);
}
foreach (var map in data.Item3)
@ -274,7 +336,11 @@ namespace Models.Game
{
Dice1.Roll();
Dice2.Roll();
DiceRolledFlag = true;
OperationChosenFlag = false;
DiceRolled?.Invoke(this, new DiceRolledEventArgs(Dice1.Value, Dice2.Value));
OnPropertyChanged(nameof(Dice1));
OnPropertyChanged(nameof(Dice2));
}
/// <summary>
@ -340,8 +406,19 @@ namespace Models.Game
select cell;
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;
OnPropertyChanged(nameof(UsedMap.Boards));
return;
}
}
}
@ -350,35 +427,32 @@ namespace Models.Game
/// </summary>
/// <param name="playerChoice"></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))
{
// 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;
if(Turn==1) return;
int index = 0;
// 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
if (!GameRules.IsInRopePaths(cells,UsedMap.RopePaths,index))
{
UsedMap.RopePaths.Add(new List<Cell> { playerChoice, cells });
foreach (var item in ValidCell)
{
if (!GameRules.IsCellAdjacent(playerChoice, item))
continue;
if (!((playerChoice.Value - item.Value) == 1 || (playerChoice.Value - item.Value) == -1))
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);
return;
}
}
}
@ -388,16 +462,30 @@ namespace Models.Game
/// </summary>
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;
CurrentPlayer = player;
Turn = 1;
Dice1 = new Dice();
Dice2 = new Dice(1);
IsPreviousGameNotFinished = false;
OnPropertyChanged(nameof(UsedMap));
OnPropertyChanged(nameof(CurrentPlayer));
OnPropertyChanged(nameof(Turn));
if (startImmediately)
{
StartGame();
}
SaveData();
}
/// <summary>
@ -407,7 +495,8 @@ namespace Models.Game
{
IsRunning = true;
GameStarted?.Invoke(this, new GameStartedEventArgs(CurrentPlayer));
GameLoop();
SaveData();
}
/// <summary>
@ -422,19 +511,15 @@ namespace Models.Game
/// <summary>
/// The main game loop that runs while the game is active.
/// </summary>
private void GameLoop()
public void GameLoop()
{
int res = 0,turn = 1;
Cell cell;
while (IsRunning)
{
RollAllDice();
res = PlayerChooseOperation();
PlayerOption?.Invoke(this,new PlayerOptionEventArgs(UsedMap.Boards.ToList(),res,turn));
Resultat = PlayerChooseOperation();
PlayerSelectionCell();
PlaceResult(PlayerCell,res);
BoardUpdated?.Invoke(this, new BoardsUpdateEventArgs(UsedMap.Boards.ToList()));
turn++;
Turn++;
}
}
@ -445,6 +530,8 @@ namespace Models.Game
{
PlayerChooseOp?.Invoke(this, new PlayerChooseOperationEventArgs(PlayerOperation));
}
PlayerOption?.Invoke(this, new PlayerOptionEventArgs(UsedMap.Boards.ToList(), ResultOperation(PlayerOperation), Turn));
OperationChosenFlag = true;
return ResultOperation(PlayerOperation);
}
@ -456,6 +543,9 @@ namespace Models.Game
PlayerChooseCell?.Invoke(this, new PlayerChooseCellEventArgs(PlayerCell));
}
MarkOperationAsChecked(PlayerOperation);
PlaceResult(PlayerCell, Resultat);
DiceRolledFlag = false;
OperationChosenFlag = false;
}
/// <summary>
@ -465,6 +555,7 @@ namespace Models.Game
public void HandlePlayerOperation(Operation operation)
{
int result = ResultOperation(operation);
OperationChosenFlag = true;
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)
{
return false;
//throw new InvalidCellCoordinatesException("Invalid cell coordinates. Please choose again.");
}
if (!GameRules.IsCellValid(cell, UsedMap.Boards.ToList()))
{
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);
AddToRopePath(cell, GameRules.EveryAdjacentCells(cell, UsedMap.Boards.ToList()));
AddToRopePath(cell);
CellChosen?.Invoke(this, new CellChosenEventArgs(cell, result));
return true;
//BoardUpdated?.Invoke(this, EventArgs.Empty);
}
/// <summary>
@ -522,7 +604,7 @@ namespace Models.Game
foreach (var cells in Boards)
if (cells.Penalty)
{
if (cells.Valid == false || cells.Value == null)
if (!cells.Valid || cells.Value == null)
continue;
result += 3;
}
@ -533,7 +615,7 @@ namespace Models.Game
{
foreach (var cells in Boards)
{
if (cells == null || cells.Value == null || cells.Valid == false)
if (cells == null || cells.Value == null || !cells.Valid)
continue;
if (!UsedMap.IsCellInZones(cells) && !UsedMap.IsCellInRopePath(cells))
cells.SetPenalty();
@ -547,7 +629,7 @@ namespace Models.Game
{
points += GameRules.ScoreRopePaths(UsedMap.RopePaths[i]);
}
points += CalculusOfPenalty(UsedMap.Boards);
points -= CalculusOfPenalty(UsedMap.Boards);
return points ?? 0;
}

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

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

@ -15,9 +15,9 @@ namespace Models.Game
[DataContract, SQLite.Table("Players")]
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));
@ -63,9 +63,6 @@ namespace Models.Game
/// <param name="profilePicture">The profile picture of the player.</param>
public Player(string pseudo, string profilePicture)
{
//char[] trim = { ' ', '\n', '\t' };
//Pseudo = pseudo.Trim();
//Pseudo = Pseudo.TrimEnd(trim);
Pseudo = pseudo;
ProfilePicture = profilePicture;
CreationDate = DateTime.Now.ToString("dd/MM/yyyy");

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

@ -69,5 +69,67 @@ namespace Tests
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);
}
[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]
[InlineData(Operation.ADDITION, 3, 4, 7)]
[InlineData(Operation.SUBTRACTION, 6, 4, 2)]
@ -191,7 +172,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player);
_game.InitializeGame(map, player, false);
Assert.Equal(map, _game.UsedMap);
}
@ -202,7 +183,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player);
_game.InitializeGame(map, player, false);
Assert.Equal(player, _game.CurrentPlayer);
}
@ -213,7 +194,7 @@ public class GameTests
Player player = new Player("test_player", "DefaultProfilePicture");
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.Dice2);
@ -233,7 +214,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture");
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
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 map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player);
_game.InitializeGame(map, player, false);
Assert.NotNull(_game.GameRules);
_game.UsedMap.Boards[0].Value = 1;
_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);
Assert.NotNull(methodInfo);
var cell = new Cell(0, 2);
cell.Value = 3;
methodInfo.Invoke(_game, new object[] { cell, 3 });
_game.PlayerCell = new Cell(2, 0);
_game.PlayerCell.Value = 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);
}
@ -287,10 +272,13 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture");
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[1].Valid = true;
bool result = _game.HandlePlayerChoice(cell, 1);
Assert.True(result);
}
@ -301,7 +289,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player);
_game.InitializeGame(map, player, false);
var cell = new Cell(0, 7);
cell.Value = 1;
@ -315,7 +303,7 @@ public class GameTests
var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player);
_game.InitializeGame(map, player, false);
var cell = new Cell(0, 0);
cell.Value = 1;
@ -324,25 +312,6 @@ public class GameTests
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]
public void RemovePlayerTest_ShouldRemovePlayer()
{
@ -366,15 +335,17 @@ public class GameTests
{
var player = new Player("test_player", "DefaultProfilePicture");
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;
var methodInfo = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo);
var cell = new Cell(0, 2);
cell.Value = 14;
methodInfo.Invoke(_game, new object[] { cell, 14 });
_game.PlayerCell = new Cell(2, 0);
_game.PlayerCell.Value = 14;
methodInfo.Invoke(_game, new object[] { _game.PlayerCell, 14 });
Assert.True(_game.UsedMap.Boards[2].Penalty);
}
@ -384,16 +355,20 @@ public class GameTests
{
var player = new Player("test_player", "DefaultProfilePicture");
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[2].IsDangerous = true;
var methodInfo = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo);
var cell = new Cell(0, 2);
cell.Value = 7;
methodInfo.Invoke(_game, new object[] { cell, 7 });
_game.PlayerCell = new Cell(2, 0);
_game.PlayerCell.Value = 7;
methodInfo.Invoke(_game, new object[] { _game.PlayerCell, 7 });
Assert.True(_game.UsedMap.Boards[2].Penalty);
}
@ -403,7 +378,7 @@ public class GameTests
{
var player = new Player("test_player", "DefaultProfilePicture");
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[3].Valid = true;
@ -431,7 +406,7 @@ public class GameTests
{
var player = new Player("test_player", "DefaultProfilePicture");
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[2].Value = 2;
@ -443,7 +418,7 @@ public class GameTests
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);
@ -453,42 +428,114 @@ public class GameTests
}
[Fact]
public void CalculusOfPenalty_ReallyCalculusPenalty()
public void CalculusOfPenalty_ReallyCalculusPenalty_ForZonesAndDangerousCellsAndOverTwelve()
{
var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player);
var methodInfo = typeof(Game).GetMethod("AddToRopePath", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(methodInfo);
_game.InitializeGame(map, player, false);
_game.UsedMap.Boards[0].Valid = true;
_game.UsedMap.Boards[1].Valid = true;
_game.UsedMap.Boards[2].Valid = true;
_game.UsedMap.Boards[3].Valid = true;
_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[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);
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]
public void CalculusOfPenalty_ReallyCalculusPenalty_ForZonesAndDangerousCellsAndOverTwelve()
public void CanIStartGame()
{
var player = new Player("test_player", "DefaultProfilePicture");
var map = new Map("test_name", "test_background.png");
_game.InitializeGame(map, player);
_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);
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[8].Valid = true;
@ -497,24 +544,20 @@ public class GameTests
_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
_game.UsedMap.Boards[10].Value = 2; // penalty (- 3)
_game.UsedMap.Boards[7].Value = 5; //5 + 2 = 7
_game.UsedMap.Boards[8].Value = 5;
_game.UsedMap.Boards[9].Value = 5;
var place = typeof(Game).GetMethod("PlaceResult", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(place);
var cell = new Cell(1, 4);
cell.Value = 7;
cell.Valid = true;
cell.IsDangerous = true;
place.Invoke(_game, new object[] { cell, 7 }); //One penalty
_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
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())
@ -525,7 +568,127 @@ public class GameTests
_game.PutPenaltyForLostCells(_game.UsedMap.Boards);
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);
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 };
map.RopePaths.Add(paths);
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);
Assert.Equal(pseudo, player.Pseudo);
Assert.Equal(profilePicture, player.ProfilePicture);
Assert.Null(player.LastPlayed);
}
[Theory]
@ -46,4 +47,15 @@ public class PlayerTests
Player player = new Player("test_pseudo", "DefaultProfilePicture");
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();
Map map = new Map("test", "background");
map.Boards[0].Valid = true;
Cell selectedCell = map.Boards[0];
Assert.True(rules.IsCellValid(selectedCell, map.Boards.ToList()));
}
@ -179,6 +180,7 @@ public class RulesTests
Cell cell1 = new Cell(0, 0);
Cell cell2 = new Cell(0, 1);
cell2.Value = 12;
cell2.Valid = true;
List<Cell> cells = new List<Cell> { cell2 };
Assert.True(rules.NearCellIsValid(cell1, cells));
}

@ -5,15 +5,15 @@ VisualStudioVersion = 17.8.34408.163
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trek-12", "Trek-12\Trek-12.csproj", "{41EE7BF8-DDE6-4B00-9434-076589C0B419}"
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
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
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
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
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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

@ -40,9 +40,9 @@ namespace Trek_12
/* Add the permanent maps if they are not already in the game */
if (Manager.Maps.Count == 0)
{
Manager.AddMap(new Map("Dunai","profile.jpg"));
Manager.AddMap(new Map("Kagkot","montagne1.png"));
Manager.AddMap(new Map("Dhaulagiri","tmp1.jpeg"));
Manager.AddMap(new Map("Dunai","montagne2.png"));
Manager.AddMap(new Map("Kagkot", "montagne3.png"));
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>
<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 -->
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
@ -38,6 +38,14 @@
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsOSPlatform('windows'))">
<TargetFrameworks>$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<WindowsPackageType>MSIX</WindowsPackageType>
<PackageCertificateThumbprint>404032fa5d4dc4c8bbf036505d2409963f355ebd</PackageCertificateThumbprint>
</PropertyGroup>
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\app_icon.png" />
@ -47,7 +55,6 @@
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
@ -61,6 +68,9 @@
<None Remove="Resources\Images\back_arrow.png" />
<None Remove="Resources\Images\checked.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" />
</ItemGroup>

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

@ -1,5 +1,6 @@
using System.ComponentModel;
using System.Diagnostics;
using Microsoft.VisualBasic;
namespace Trek_12.Views;
@ -10,10 +11,15 @@ public partial class PageBoard : ContentPage
{
public Game GameManager => (App.Current as App).Manager;
public int Result { get; set; }
public Cell ChoosenCell { get; set; }
public PageBoard()
{
InitializeComponent();
BindingContext = GameManager;
GameManager.CurrentPlayer.UpdateLastPlayed();
GameManager.DiceRolled += TheGame_DiceRolled;
GameManager.DiceRolled += ResultAddition;
@ -21,13 +27,59 @@ public partial class PageBoard : ContentPage
GameManager.DiceRolled += ResultHigher;
GameManager.DiceRolled += ResultSubstraction;
GameManager.DiceRolled += ResultMultiplication;
// We add this game to the list of games
GameManager.PlayerOption += GameManager_PlayerOption;
GameManager.CellChosen += HandleCellChosen;
GameManager.AddGame(GameManager);
GameManager.OnPropertyChanged(nameof(GameManager.Games));
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)
{
Multiplication.IsVisible = true;
@ -66,14 +118,16 @@ public partial class PageBoard : ContentPage
private void TheGame_DiceRolled(object? sender, Models.Events.DiceRolledEventArgs e)
{
YellowDice.IsVisible = true;
RedDice.IsVisible = true;
Dice1.Text = $"{e.Dice1Value}";
Dice2.Text = $"{e.Dice2Value}";
RollButton.IsEnabled = false;
}
private void OnOperationCellSelected(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine("OnOperationCellSelected"); // Debug
if (e.CurrentSelection.Count > 0) // Si un <20>l<EFBFBD>ment est s<>lectionn<6E>
if (e.CurrentSelection.Count > 0) // Si un élément est sélectionné
{
var selectedCell = (OperationCell)e.CurrentSelection[0];
if (selectedCell != null && !selectedCell.IsChecked)
@ -81,38 +135,82 @@ public partial class PageBoard : ContentPage
selectedCell.Check();
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)
{
GameManager.MarkOperationAsChecked(Operation.HIGHER);
Higher.IsVisible = false;
GameManager.PlayerOperation = Operation.HIGHER;
SetOperationButtonState((Button)sender);
Result = GameManager.ResultOperation(Operation.HIGHER);
GameManager.HandlePlayerOperation(Operation.HIGHER);
}
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)
{
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)
{
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)
{
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)
{
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>
</CollectionView.ItemTemplate>
</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"
FontAttributes="Bold"
FontSize="Large"

@ -10,12 +10,14 @@ public partial class PageSelectMap : ContentPage
public Game SelectMapManager => (App.Current as App).Manager;
private Map? _selectedMap;
private bool isVisibleContinueButton = false;
protected override async void OnAppearing()
{
base.OnAppearing();
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");
}
@ -57,9 +59,26 @@ public partial class PageSelectMap : ContentPage
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));
}
@ -79,4 +98,17 @@ public partial class PageSelectMap : ContentPage
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