private RunResult InternalCalculation(IGame game, int stepNumber)
        {
            if (stepNumber <= 1)
            {
                return(oneStepSolver.InternalCalculation(game));
            }

            IDictionary <Direction, double> result = new Dictionary <Direction, double>();

            foreach (Direction dir in Directions.All)
            {
                IGame newGame  = game.DeepCopy();
                bool  hasShift = newGame.PlayerShift(dir);
                if (!hasShift)
                {
                    continue;
                }

                List <double> scores = new List <double>();
                foreach (Position pos in newGame.InternalBoard.BlankSlots())
                {
                    IGame other2 = newGame.DeepCopy();
                    other2.InternalBoard.SetNumber(2, pos);
                    RunResult run2     = InternalCalculation(other2, stepNumber - 1);
                    double    penalty2 = run2.IsSuccess ? run2.Penalty : double.MaxValue;

                    IGame other4 = newGame.DeepCopy();
                    other4.InternalBoard.SetNumber(4, pos);
                    RunResult run4     = InternalCalculation(other4, stepNumber - 1);
                    double    penalty4 = run4.IsSuccess ? run4.Penalty : double.MaxValue;

                    scores.Add(penalty2 * 0.9 + penalty4 * 0.1);
                }
                result[dir] = scores.Average();
            }
            if (!result.Any())
            {
                return(RunResult.Fail);
            }
            return(RunResult.OK(result.OrderBy(x => x.Value).First()));
        }
        public Direction Recommend(IGame game)
        {
            RunResult run = InternalCalculation(game, STEPNUM);

            return(run.IsSuccess ? run.Direction : Directions.Default);
        }