Example #1
0
        private static IEnumerable <IEnumerable <TileKinds> > FindValidCombinations(Tiles34 tiles34,
                                                                                    int firstIndex,
                                                                                    int secondIndex,
                                                                                    bool handNotCompleted = false)
        {
            //Tiles34[0,1,1,1,2,...]=>TileKinds[1,2,3,4,4,...]
            var indices = new TileKinds();

            for (var x = firstIndex; x <= secondIndex; x++)
            {
                if (tiles34[x] > 0)
                {
                    var l = indices.ToList();
                    l.AddRange(Enumerable.Repeat(new TileKind(x), tiles34[x]));
                    indices = new TileKinds(l);
                }
            }
            if (indices.Count == 0)
            {
                return(new List <IEnumerable <TileKinds> >());
            }

            //TileKindsのnP3全順列を列挙
            //[1,2,3,4,4]=>[[1,2,3],[1,2,4],[1,3,2],[1,3,4],[1,4,2],[1,4,3],[1,4,4],...]
            var t = indices.Permutations(3);
            var allPossibleCombinations = t.Select(x => new TileKinds(x));

            //刻子、順子の形をしている順列を抜きだす
            var validCombinations = new List <TileKinds>();

            foreach (var combination in allPossibleCombinations)
            {
                if (combination.IsChi || combination.IsPon)
                {
                    validCombinations.Add(combination);
                }
            }
            if (validCombinations.Count == 0)
            {
                return(new List <IEnumerable <TileKinds> >());
            }

            var countOfNeededCombinations = indices.Count / 3;

            //有り得る順列のセットが一通りしかないとき
            if (countOfNeededCombinations == validCombinations.Count &&
                indices.Equals(validCombinations.Aggregate(
                                   (x, y) => new TileKinds(Enumerable.Concat(x, y)))))
            {
                return new List <IEnumerable <TileKinds> > {
                           validCombinations
                }
            }
            ;

            var validCombinationsCopy = new List <TileKinds>(validCombinations);

            foreach (var item in validCombinations)
            {
                if (!item.IsPon)
                {
                    continue;
                }
                var countOfSets = 1;

                var countOfTiles = 0;
                while (countOfSets > countOfTiles)
                {
                    countOfTiles = indices.Count(x => item[0].Equals(x)) / 3;
                    countOfSets  = validCombinationsCopy.Count(x => item[0].Equals(x[0]) &&
                                                               item[1].Equals(x[1]) &&
                                                               item[2].Equals(x[2]));
                    if (countOfSets > countOfTiles)
                    {
                        validCombinationsCopy.Remove(item);
                    }
                }
            }
            validCombinations     = validCombinationsCopy;
            validCombinationsCopy = new List <TileKinds>(validCombinations);
            foreach (var item in validCombinations)
            {
                if (!item.IsChi)
                {
                    continue;
                }
                var countOfSets         = 5;
                var countOfPossibleSets = 4;
                while (countOfSets > countOfPossibleSets)
                {
                    countOfSets = validCombinationsCopy.Count(x => item[0].Equals(x[0]) &&
                                                              item[1].Equals(x[1]) &&
                                                              item[2].Equals(x[2]));
                    if (countOfSets > countOfPossibleSets)
                    {
                        validCombinationsCopy.Remove(item);
                    }
                }
            }
            validCombinations = validCombinationsCopy;

            if (handNotCompleted)
            {
                return new List <IEnumerable <TileKinds> >()
                       {
                           validCombinations
                       }
            }
            ;

            var possibleCombinations =
                new TileKinds(Enumerable.Range(0, validCombinations.Count))
                .Permutations(countOfNeededCombinations);

            var combinationsResults = new List <IEnumerable <TileKinds> >();

            foreach (var combination in possibleCombinations)
            {
                var result = new List <TileKind>();

                foreach (var item in combination)
                {
                    result.AddRange(validCombinations[item.Value]);
                }
                result.Sort((x, y) => x.CompareTo(y));

                if (!indices.Equals(new TileKinds(result)))
                {
                    continue;
                }

                var results = new List <TileKinds>();
                foreach (var item in combination)
                {
                    results.Add(validCombinations[item.Value]);
                }
                results.Sort((x, y) => x[0].CompareTo(y[0]));
                if (!combinationsResults.Contains_(results))
                {
                    combinationsResults.Add(results);
                }
            }
            return(combinationsResults);
        }