Ejemplo n.º 1
0
        public TetrisFiguresRandom(int Size, bool CheckConnected = true, int MinBlocks = 0, int MaxBlocks = 0)
        {
            int Variants = (int)Math.Pow(2, Size * Size); // количество вариантов для анализа

            for (int Variant = 1; Variant < Variants; Variant++)
            {
                bool[] Bits = Convert.ToString(Variant, 2).PadLeft(Size * Size, '0').Select(c => c == '1').ToArray();

                // проверяем количество точек

                int BlockCount = Bits.Count(b => b);

                if ((MinBlocks != 0 && BlockCount < MinBlocks) || (MaxBlocks != 0 && BlockCount > MaxBlocks))
                {
                    continue;
                }

                // заполняем точки фигуры, проверяем положение в левом верхнем углу

                TetrisBlock[] Blocks = new TetrisBlock[BlockCount];

                bool FirstRow    = false;
                bool FirstColumn = false;

                int BlockNumber = 0;

                for (int X = 0; X < Size; X++)
                {
                    for (int Y = 0; Y < Size; Y++)
                    {
                        if (Bits[X * Size + Y])
                        {
                            Blocks[BlockNumber] = new TetrisBlock(X, Y);

                            BlockNumber++;

                            if (Y == 0)
                            {
                                FirstRow = true;
                            }
                            if (X == 0)
                            {
                                FirstColumn = true;
                            }
                        }
                    }
                }

                if (!FirstRow || !FirstColumn)
                {
                    continue;
                }

                // проверяем связность фигуры

                if (CheckConnected)
                {
                    // http://algolist.manual.ru/maths/graphs/linked.php

                    // начальное значение - точки не связаны
                    foreach (TetrisBlock Block in Blocks)
                    {
                        Block.Mark = 1;
                    }

                    // начинаем проверку связности с этой точки
                    Blocks[0].Mark = 2;

                    TetrisBlock StartBlock;

                    while ((StartBlock = Blocks.FirstOrDefault(p => p.Mark == 2)) != null)
                    {
                        // точка обработана
                        StartBlock.Mark = 3;

                        // связанные точки ставим в очередь на обработку
                        foreach (TetrisBlock Block in Blocks.Where(p => p.Mark == 1 && Math.Abs(StartBlock.X - p.X) + Math.Abs(StartBlock.Y - p.Y) == 1))
                        {
                            Block.Mark = 2;
                        }
                    }

                    // остались не связанные точки
                    if (Blocks.Any(p => p.Mark == 1))
                    {
                        continue;
                    }
                }

                // проверяем совпадение фигур и добавляем фигуру

                TetrisFigure Figure = new TetrisFigure(Blocks);

                if (!Figures.Any(f => f.IsSimilar(Figure)))
                {
                    AddFigure(Figure);
                }
            }
        }