Пример #1
0
        // 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());
        }
Пример #2
0
        // 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);
        }
Пример #3
0
        /// <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;
        }