Boum le bibi

master
Jules LASCRET 11 months ago
parent 1009c742f8
commit 1073b2d802

@ -53,7 +53,7 @@ namespace QwirkleClassLibrary.Boards
{ {
for (int b = 0; b < Columns; b++) for (int b = 0; b < Columns; b++)
{ {
Cell localcell = new(a, b); Cell localcell = new(b, a);
cells.Add(localcell); cells.Add(localcell);
} }
} }

@ -11,39 +11,31 @@ using static System.Formats.Asn1.AsnWriter;
namespace QwirkleClassLibrary.Games namespace QwirkleClassLibrary.Games
{ {
[DataContract] [DataContract]
public class Game : IPlayer, IRules, INotifyPropertyChanged public class Game : IPlayer, IRules, INotifyPropertyChanged
{ {
[DataMember] [DataMember] private TileBag? bag = null;
private TileBag? bag = null;
[DataMember] [DataMember] public bool GameRunning { get; set; }
public bool GameRunning { get; set; }
[DataMember] [DataMember] private Board board = new(17, 14);
private Board board = new(17, 14);
public bool PlayerSwapping { get; set; } public bool PlayerSwapping { get; set; }
public Board Board => board; public Board Board => board;
public ReadOnlyCollection<Player> PlayerList => players.AsReadOnly(); public ReadOnlyCollection<Player> PlayerList => players.AsReadOnly();
[DataMember] [DataMember] private readonly List<Player> players = [];
private readonly List<Player> players = [];
[DataMember] [DataMember] private readonly Dictionary<string, int> scoreBoard = new Dictionary<string, int>();
private readonly Dictionary<string, int> scoreBoard = new Dictionary<string, int>();
public ReadOnlyDictionary<string, int> ScoreBoard => scoreBoard.AsReadOnly(); public ReadOnlyDictionary<string, int> ScoreBoard => scoreBoard.AsReadOnly();
[DataMember] [DataMember] private readonly ObservableCollection<KeyValuePair<string, int>> observableScoreBoard = [];
private readonly ObservableCollection<KeyValuePair<string, int>> observableScoreBoard = [];
public ReadOnlyObservableCollection<KeyValuePair<string, int>> ObservableScoreBoard => public ReadOnlyObservableCollection<KeyValuePair<string, int>> ObservableScoreBoard =>
new(observableScoreBoard); new(observableScoreBoard);
[DataMember] [DataMember] private readonly List<Cell> cellUsed = [];
private readonly List<Cell> cellUsed = [];
public ReadOnlyCollection<Cell> CellsUsed => cellUsed.AsReadOnly(); public ReadOnlyCollection<Cell> CellsUsed => cellUsed.AsReadOnly();
@ -104,9 +96,11 @@ namespace QwirkleClassLibrary.Games
if (playersTag.Count <= 1 || playersTag.Count > 4) if (playersTag.Count <= 1 || playersTag.Count > 4)
{ {
playersTag.Clear(); playersTag.Clear();
OnPlayerNotified(new AddPlayerNotifiedEventArgs("ERROR : It takes a minimum of 2 players and a maximum of 4 players to start a game.")); OnPlayerNotified(new AddPlayerNotifiedEventArgs(
"ERROR : It takes a minimum of 2 players and a maximum of 4 players to start a game."));
return false; return false;
} }
for (int i = playersTag.Count - 1; i >= 0; i--) for (int i = playersTag.Count - 1; i >= 0; i--)
{ {
if (!CheckPlayerTag(playersTag, i)) if (!CheckPlayerTag(playersTag, i))
@ -131,7 +125,8 @@ namespace QwirkleClassLibrary.Games
{ {
if (string.IsNullOrWhiteSpace(playersTag[pos])) if (string.IsNullOrWhiteSpace(playersTag[pos]))
{ {
OnPlayerNotified(new AddPlayerNotifiedEventArgs("ERROR with " + (pos + 1) + " entry : The name is null or white space.")); OnPlayerNotified(new AddPlayerNotifiedEventArgs("ERROR with " + (pos + 1) +
" entry : The name is null or white space."));
return false; return false;
} }
@ -148,7 +143,6 @@ namespace QwirkleClassLibrary.Games
new AddPlayerNotifiedEventArgs("ERROR with " + (pos + 1) + " entry : Name alreay taken")); new AddPlayerNotifiedEventArgs("ERROR with " + (pos + 1) + " entry : Name alreay taken"));
return false; return false;
} }
} }
return true; return true;
@ -170,13 +164,19 @@ namespace QwirkleClassLibrary.Games
/// Returns the Board of the game /// Returns the Board of the game
/// </summary> /// </summary>
/// <returns>Board</returns> /// <returns>Board</returns>
public Board? GetBoard() { return board; } public Board? GetBoard()
{
return board;
}
/// <summary> /// <summary>
/// Returns the tile bag of the game /// Returns the tile bag of the game
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public TileBag? GetTileBag() { return bag; } public TileBag? GetTileBag()
{
return bag;
}
/// <summary> /// <summary>
/// Creates a Board with a number of columns and rows /// Creates a Board with a number of columns and rows
@ -238,6 +238,7 @@ namespace QwirkleClassLibrary.Games
{ {
throw new ArgumentException("No player currently playing !"); throw new ArgumentException("No player currently playing !");
} }
return players[GetPlayingPlayerPosition()]; return players[GetPlayingPlayerPosition()];
} }
@ -254,6 +255,7 @@ namespace QwirkleClassLibrary.Games
return i; return i;
} }
} }
return -1; return -1;
} }
@ -312,11 +314,10 @@ namespace QwirkleClassLibrary.Games
startingPlayer = player; startingPlayer = player;
} }
} }
startingPlayer!.IsPlaying = true; startingPlayer!.IsPlaying = true;
OnNextPlayer(new NextPlayerNotifiedEventArgs(players[0])); OnNextPlayer(new NextPlayerNotifiedEventArgs(players[0]));
return startingPlayer.NameTag; return startingPlayer.NameTag;
} }
/// <summary> /// <summary>
@ -354,11 +355,13 @@ namespace QwirkleClassLibrary.Games
OnPlaceTile(new PlaceTileNotifiedEventArgs(tile, "you are swapping, you can't place tile !")); OnPlaceTile(new PlaceTileNotifiedEventArgs(tile, "you are swapping, you can't place tile !"));
return false; return false;
} }
if (!TileInbag(player, tile)) if (!TileInbag(player, tile))
{ {
OnPlaceTile(new PlaceTileNotifiedEventArgs(tile, "you can't play")); OnPlaceTile(new PlaceTileNotifiedEventArgs(tile, "you can't play"));
return false; return false;
} }
if (!IsMoveCorrect(tile, x, y, board!)) return false; if (!IsMoveCorrect(tile, x, y, board!)) return false;
if (board!.AddTileInCell(x, y, tile)) if (board!.AddTileInCell(x, y, tile))
{ {
@ -446,12 +449,12 @@ namespace QwirkleClassLibrary.Games
{ {
players[GetPlayingPlayerPosition()].AddTileToPlayer(t); players[GetPlayingPlayerPosition()].AddTileToPlayer(t);
} }
}
}
/// <summary> /// <summary>
/// Extension of IsMoveCorrect to check beyond the surrounding cells of the cell where the tile is placed /// Extension of IsMoveCorrect to check beyond the surrounding cells of the cell where the tile is placed
/// </summary> /// </summary>
/// <param name="previousTilesFound"></param>
/// <param name="tile"></param> /// <param name="tile"></param>
/// <param name="x"></param> /// <param name="x"></param>
/// <param name="y"></param> /// <param name="y"></param>
@ -459,12 +462,23 @@ namespace QwirkleClassLibrary.Games
/// <param name="dy">used to get the direction on the y axis</param> /// <param name="dy">used to get the direction on the y axis</param>
/// <param name="b"></param> /// <param name="b"></param>
/// <returns>bool</returns> /// <returns>bool</returns>
public bool CheckExtendedSurroundingCells(Tile tile, int x, int y, int dx, int dy, Board b) public bool CheckExtendedSurroundingCells(ref bool previousTilesFound, Tile tile, int x, int y, int dx, int dy,
Board b)
{ {
for (int i = 1; i < 7; i++) for (int i = 1; i < 7; i++)
{ {
var extendedCell = b.GetCell(x + i * dx, y + i * dy); var extendedCell = b.GetCell(x + i * dx, y + i * dy);
if (cellUsed.Count == 0)
{
previousTilesFound = true;
}
if (cellUsed.Contains(extendedCell))
{
previousTilesFound = true;
}
if (extendedCell?.Tile == null) if (extendedCell?.Tile == null)
{ {
break; break;
@ -472,13 +486,15 @@ namespace QwirkleClassLibrary.Games
if (extendedCell.Tile.GetColor != tile.GetColor && extendedCell.Tile.GetShape != tile.GetShape) if (extendedCell.Tile.GetColor != tile.GetColor && extendedCell.Tile.GetShape != tile.GetShape)
{ {
OnPlaceTile(new PlaceTileNotifiedEventArgs(tile, " : Color / Shape does not match with the surrounding tiles !")); OnPlaceTile(new PlaceTileNotifiedEventArgs(tile,
" : Color / Shape does not match with the surrounding tiles !"));
return false; return false;
} }
if (extendedCell.Tile.GetColor == tile.GetColor && extendedCell.Tile.GetShape == tile.GetShape) if (extendedCell.Tile.GetColor == tile.GetColor && extendedCell.Tile.GetShape == tile.GetShape)
{ {
OnPlaceTile(new PlaceTileNotifiedEventArgs(tile, " : Tile already placed on the same line / column !")); OnPlaceTile(new PlaceTileNotifiedEventArgs(tile,
" : Tile already placed on the same line / column !"));
return false; return false;
} }
@ -527,6 +543,7 @@ namespace QwirkleClassLibrary.Games
{ {
return x == x1; return x == x1;
} }
if (y1 == y2) if (y1 == y2)
{ {
return y == y1; return y == y1;
@ -534,6 +551,54 @@ namespace QwirkleClassLibrary.Games
return false; return false;
} }
public bool CheckWrongCompletedLines(Tile tile, int x, int y, int dx, int dy, Board b, ref List<Tile> checkdoubles)
{
int nbTiles = 1;
for (int i = 1; i < 7; i++)
{
var extendedCell = b.GetCell(x + i * dx, y + i * dy);
var extendedCell2 = b.GetCell(x - i * dx, y - i * dy);
if (extendedCell?.Tile == null && extendedCell2?.Tile == null)
{
break;
}
if (extendedCell?.Tile != null)
{
nbTiles++;
foreach (var t in checkdoubles)
{
if (t.CompareTo(extendedCell.Tile) == 0)
{
return false;
}
}
checkdoubles.Add(extendedCell.Tile);
}
if (extendedCell2?.Tile != null)
{
nbTiles++;
foreach (var t in checkdoubles)
{
if (t.CompareTo(extendedCell2.Tile) == 0)
{
return false;
}
}
checkdoubles.Add(extendedCell2.Tile);
}
}
return nbTiles <= 6;
}
/// <summary> /// <summary>
/// Main method to check if the move the player is trying to make is correct /// Main method to check if the move the player is trying to make is correct
@ -545,6 +610,10 @@ namespace QwirkleClassLibrary.Games
/// <returns>bool</returns> /// <returns>bool</returns>
public bool IsMoveCorrect(Tile t, int x, int y, Board b) public bool IsMoveCorrect(Tile t, int x, int y, Board b)
{ {
bool previousTilesFound = false;
var checkDoubles = new List<Tile>();
if (!b.HasOccupiedCase()) if (!b.HasOccupiedCase())
{ {
return true; return true;
@ -572,7 +641,8 @@ namespace QwirkleClassLibrary.Games
if (cell.Tile.GetColor != t.GetColor && cell.Tile.GetShape != t.GetShape) if (cell.Tile.GetColor != t.GetColor && cell.Tile.GetShape != t.GetShape)
{ {
OnPlaceTile(new PlaceTileNotifiedEventArgs(t, " : Colors / Shapes do not match with the surrounding tiles !")); OnPlaceTile(new PlaceTileNotifiedEventArgs(t,
" : Colors / Shapes do not match with the surrounding tiles !"));
return false; return false;
} }
@ -586,26 +656,38 @@ namespace QwirkleClassLibrary.Games
var dx = cell.GetX - x; var dx = cell.GetX - x;
var dy = cell.GetY - y; var dy = cell.GetY - y;
if (!CheckExtendedSurroundingCells(t, x, y, dx, dy, b)) if (!CheckExtendedSurroundingCells(ref previousTilesFound, t, x, y, dx, dy, b))
{ {
return false; return false;
} }
if (!CheckWrongCompletedLines(t, x, y, dx, dy, b, ref checkDoubles))
{
OnPlaceTile(new PlaceTileNotifiedEventArgs(t, " : You can't complete this line ! (More than 6 tiles / same tiles on the line)"));
return false;
}
} }
if (!CheckTilesInLine(cellUsed, b, x, y)) if (!CheckTilesInLine(cellUsed, b, x, y))
{ {
OnPlaceTile(new PlaceTileNotifiedEventArgs(t, "isn't on the same line as the ones previously placed !")); OnPlaceTile(new PlaceTileNotifiedEventArgs(t,
"isn't on the same line as the ones previously placed !"));
return false; return false;
} }
if (surroundingCells.All(cell => cell?.Tile == null)) if (surroundingCells.All(cell => cell?.Tile == null))
{ {
OnPlaceTile(new PlaceTileNotifiedEventArgs(t, " : You can't place a tile that isn't adjacent to another one !")); OnPlaceTile(new PlaceTileNotifiedEventArgs(t,
" : You can't place a tile that isn't adjacent to another one !"));
return false; return false;
} }
return true; if (previousTilesFound) return true;
OnPlaceTile(new PlaceTileNotifiedEventArgs(t,
" : You must place your tile next / on the same line as the ones previously placed !"));
return false;
} }
@ -654,7 +736,8 @@ namespace QwirkleClassLibrary.Games
cellsX = cellsY = -1; cellsX = cellsY = -1;
} }
score += cellsPlayed.Sum(cell => CalculateAdjacentScore(cell, b, cellsPlayed, cellsX, cellsY, ref nbCellsInLine)); score += cellsPlayed.Sum(cell =>
CalculateAdjacentScore(cell, b, cellsPlayed, cellsX, cellsY, ref nbCellsInLine));
if (nbCellsInLine == 6) if (nbCellsInLine == 6)
{ {
@ -663,7 +746,6 @@ namespace QwirkleClassLibrary.Games
if (!scoreBoard.TryAdd(player.NameTag, score)) if (!scoreBoard.TryAdd(player.NameTag, score))
{ {
scoreBoard.TryGetValue(player.NameTag, out int scoreold); scoreBoard.TryGetValue(player.NameTag, out int scoreold);
SetScoreBoard(player.NameTag, score + scoreold); SetScoreBoard(player.NameTag, score + scoreold);
} }
@ -681,7 +763,8 @@ namespace QwirkleClassLibrary.Games
/// <param name="cellsY"></param> /// <param name="cellsY"></param>
/// <param name="nbCellsInLine"></param> /// <param name="nbCellsInLine"></param>
/// <returns>int</returns> /// <returns>int</returns>
public int CalculateAdjacentScore(Cell cell, Board b, ReadOnlyCollection<Cell> cellsPlayed, int cellsX, int cellsY, ref int nbCellsInLine) public int CalculateAdjacentScore(Cell cell, Board b, ReadOnlyCollection<Cell> cellsPlayed, int cellsX,
int cellsY, ref int nbCellsInLine)
{ {
int score = 0; int score = 0;
@ -697,7 +780,8 @@ namespace QwirkleClassLibrary.Games
foreach (var adjacentCell in surroundingCells) foreach (var adjacentCell in surroundingCells)
{ {
if (adjacentCell?.Tile == null || cellsPlayed.Contains(adjacentCell) || checkedSurroundingCells.Contains(adjacentCell)) if (adjacentCell?.Tile == null || cellsPlayed.Contains(adjacentCell) ||
checkedSurroundingCells.Contains(adjacentCell))
{ {
continue; continue;
} }
@ -705,7 +789,8 @@ namespace QwirkleClassLibrary.Games
int dx = adjacentCell.GetX - cell.GetX; int dx = adjacentCell.GetX - cell.GetX;
int dy = adjacentCell.GetY - cell.GetY; int dy = adjacentCell.GetY - cell.GetY;
score += CalculateLineScore(cellsPlayed, cell, new Tuple<int, int>(dx, dy), b, new Tuple<int, int>(cellsX, cellsY), ref nbCellsInLine); score += CalculateLineScore(cellsPlayed, cell, new Tuple<int, int>(dx, dy), b,
new Tuple<int, int>(cellsX, cellsY), ref nbCellsInLine);
checkedSurroundingCells.Add(adjacentCell); checkedSurroundingCells.Add(adjacentCell);
} }
@ -723,7 +808,8 @@ namespace QwirkleClassLibrary.Games
/// <param name="orientation"></param> /// <param name="orientation"></param>
/// <param name="nbCellsInLine"></param> /// <param name="nbCellsInLine"></param>
/// <returns>int</returns> /// <returns>int</returns>
public int CalculateLineScore(ReadOnlyCollection<Cell> cellsPlayed, Cell cell, Tuple<int, int> direction, Board b, Tuple<int, int> orientation, ref int nbCellsInLine) public int CalculateLineScore(ReadOnlyCollection<Cell> cellsPlayed, Cell cell, Tuple<int, int> direction,
Board b, Tuple<int, int> orientation, ref int nbCellsInLine)
{ {
int score = 0; int score = 0;
@ -744,7 +830,8 @@ namespace QwirkleClassLibrary.Games
score++; score++;
} }
if (direction.Item1 == 0 && orientation.Item1 == -1 && orientation.Item2 != -1 || direction.Item2 == 0 && orientation.Item2 == -1 && orientation.Item1 != -1) if (direction.Item1 == 0 && orientation.Item1 == -1 && orientation.Item2 != -1 ||
direction.Item2 == 0 && orientation.Item2 == -1 && orientation.Item1 != -1)
{ {
score += 1; score += 1;
} }
@ -770,7 +857,6 @@ namespace QwirkleClassLibrary.Games
playerTilesBagPos.Add(i); playerTilesBagPos.Add(i);
} }
} }
} }
return playerTilesBagPos; return playerTilesBagPos;
@ -813,7 +899,8 @@ namespace QwirkleClassLibrary.Games
{ {
List<int> playerTilesBagPos = CheckTilesBag(); List<int> playerTilesBagPos = CheckTilesBag();
if (playerTilesBagPos.Count != 0 && !CheckPlacementPossibilities(playerTilesBagPos) || bag!.TilesBag!.Count == 0 && players[GetPlayingPlayerPosition()].Tiles.Count == 0) if (playerTilesBagPos.Count != 0 && !CheckPlacementPossibilities(playerTilesBagPos) ||
bag!.TilesBag!.Count == 0 && players[GetPlayingPlayerPosition()].Tiles.Count == 0)
{ {
OnEndOfGame(new EndOfGameNotifiedEventArgs(player)); OnEndOfGame(new EndOfGameNotifiedEventArgs(player));
GameRunning = false; GameRunning = false;
@ -838,7 +925,6 @@ namespace QwirkleClassLibrary.Games
public void SetScoreBoard(string name, int score) public void SetScoreBoard(string name, int score)
{ {
if (!scoreBoard.TryAdd(name, score)) if (!scoreBoard.TryAdd(name, score))
{ {
scoreBoard[name] = score; scoreBoard[name] = score;
@ -849,6 +935,7 @@ namespace QwirkleClassLibrary.Games
{ {
observableScoreBoard.Add(item); observableScoreBoard.Add(item);
} }
OnPropertyChanged(nameof(ObservableScoreBoard)); OnPropertyChanged(nameof(ObservableScoreBoard));
} }
} }

@ -17,7 +17,7 @@ namespace QwirkleClassLibrary.Games
bool IsMoveCorrect(Tile t, int x, int y, Board b); bool IsMoveCorrect(Tile t, int x, int y, Board b);
bool CheckExtendedSurroundingCells(Tile tile, int x, int y, int dx, int dy, Board b); bool CheckExtendedSurroundingCells(ref bool previousTilesFound, Tile tile, int x, int y, int dx, int dy, Board b);
bool CheckTilesInLine(List<Cell> cells, Board b, int x, int y); bool CheckTilesInLine(List<Cell> cells, Board b, int x, int y);

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace QwirkleClassLibrary.Tiles namespace QwirkleClassLibrary.Tiles
{ {
[DataContract] [DataContract]
public class Tile public class Tile : IComparable
{ {
[DataMember] [DataMember]
private readonly Shape shape; private readonly Shape shape;
@ -63,5 +63,23 @@ namespace QwirkleClassLibrary.Tiles
{ {
return color.ToString() + " " + shape.ToString(); return color.ToString() + " " + shape.ToString();
} }
public int CompareTo(object? obj)
{
if (obj == null) return 1;
var otherTile = obj as Tile;
if (otherTile != null)
{
if (color == otherTile.color)
{
return shape.CompareTo(otherTile.shape);
}
return color.CompareTo(otherTile.color);
}
throw new ArgumentException("Object is not a Tile");
}
} }
} }
Loading…
Cancel
Save