protected Figure ExecuteCommand(Commander.CommandType command, Figure figure, PlayingField playingField)
        {
            switch (command)
            {
                case Commander.CommandType.A:
                    figure = figure.ShiftXLeft();
                    break;
                case Commander.CommandType.D:
                    figure = figure.ShiftXRight();
                    break;
                case Commander.CommandType.S:
                    figure = figure.ShiftYDown();
                    break;
                case Commander.CommandType.Q:
                    figure = figure.RotateCounterClockwise();
                    break;
                case Commander.CommandType.E:
                    figure = figure.RotateClockwise();
                    break;
                case Commander.CommandType.P:
                    var fieldOut = playingField.Field.Select(row => row.ToArray()).ToArray();
                    foreach (var cell in figure.Cells)
                        fieldOut[cell.ProjectionY][cell.ProjectionX] = PlayingField.StateCoord.CurrentFigure;

                    foreach (var row in fieldOut)
                    {
                        foreach (var cell in row)
                            Console.Write
                            (
                                cell == PlayingField.StateCoord.Free ? '.' :
                                cell == PlayingField.StateCoord.Busy ? '#' : '*'
                            );
                        Console.Write(Environment.NewLine);
                    }
                    break;
            }

            if (СheckCollision(figure, playingField))
                throw new CollisionException();

            return figure;
        }
        protected PlayingField FixedFigureOnField(Figure figure, PlayingField playingField)
        {
            Action<PlayingField.StateCoord[][]> modPutFigure = field =>
            {
                foreach (var cell in figure.Cells)
                    field[cell.ProjectionY][cell.ProjectionX] = PlayingField.StateCoord.Busy;
            };

            PlayingField newPlayingField = ModifyField(modPutFigure, playingField);

            return newPlayingField;
        }
 public PlayingEngine(PlayingField playingField, Figure[] figurs, Commander commander)
 {
     _playingField = playingField;
     _commander = commander;
     _figurs = figurs.ToImmutableArray();
 }
 private bool СheckCollision(Figure figure, PlayingField playingField)
 {
     try
     {
         foreach (var cell in figure.Cells)
             if (playingField.Field[cell.ProjectionY][cell.ProjectionX] != PlayingField.StateCoord.Free)
                 return true;
     }
     catch (IndexOutOfRangeException)
     {
         return true;
     }
     return false;
 }
        private PlayingField ModifyField(Action<PlayingField.StateCoord[][]> modifyFieldFunc, PlayingField playingField)
        {
            var modField = playingField.Field.Select(row => row.ToArray()).ToArray();

            modifyFieldFunc(modField);

            var newField = modField.Select(row => row.ToImmutableArray()).ToImmutableArray();
            var newPlayingField = new PlayingField(playingField.CountX, playingField.CountY, newField);

            return newPlayingField;
        }
        protected PlayingField RemAllFullRow(PlayingField playingField, ref int bonus)
        {
            var field = playingField.Field.ToList();
            var remRow = new List<ImmutableArray<PlayingField.StateCoord>>();
            foreach (var row in field)
                if (СheckFullRow(row))
                {
                    remRow.Add(row);
                    bonus++;
                }
            remRow.ForEach(row => field.Remove(row));

            var valueEmptyRow = playingField.CountY - field.Count;
            var newFreeRow = Enumerable.Repeat
                (
                    Enumerable.Repeat(PlayingField.StateCoord.Free, playingField.CountX).ToImmutableArray(),
                    valueEmptyRow
                );

            var newPlayingField = new PlayingField(
                playingField.CountX, playingField.CountY, newFreeRow.Concat(field).ToImmutableArray());

            return newPlayingField;
        }
        protected Figure ProjectNewFigure(Figure figure, PlayingField playingField)
        {
            int rightEndFigure = figure.Cells[0].X;
            foreach (var cell in figure.Cells.Skip(1))
                if (rightEndFigure < cell.X)
                    rightEndFigure = cell.X;

            int leftEndFigure = figure.Cells[0].X;
            foreach (var cell in figure.Cells.Skip(1))
                if (leftEndFigure > cell.X)
                    leftEndFigure = cell.X;

            int lenFigure = rightEndFigure - leftEndFigure + 1;

            int positionOffsetLeft = (playingField.CountX - lenFigure) / 2;

            int upEndFigure = figure.Cells[0].Y;
            foreach (var cell in figure.Cells.Skip(1))
                if (cell.Y < upEndFigure)
                    upEndFigure = cell.Y;

            var newFigure = figure.ShiftXRight(Math.Abs(leftEndFigure) + positionOffsetLeft).ShiftYDown(Math.Abs(upEndFigure));

            if (СheckCollision(newFigure, playingField))
                throw new CollisionException();

            return newFigure;
        }
 protected PlayingField GameOver(PlayingField playingField, ref int bonus)
 {
     bonus -= 10;
     return new PlayingField(playingField.CountX, playingField.CountY);
 }