|
|
@ -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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|