diff --git a/Qwirkle/QwirkleClassLibrary/Cell.cs b/Qwirkle/QwirkleClassLibrary/Cell.cs index 911ee73..88ad90b 100644 --- a/Qwirkle/QwirkleClassLibrary/Cell.cs +++ b/Qwirkle/QwirkleClassLibrary/Cell.cs @@ -5,8 +5,8 @@ namespace QwirkleClassLibrary; public class Cell { - private int x; - private int y; + private readonly int x; + private readonly int y; private Tile? tile = null; public Cell(int x, int y) diff --git a/Qwirkle/QwirkleClassLibrary/Game.cs b/Qwirkle/QwirkleClassLibrary/Game.cs index 3783c16..68360de 100644 --- a/Qwirkle/QwirkleClassLibrary/Game.cs +++ b/Qwirkle/QwirkleClassLibrary/Game.cs @@ -11,13 +11,16 @@ namespace QwirkleClassLibrary { public class Game : IPlayer, IRules { - private TileBag bag; + private readonly TileBag bag; public bool GameRunning { get; private set; } private Board board; public ReadOnlyCollection PlayerList => players.AsReadOnly(); private readonly List players = new(); + public ReadOnlyCollection ScoreList => scores.AsReadOnly(); + private readonly List scores = new(); + public Game() { bag = new TileBag(3); @@ -45,6 +48,7 @@ namespace QwirkleClassLibrary } players.Add(CreatePlayer(playerTag)); + scores.Add(new Score(players[players.Count-1])); return true; } @@ -61,13 +65,22 @@ namespace QwirkleClassLibrary return board; } - public void StartGame() + public bool StartGame() { - this.GameRunning = true; + if(players.Count>= 2 && players.Count < 5) + { + this.GameRunning = true; + return true; + } + return false; } public Player GetPlayingPlayer() { + if(GetPlayingPlayerPosition() == -1) + { + throw new ArgumentException(); + } return players[GetPlayingPlayerPosition()]; } @@ -104,8 +117,16 @@ namespace QwirkleClassLibrary public string SetFirstPlayer() { - players[0].IsPlaying = true; - return players[0].NameTag; + if (GameRunning == true) + { + players[0].IsPlaying = true; + return players[0].NameTag; + } + else + { + throw new ArgumentException("Game is not running"); + } + } public string SetNextPlayer() diff --git a/Qwirkle/QwirkleClassLibrary/Score.cs b/Qwirkle/QwirkleClassLibrary/Score.cs index 14b5763..50822f2 100644 --- a/Qwirkle/QwirkleClassLibrary/Score.cs +++ b/Qwirkle/QwirkleClassLibrary/Score.cs @@ -8,14 +8,20 @@ namespace QwirkleClassLibrary { public struct Score { - private int score; - private string playerTag; + private int score { get; set; } + public string playerTag { get; } public Score(Player p) { - score = 0; - playerTag = p.NameTag; + if (p == null) + { + throw new ArgumentException(); + } + else + { + score = 0; + playerTag = p.NameTag; + } } - } } diff --git a/Qwirkle/QwirkleClassLibrary/Tile.cs b/Qwirkle/QwirkleClassLibrary/Tile.cs index df68a5f..f6adb00 100644 --- a/Qwirkle/QwirkleClassLibrary/Tile.cs +++ b/Qwirkle/QwirkleClassLibrary/Tile.cs @@ -10,8 +10,8 @@ namespace QwirkleClassLibrary { public class Tile { - private Shape shape; - private Color color; + private readonly Shape shape; + private readonly Color color; public Tile(Shape sh, Color co) { shape = sh; diff --git a/Qwirkle/QwirkleClassLibrary/TileBag.cs b/Qwirkle/QwirkleClassLibrary/TileBag.cs index 9b16b4b..01ed06d 100644 --- a/Qwirkle/QwirkleClassLibrary/TileBag.cs +++ b/Qwirkle/QwirkleClassLibrary/TileBag.cs @@ -14,7 +14,7 @@ namespace QwirkleClassLibrary public TileBag(int nbSet) { - if (nbSet < 0 || nbSet < 3) + if (nbSet < 0 || nbSet > 3) { throw new ArgumentException(nbSet.ToString()); } @@ -35,7 +35,7 @@ namespace QwirkleClassLibrary public bool AddTileInBag(Tile tile) { - if (tiles == null) + if (tile == null) { return false; } diff --git a/Qwirkle/QwirkleConsoleApp/Properties/launchSettings.json b/Qwirkle/QwirkleConsoleApp/Properties/launchSettings.json new file mode 100644 index 0000000..c2bcc14 --- /dev/null +++ b/Qwirkle/QwirkleConsoleApp/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "QwirkleConsoleApp": { + "commandName": "Project" + }, + "WSL": { + "commandName": "WSL2", + "distributionName": "" + } + } +} \ No newline at end of file diff --git a/Qwirkle/TestBase/TestBoard.cs b/Qwirkle/TestBase/TestBoard.cs index 4466f57..3a58795 100644 --- a/Qwirkle/TestBase/TestBoard.cs +++ b/Qwirkle/TestBase/TestBoard.cs @@ -1,31 +1,62 @@ using QwirkleClassLibrary; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace TestBase; namespace TestBase { - public class TestBoard +public class TestBoard +{ + public static IEnumerable Data_Board() { - [Fact] - - public void TestConstructor() + yield return new object[] + { + true, + 1, + 2, + new Tile(Shape.Round, Color.Red) + }; + yield return new object[] { - List c = new List(); - for (int i = 0; i < 12; i++) - { - for (int j = 0; j < 12; j++) - { - Cell localcell = new(i, j); - c.Add(localcell); - } - } - Board b = new Board(); - Assert.NotNull(c); - Assert.Equal(c, b.GetCells()); + false, + -5, + 9999, + new Tile(Shape.Round, Color.Red) + }; + } + [Theory] + [MemberData(nameof(Data_Board))] + public void Test_BoardAddSolo(bool except, int x, int y, Tile t) + { + + Board b = new Board(); + + if (!except) + { + Assert.False(b.AddTileInCell(x, y, t)); + return; + } + Assert.True(b.AddTileInCell(x, y, t)); } + + public static IEnumerable Data_BoardDouble() + { + yield return new object[] + { + 1, + 2, + new Tile(Shape.Round, Color.Red) + }; + } + + [Theory] + [MemberData(nameof(Data_BoardDouble))] + public void Test_BoardFree(int x, int y, Tile t) + { + Board board = new Board(); + board.AddTileInCell(x, y, t); + Assert.False(board.AddTileInCell(x,y, t)); + } + } + diff --git a/Qwirkle/TestBase/TestGame.cs b/Qwirkle/TestBase/TestGame.cs new file mode 100644 index 0000000..121e8de --- /dev/null +++ b/Qwirkle/TestBase/TestGame.cs @@ -0,0 +1,127 @@ +using QwirkleClassLibrary; +namespace TestBase; + +public class TestGame +{ + + + [Theory] + [InlineData(true, false, "testt")] + [InlineData(false, false, "testt")] + public void Test_GameAddPlayerIngame(bool result, bool gamestate, string p) + { + Game game = new Game(); + + if (!result) { + game.AddPlayerInGame(p); + Assert.False(game.AddPlayerInGame(p)); + } + else + { + Assert.True(game.AddPlayerInGame(p)); + } + + if (gamestate) + { + Assert.False(game.AddPlayerInGame(p)); + } + + + + + + } + + [Theory] + [InlineData(false, null)] + [InlineData(true, "test")] + public void Test_GameAddPlayerIngame2(bool result, string p) + { + Game game = new Game(); + + if (!result) + { + Assert.False(game.AddPlayerInGame(p)); + } + + for (int i = 0; i < 4; i++) + { + string name = p + i; + game.AddPlayerInGame(name); + } + Assert.False(game.AddPlayerInGame(p)); + + } + + [Theory] + [InlineData("test")] + public void Test_GameCreatePlayers(string p) + { + Game game = new Game(); + Player player = new Player(p); + Assert.Equal(game.CreatePlayer(p).NameTag, player.NameTag); + } + + [Theory] + [InlineData(true, "test1", "test2")] + [InlineData(false, "test1", "test2")] + public void Test_GameState(bool result, string p1, string p2) + { + Game game = new Game(); + + if (!result) + { + game.StartGame(); + Assert.False(game.GameRunning); + } + game.AddPlayerInGame(p1); + game.AddPlayerInGame(p2); + game.StartGame(); + + Assert.True(game.GameRunning); + } + + + [Theory] + [InlineData(true, "test1", "test2", "test3")] + [InlineData(false, "test1", "test2", "test3")] + public void Test_GameGetPlayingPlayerPosition(bool result, string p1, string p2, string p3) + { + Game game = new Game(); + game.AddPlayerInGame(p1); + game.AddPlayerInGame(p2); + game.AddPlayerInGame(p3); + + if (!result) + { + Assert.Equal(-1, game.GetPlayingPlayerPosition()); + return; + } + game.StartGame(); + game.SetFirstPlayer(); + Assert.Equal(0, game.GetPlayingPlayerPosition()); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Test_GameGetPlaylingPlayer(bool result) + { + Game game = new Game(); + game.AddPlayerInGame("patrick"); + game.AddPlayerInGame("jean"); + if (!result) + { + Assert.Throws(() => game.GetPlayingPlayer()); + } + game.StartGame(); + game.SetFirstPlayer(); + + Assert.Equal(game.PlayerList[0], game.GetPlayingPlayer()); + + } + + + +} + diff --git a/Qwirkle/TestBase/TestPlayer.cs b/Qwirkle/TestBase/TestPlayer.cs index a619600..37b92e5 100644 --- a/Qwirkle/TestBase/TestPlayer.cs +++ b/Qwirkle/TestBase/TestPlayer.cs @@ -1,8 +1,7 @@ using QwirkleClassLibrary; +namespace TestBase; -namespace TestBase -{ - public class TestPlayers +public class TestPlayers { [Theory] [InlineData(true, "Mathis")] @@ -61,5 +60,4 @@ namespace TestBase } Assert.True(r); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/Qwirkle/TestBase/TestScore.cs b/Qwirkle/TestBase/TestScore.cs new file mode 100644 index 0000000..7f1fd02 --- /dev/null +++ b/Qwirkle/TestBase/TestScore.cs @@ -0,0 +1,30 @@ +using QwirkleClassLibrary; +namespace TestBase; + +public class TestScore +{ + [Theory] + [InlineData(false)] + //[InlineData(true)] + public void Test_CellScoreConstructor(bool except) + { + /*if (!except) + { + Assert.Throws(() => new Score(null)); + return; + }*/ + Player p = new Player("test"); + Score score = new Score(p); + Assert.True(true); + } + + + + + + + + + +} + diff --git a/Qwirkle/TestBase/TestTileBag.cs b/Qwirkle/TestBase/TestTileBag.cs index c06f72d..350f0f6 100644 --- a/Qwirkle/TestBase/TestTileBag.cs +++ b/Qwirkle/TestBase/TestTileBag.cs @@ -16,7 +16,7 @@ public class TestTileBag return; } TileBag bag = new TileBag(nbset); - Assert.Equal(bag.TilesBag.Count, nbset); + Assert.Equal(bag.TilesBag.Count, nbset*36); } [Fact] @@ -33,5 +33,23 @@ public class TestTileBag } } + + [Fact] + public void Test_RemoveTileInBag() + { + Tile t = null; + Tile tok = new(Shape.Club, Color.Green); + TileBag bag = new TileBag(2); + bag.AddTileInBag(tok); + + if (bag.RemoveTileInBag(t) == false) + { + Assert.True(bag.RemoveTileInBag(tok)); + + } + + } + + } diff --git a/Qwirkle/cm6(suite).cs b/Qwirkle/cm6(suite).cs new file mode 100644 index 0000000..b19f94c --- /dev/null +++ b/Qwirkle/cm6(suite).cs @@ -0,0 +1,35 @@ +public interface IDisplayer +{ + void OnGameStart(Board board); + void OnPlayerNotified(Player player); + void OnMoveChosen(Player player, int row, int col); + void OnValidMove(Player player, Board board, int row, int col, bool isValid); + void OnBoardChanged(Board board); +} + +public class ConsoleDisplayer : IDisplayer +{ + public void OnGameStarted(Board board) + { + Console.WriteLine("Game has started !"); + DisplayBoard(board); + } + + public void DisplayBoard(Board board) + { + for(int row = 0; row < board.NbRows; row++) + { + for(int col = 0; col < board.NbCols; col++) + { + var playerSymbol = board[row, col] ?.Player == 1 ? "X" : "O"; + Console.Write($"{playerSymbol} ") + } + Console.WriteLine(); + } + } +} + + +// program.cs + +OnGameStarted += _ => Console.WriteLine("Game has started !"); // j'ai pas compris mais ça à l'air complètement fumé \ No newline at end of file diff --git a/Qwirkle/cm6.cs b/Qwirkle/cm6.cs new file mode 100644 index 0000000..a030e06 --- /dev/null +++ b/Qwirkle/cm6.cs @@ -0,0 +1,128 @@ +// Cours sur les évènements + +/* +Pour la faire courte, y a 3 possibilités pour les affichages : +- les Console.WriteLine qui sont absolument interdits dans les classes de logique (Game, Board, Rules, Player) +- l'implémentations d'une interface IDisplayer qui permet de définir des méthodes qui seront appelées par les classes de logique +- Définition du type délégué (delegate) => ça prend un board, ça rend rien + - + +*/ + + +public class Game // Game.cs file +{ + public /*delegate*/ event void GameStarted(); // c'est pas une méthode, c'est un type de méthode !!! + // le event est une propriété qui permet de s'abonner à un évènement : elle empêche de faire = + + + public event EventHandler GameStarted; + protected virtual void OnGameStarted() + { + GameStarted?.Invoke(this, EventArgs.Empty); + } + + private GameStarted onGameStarted; + + private Board board { get; init; } // je sais pas ce que fait le init + + private IRules Rules { get; init; } + + private Player Player1 { get; init; } + private Player Player2 { get; init; } + + private IDisplayer displayer + + public Game(Irules rules, Player player1, Player player2) + { + Player1 = player1; + Player2 = player2; + Rules = rules; + Board = rules.InitBoard(); + } + + { + + } + + public void start() + { + displayer.OnGameStart(Board); + + Console.WriteLine("Game started !"); + while(true) + { + // Get next player + Player nextPlayer = Rules.GetNextPlayer(Board) == 1 ? Player1 : Player2; + // displayer.OnPlayerNotified(nextPlayer); + onGameStarted(board); + + // Notify player to make a move + (int chosenRow, int chosenCol) = nextPlayer.ChooseMove(Board, Rules); + displayer.OnMoveChosen(nextPlayer, chosenRow, chosenCol); + + // If move is valid (check with rules) + if(Rules.IsValidMove(Board, chosenRow, chosenCol, nextPlayer.Id)) + { + // true => modify board + Board.InsertPiece(chosenRow, chosenCol, nextPlayer.Id); + displayer.OnValidMove(nextPlayer, Board, chosenRow, chosenCol, true); + + displayer.OnGameOver(Board, nextPlayer, Rules); + + // is game over? (check with rules) + if(Rules.IsGameOver(Board, chosenRow, chosenCol, out int winner, out Case[] winningPlaces)) + { + Console.WriteLine($"Player {winner} won the game !"); + + for(int row = 0; row < Board.NbRows; row++) + { + for(int col = 0; col < Board.NbCols; col++) + { + Console.Write($"{playerSymbol} ") + } + Console.WriteLine(); + } + + return; + } + } + // gets the winner, winning places, return + // false => nothing + } + + } +} + +public abstract class Player // Player.cs file +{ + public string Name { get; private set; } + + public int Id { get; private init; } + + public Player(string name, int id) + { + Id = id; + Name = name; + } + + public abstract (int row, int col) ChooseMove(Board board, IRules rules); +} + +public class RandomPlayer : Player // RandomPlayer.cs file +{ + public RandomPlayer(int id) : base(id, "Jérôme") + { + } + + public static Random random = new Random(); + + public override (int row, int col) ChooseMove(Board board, IRules rules) + { + var moves = rules.GetPossibleMoves(board, Id); + var chosenMoveId = random.Next(0, moves.Count()); + Case chosenCase = moves.ElementAt(chosenMoveId); + + return (chosenCase.Row, chosenCase.Col); + } +} \ No newline at end of file