// Computes, for the tile at the specified index of the list, every possible sets in the list. Result as list of indexes list, not tiles list. private static List <List <int> > GetPossibleSetsForATile(List <TilePivot> baseTilesOfFamily, int i) { TilePivot currentTile = baseTilesOfFamily[i]; // Indexes of other tiles of the list which can be used for pairs or pons. List <int> indexOfDoublons = new List <int>(); // Indexes of other tiles of the list which can be used for second tile of a chi. List <int> indexOfNext1Num = new List <int>(); // Indexes of other tiles of the list which can be used for third tile of a chi. List <int> indexOfNext2Num = new List <int>(); for (int j = (i + 1); j < baseTilesOfFamily.Count; j++) { if (currentTile.Equals(baseTilesOfFamily[j])) { indexOfDoublons.Add(j); } else if (currentTile.Number == (baseTilesOfFamily[j].Number - 1)) { indexOfNext1Num.Add(j); } else if (currentTile.Number == (baseTilesOfFamily[j].Number - 2)) { indexOfNext2Num.Add(j); } } // Creates list of pairs. List <List <int> > listOfPairs = new List <List <int> >(); foreach (int doublonIndex in indexOfDoublons) { listOfPairs.Add(new List <int> { i, doublonIndex }); } // Creates list of pons. List <List <int> > listOfPons = new List <List <int> >(); foreach (List <int> pair in listOfPairs) { foreach (int doublonIndex in indexOfDoublons.Where(ind => !pair.Contains(ind))) { listOfPons.Add(new List <int>(pair) { doublonIndex }); } } // Creates list of chis. List <List <int> > listOfChis = indexOfNext1Num.SelectMany(num1 => indexOfNext2Num, (num1, num2) => new List <int> { i, num1, num2 }).ToList(); return(listOfPairs.Concat(listOfPons).Concat(listOfChis).ToList()); }
// Tries to extract each set from the lsit of tiles and adds it to the sets list if success. private static bool TryExtractSetsFromWindOrDragonFamily(List <SetPivot> setsList, List <TilePivot> tilesList) { if (_withPairCounts.Contains(tilesList.Count)) { // Extracts pair, then removes both tiles from the list. TilePivot pairTile = tilesList.GroupBy(t => t).Single(kvp => kvp.Count() == 2).Key; setsList.Add(new SetPivot(tilesList.Where(t => t.Equals(pairTile)).ToArray())); tilesList.RemoveAll(t => t == pairTile); CreateSetOfThreeTiles(setsList, tilesList); } else { CreateSetOfThreeTiles(setsList, tilesList); } return(true); }
/// <summary> /// Constructor. /// </summary> /// <param name="tiles"><see cref="ConcealedTiles"/>.</param> /// <param name="dominantWind"><see cref="DominantWind"/>.</param> /// <param name="seatWind"><see cref="SeatWind"/>.</param> /// <param name="latestTile"><see cref="LatestTile"/>.</param> /// <param name="isRon">Optionnal; <see cref="IsRon"/>.</param> /// <param name="openedSets">Optionnal; <see cref="OpenedSets"/>.</param> /// <param name="concealedKans">Optionnal; <see cref="ConcealedKans"/>.</param> /// <param name="isRiichi">Optionnal; <see cref="IsRiichi"/>.</param> /// <param name="isDoubleRiichi">Optionnal; <see cref="IsDoubleRiichi"/>.</param> /// <param name="isIppatsu">Optionnal; <see cref="IsIppatsu"/>.</param> /// <param name="isHaitei">Optionnal; <see cref="IsHaitei"/>.</param> /// <param name="isRinshankaihou">Optionnal ; <see cref="IsRinshankaihou"/>.</param> /// <param name="isChankan">Optionnal; <see cref="IsChankan"/>.</param> /// <param name="isInitialDraw">Optionnal; <see cref="IsInitialDraw"/>.</param> /// <exception cref="ArgumentException"><see cref="Messages.InvalidTilesCountInHandError"/>.</exception> /// <exception cref="ArgumentException"><see cref="Messages.InvalidHandArgumentsConsistencyError"/>.</exception> public FullHandPivot(List <TilePivot> tiles, WindPivot dominantWind, WindPivot seatWind, TilePivot latestTile, bool isRon = false, List <SetPivot> openedSets = null, List <SetPivot> concealedKans = null, bool isRiichi = false, bool isDoubleRiichi = false, bool isIppatsu = false, bool isHaitei = false, bool isRinshankaihou = false, bool isChankan = false, bool isInitialDraw = false) { tiles = tiles ?? new List <TilePivot>(); openedSets = openedSets ?? new List <SetPivot>(); concealedKans = concealedKans ?? new List <SetPivot>(); if ((openedSets.Count * 3 + concealedKans.Count * 3 + 1 + tiles.Count) != 14) { throw new ArgumentException(Messages.InvalidTilesCountInHandError); } if (openedSets.Count > 0 && (isRiichi || isDoubleRiichi || isIppatsu || openedSets.Any(set => set.IsPair))) { throw new ArgumentException(Messages.InvalidHandArgumentsConsistencyError, nameof(openedSets)); } if (concealedKans.Count > 0 && concealedKans.Any(set => !set.IsKan)) { throw new ArgumentException(Messages.InvalidHandArgumentsConsistencyError, nameof(concealedKans)); } if (concealedKans.Count == 0 && !openedSets.Any(set => set.IsKan) && isRinshankaihou) { throw new ArgumentException(Messages.InvalidHandArgumentsConsistencyError, nameof(isRinshankaihou)); } if (IsHaitei && isRinshankaihou) { throw new ArgumentException(Messages.InvalidHandArgumentsConsistencyError, nameof(IsHaitei)); } if (isChankan && (isRinshankaihou || !isRon)) { throw new ArgumentException(Messages.InvalidHandArgumentsConsistencyError, nameof(isChankan)); } if (isIppatsu && (isRinshankaihou || (IsRon && isHaitei))) { throw new ArgumentException(Messages.InvalidHandArgumentsConsistencyError, nameof(isIppatsu)); } // TODO : implement controls to prevent buggy initial draw ConcealedTiles = tiles.OrderBy(t => t).ToList(); DominantWind = dominantWind; SeatWind = seatWind; LatestTile = latestTile ?? throw new ArgumentNullException(nameof(latestTile)); IsRon = isRon; OpenedSets = openedSets; ConcealedKans = concealedKans; IsRiichi = isRiichi || isDoubleRiichi; IsIppatsu = isIppatsu; IsDoubleRiichi = isDoubleRiichi; IsChankan = isChankan; IsHaitei = isHaitei; IsRinshankaihou = isRinshankaihou; IsInitialDraw = IsInitialDraw; }