@ -7,43 +7,37 @@ using QwirkleClassLibrary.Events;
using QwirkleClassLibrary.Players ;
using QwirkleClassLibrary.Players ;
using System.ComponentModel ;
using System.ComponentModel ;
using System.Runtime.CompilerServices ;
using System.Runtime.CompilerServices ;
using static System . Formats . Asn1 . AsnWriter ;
namespace QwirkleClassLibrary.Games
namespace QwirkleClassLibrary.Games
{
{
/// <summary>
/// This is our main class for the Qwirkle application, taking care of the good efficiency of the game.
/// </summary>
[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 +98,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 ) )
@ -126,12 +122,18 @@ namespace QwirkleClassLibrary.Games
OnPlayerNotified ( new AddPlayerNotifiedEventArgs ( "Players were correctly added." ) ) ;
OnPlayerNotified ( new AddPlayerNotifiedEventArgs ( "Players were correctly added." ) ) ;
return true ;
return true ;
}
}
/// <summary>
/// This function is used to check if the player name that the user has entered meets the criteria set by the application.
/// </summary>
/// <param name="playersTag">A list that contains all the names entered when the game was started.</param>
/// <param name="pos">The position of the name we want to check in this list.</param>
/// <returns>boolean true if everything is okay, false if there was a problem in the player name.</returns>
public bool CheckPlayerTag ( List < string > playersTag , int pos )
public bool CheckPlayerTag ( List < string > playersTag , int pos )
{
{
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 +150,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 +171,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 +245,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 +262,7 @@ namespace QwirkleClassLibrary.Games
return i ;
return i ;
}
}
}
}
return - 1 ;
return - 1 ;
}
}
@ -316,7 +325,6 @@ namespace QwirkleClassLibrary.Games
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,13 +362,15 @@ 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 ( board ! . AddTileInCell ( x , y , tile ) )
if ( ! IsMoveCorrect ( tile , x , y , board ) ) return false ;
if ( board . AddTileInCell ( x , y , tile ) )
{
{
AddCellUsed ( board . GetCell ( x , y ) ) ;
AddCellUsed ( board . GetCell ( x , y ) ) ;
return player . RemoveTileToPlayer ( tile ) ;
return player . RemoveTileToPlayer ( tile ) ;
@ -446,12 +456,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,26 +469,39 @@ 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 ( extendedCell ? . Tile = = null )
if ( cellUsed . Count = = 0 )
{
previousTilesFound = true ;
}
if ( cellUsed . Contains ( extendedCell ! ) )
{
previousTilesFound = true ;
}
if ( extendedCell ? . Tile ! = = null ! )
{
{
break ;
break ;
}
}
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 +550,7 @@ namespace QwirkleClassLibrary.Games
{
{
return x = = x1 ;
return x = = x1 ;
}
}
if ( y1 = = y2 )
if ( y1 = = y2 )
{
{
return y = = y1 ;
return y = = y1 ;
@ -536,13 +560,62 @@ namespace QwirkleClassLibrary.Games
}
}
/// <summary>
/// <summary>
/// Main method to check if the move the player is trying to make is correct
/// Check that there isn't any same tile on a said line when a tile is forming a line
/// </summary>
/// </summary>
/// <param name="t"></param>
/// <param name="t1"></param>
/// <param name="nbTiles"></param>
/// <param name="checkdoubles"></param>
/// <returns></returns>
public static bool CheckTileInCompletedLines ( Tile ? t1 , ref int nbTiles , ref List < Tile > checkdoubles )
{
if ( t1 ! ! = null ! )
{
nbTiles + + ;
if ( checkdoubles . Any ( t = > t . CompareTo ( t1 ) = = 0 ) )
{
return false ;
}
checkdoubles . Add ( t1 ) ;
}
return true ;
}
/// <summary>
/// Check if the line is completed with the tile placed
/// </summary>
/// <param name="tile"></param>
/// <param name="x"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="y"></param>
/// <param name="dx"></param>
/// <param name="dy"></param>
/// <param name="b"></param>
/// <param name="b"></param>
/// <returns>bool</returns>
/// <param name="checkdoubles"></param>
/// <returns></returns>
public static bool CheckWrongCompletedLines ( 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 ( ! CheckTileInCompletedLines ( extendedCell ? . Tile , ref nbTiles , ref checkdoubles ) ) return false ;
if ( ! CheckTileInCompletedLines ( extendedCell2 ? . Tile , ref nbTiles , ref checkdoubles ) ) return false ;
}
return nbTiles < = 6 ;
}
public bool IsMoveCorrect ( Tile t , int x , int y , Board b )
public bool IsMoveCorrect ( Tile t , int x , int y , Board b )
{
{
if ( ! b . HasOccupiedCase ( ) )
if ( ! b . HasOccupiedCase ( ) )
@ -550,9 +623,10 @@ namespace QwirkleClassLibrary.Games
return true ;
return true ;
}
}
if ( b . GetCell ( x , y ) ! . Tile ! = null )
if ( b . GetCell ( x , y ) ! . Tile ! ! = null ! )
{
{
OnPlaceTile ( new PlaceTileNotifiedEventArgs ( t , " : Cell already used !" ) ) ;
OnPlaceTile ( new PlaceTileNotifiedEventArgs ( t , " : Cell already used !" ) ) ;
return false ;
}
}
var surroundingCells = new List < Cell ? >
var surroundingCells = new List < Cell ? >
@ -563,49 +637,67 @@ namespace QwirkleClassLibrary.Games
b . GetCell ( x , y - 1 )
b . GetCell ( x , y - 1 )
} ;
} ;
if ( surroundingCells . All ( cell = > cell ? . Tile ! = = null ! ) )
{
OnPlaceTile ( new PlaceTileNotifiedEventArgs ( t ,
" : You can't place a tile that isn't adjacent to another one !" ) ) ;
return false ;
}
return IsTilePlacementCorrect ( t , x , y , b , surroundingCells ) ;
}
public bool IsTilePlacementCorrect ( Tile t , int x , int y , Board b , List < Cell ? > surroundingCells )
{
bool previousTilesFound = false ;
var checkDoubles = new List < Tile > ( ) ;
foreach ( var cell in surroundingCells )
foreach ( var cell in surroundingCells )
{
{
if ( cell ? . Tile = = null )
if ( cell ? . Tile ! = = null ! )
{
{
continue ;
continue ;
}
}
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 ;
}
}
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 , " is already placed on the same line / column !" ) ) ;
OnPlaceTile ( new PlaceTileNotifiedEventArgs ( t , " is already placed on the same line / column !" ) ) ;
return false ;
return false ;
}
}
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 ( x , y , dx , dy , b , ref checkDoubles ) ) continue ;
if ( ! CheckTilesInLine ( cellUsed , b , x , y ) )
OnPlaceTile ( new PlaceTileNotifiedEventArgs ( t ,
{
" : You can't complete this line ! (More than 6 tiles / same tiles on the line)" ) ) ;
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 ( ! CheckTilesInLine ( cellUsed , b , x , y ) )
{
{
OnPlaceTile ( new PlaceTileNotifiedEventArgs ( t , " : You can't place a tile that isn't adjacent to another one !" ) ) ;
OnPlaceTile ( new PlaceTileNotifiedEventArgs ( t ,
"isn't on the same line as the ones previously placed !" ) ) ;
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 ;
}
}
@ -625,6 +717,9 @@ namespace QwirkleClassLibrary.Games
int score = cellsPlayed . Count ;
int score = cellsPlayed . Count ;
int nbCellsInLine = cellsPlayed . Count ;
int nbCellsInLine = cellsPlayed . Count ;
int nbCellsInPerpLine = 1 ;
var checkedCells = new List < Cell > ( ) ;
if ( cellsPlayed . Count = = 6 )
if ( cellsPlayed . Count = = 6 )
{
{
@ -654,16 +749,16 @@ 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 , new Tuple < int , int > ( cellsX , cellsY ) , ref nbCellsInLine , ref nbCellsInPerpLine , ref checkedCells ) ) ;
if ( nbCellsInLine = = 6 )
if ( nbCellsInLine = = 6 | | nbCellsInPerpLine = = 6 )
{
{
score + = 6 ;
score + = 6 ;
}
}
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 ) ;
}
}
@ -677,11 +772,12 @@ namespace QwirkleClassLibrary.Games
/// <param name="cell"></param>
/// <param name="cell"></param>
/// <param name="b"></param>
/// <param name="b"></param>
/// <param name="cellsPlayed"></param>
/// <param name="cellsPlayed"></param>
/// <param name="cellsX"></param>
/// <param name="orientation"></param>
/// <param name="cellsY"></param>
/// <param name="nbCellsInPerpLine"></param>
/// <param name="checkedCells"></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 nbCellsIn Line)
public int CalculateAdjacentScore ( Cell cell , Board b , ReadOnlyCollection < Cell > cellsPlayed , Tuple < int , int > orientation , ref int nbCellsInLine , ref int nbCellsIn Perp Line, ref List < Cell > checkedCells )
{
{
int score = 0 ;
int score = 0 ;
@ -693,11 +789,10 @@ namespace QwirkleClassLibrary.Games
b . GetCell ( cell . GetX , cell . GetY - 1 )
b . GetCell ( cell . GetX , cell . GetY - 1 )
} ;
} ;
var checkedSurroundingCells = new List < Cell > ( ) ;
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 ) | |
checkedCells . Contains ( adjacentCell ) )
{
{
continue ;
continue ;
}
}
@ -705,9 +800,10 @@ 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 ) ,
new Tuple < int , int > ( orientation . Item1 , orientation . Item2 ) , ref nbCellsInLine , ref nbCellsInPerpLine , ref checkedCells ) ;
checked Surrounding Cells. Add ( adjacentCell ) ;
checked Cells. Add ( adjacentCell ) ;
}
}
return score ;
return score ;
@ -719,19 +815,20 @@ namespace QwirkleClassLibrary.Games
/// <param name="cellsPlayed"></param>
/// <param name="cellsPlayed"></param>
/// <param name="cell"></param>
/// <param name="cell"></param>
/// <param name="direction"></param>
/// <param name="direction"></param>
/// <param name="b"></param>
/// <param name="orientation"></param>
/// <param name="orientation"></param>
/// <param name="nbCellsInLine"></param>
/// <param name="nbCellsInLine"></param>
/// <param name="nbCellsInPerpLine"></param>
/// <param name="checkedCells"></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 , Tuple< int , int > orientation , ref int nbCellsInLine , ref int nbCellsInPerpLine , ref List < Cell > checkedCells )
{
{
int score = 0 ;
int score = 0 ;
for ( int i = 1 ; i < 6 ; i + + )
for ( int i = 1 ; i < 6 ; i + + )
{
{
var extendedCell = b . GetCell ( cell . GetX + i * direction . Item1 , cell . GetY + i * direction . Item2 ) ;
var extendedCell = b oard . GetCell ( cell . GetX + i * direction . Item1 , cell . GetY + i * direction . Item2 ) ;
if ( extendedCell ? . Tile = = null | | cellsPlayed . Contains ( extendedCell ) )
if ( extendedCell ? . Tile ! = = null ! | | cellsPlayed . Contains ( extendedCell ) | | checkedCells . Contains ( extendedCell ) )
{
{
break ;
break ;
}
}
@ -741,10 +838,16 @@ namespace QwirkleClassLibrary.Games
nbCellsInLine + + ;
nbCellsInLine + + ;
}
}
if ( direction . Item1 ! = 0 & & orientation . Item1 ! = - 1 | | direction . Item2 ! = 0 & & orientation . Item2 ! = - 1 )
{
nbCellsInPerpLine + + ;
}
checkedCells . Add ( extendedCell ) ;
score + + ;
score + + ;
}
}
if ( direction . Item1 = = 0 & & orientation . Item1 = = - 1 & & orientation . Item2 ! = - 1 | | direction . Item2 = = 0 & & orientation . Item2 = = - 1 & & orientation . Item1 ! = - 1 )
if ( ShouldIncreaseScore( direction , orientation ) )
{
{
score + = 1 ;
score + = 1 ;
}
}
@ -752,6 +855,11 @@ namespace QwirkleClassLibrary.Games
return score ;
return score ;
}
}
public static bool ShouldIncreaseScore ( Tuple < int , int > direction , Tuple < int , int > orientation )
{
return direction . Item1 = = 0 & & orientation . Item1 = = - 1 & & orientation . Item2 ! = - 1 | |
direction . Item2 = = 0 & & orientation . Item2 = = - 1 & & orientation . Item1 ! = - 1 ;
}
/// <summary>
/// <summary>
/// Returns the list of the positions of the players who still have tiles in their bag
/// Returns the list of the positions of the players who still have tiles in their bag
@ -770,7 +878,6 @@ namespace QwirkleClassLibrary.Games
playerTilesBagPos . Add ( i ) ;
playerTilesBagPos . Add ( i ) ;
}
}
}
}
}
}
return playerTilesBagPos ;
return playerTilesBagPos ;
@ -787,7 +894,7 @@ namespace QwirkleClassLibrary.Games
{
{
foreach ( var t in players [ t1 ] . Tiles )
foreach ( var t in players [ t1 ] . Tiles )
{
{
for ( int b = 0 ; b < board ! .ReadCells . Count ; b + + )
for ( int b = 0 ; b < board .ReadCells . Count ; b + + )
{
{
int x = board . ReadCells [ b ] . GetX ;
int x = board . ReadCells [ b ] . GetX ;
int y = board . ReadCells [ b ] . GetY ;
int y = board . ReadCells [ b ] . GetY ;
@ -813,7 +920,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 +946,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 +956,7 @@ namespace QwirkleClassLibrary.Games
{
{
observableScoreBoard . Add ( item ) ;
observableScoreBoard . Add ( item ) ;
}
}
OnPropertyChanged ( nameof ( ObservableScoreBoard ) ) ;
OnPropertyChanged ( nameof ( ObservableScoreBoard ) ) ;
}
}
}
}