public void PerformMove()
        {
            var probabilityCruxes = new List <ProbabilityCrux>();

            // Find groups of linked cruxes (across, not adjacent). They are separated
            // into different groups because they are statistically independent, so we
            // want to perform the calculations separately to vastly speed up the program
            var cruxGroups = FindCruxGroups();

            foreach (var cruxGroup in cruxGroups)
            {
                var numbers = FindAllAdjacentNumbers(cruxGroup);

                // Calculate the safest crux to click in this group and add it to a list
                probabilityCruxes.Add(GetSafeProbabilityCrux(numbers, cruxGroup));
            }

            // Find the safest crux out of all of the groups
            var safestCrux = probabilityCruxes.OrderBy(_ => _.MineProbability).First();

            MouseOperations.PerformLeftClick(
                gameBoard.WindowRect.left + Solver.GRID_OFFSET_X + (safestCrux.Crux.PosX * Square.PIXEL_WIDTH) + 8,
                gameBoard.WindowRect.top + Solver.GRID_OFFSET_Y + (safestCrux.Crux.PosY * Square.PIXEL_HEIGHT) + 8);
            LogStatistics(safestCrux);
        }
 /// <summary>
 /// Mark all crux squares on the game grid
 /// </summary>
 /// <param name="grid"></param>
 private void SetCruxes(Square[,] grid)
 {
     for (int i = 0; i < grid.GetLength(0); i++)
     {
         for (int v = 0; v < grid.GetLength(1); v++)
         {
             var currentSquare = grid[i, v];
             if (currentSquare.Type == SquareType.Number)
             {
                 var adjacentUnknown = currentSquare.AdjacentUnclicked.Where(_ => _.Threat != ThreatType.Flag);
                 var adjacentFlags   = currentSquare.AdjacentUnclicked.Where(_ => _.Threat == ThreatType.Flag);
                 if (adjacentUnknown.Count() > currentSquare.Number - adjacentFlags.Count())
                 {
                     foreach (var square in adjacentUnknown)
                     {
                         if (square.Threat != ThreatType.Crux)
                         {
                             square.Threat = ThreatType.Crux;
                             MouseOperations.PerformQuestionClick(
                                 gameBoard.WindowRect.left + Solver.GRID_OFFSET_X + (square.PosX * Square.PIXEL_WIDTH) + 8,
                                 gameBoard.WindowRect.top + Solver.GRID_OFFSET_Y + (square.PosY * Square.PIXEL_HEIGHT) + 8);
                         }
                     }
                 }
             }
         }
     }
 }
 /// <summary>
 /// Mark all flags on the game grid
 /// </summary>
 /// <param name="grid"></param>
 private void SetFlags(Square[,] grid)
 {
     for (int i = 0; i < grid.GetLength(0); i++)
     {
         for (int v = 0; v < grid.GetLength(1); v++)
         {
             if (grid[i, v].Type == SquareType.Number)
             {
                 if (grid[i, v].AdjacentUnclicked.Count <= grid[i, v].Number)
                 {
                     foreach (var square in grid[i, v].AdjacentUnclicked)
                     {
                         if (square.Threat != ThreatType.Flag)
                         {
                             square.Threat = ThreatType.Flag;
                             MouseOperations.PerformFlagClick(
                                 gameBoard.WindowRect.left + Solver.GRID_OFFSET_X + (square.PosX * Square.PIXEL_WIDTH) + 8,
                                 gameBoard.WindowRect.top + Solver.GRID_OFFSET_Y + (square.PosY * Square.PIXEL_HEIGHT) + 8);
                         }
                     }
                 }
             }
         }
     }
 }
 public void PerformMoves(IEnumerable <Square> safeSquares)
 {
     foreach (var square in safeSquares)
     {
         int safestClickX = square.PosX;
         int safestClickY = square.PosY;
         MouseOperations.PerformLeftClick(
             gameBoard.WindowRect.left + Solver.GRID_OFFSET_X + (safestClickX * Square.PIXEL_WIDTH) + 8,
             gameBoard.WindowRect.top + Solver.GRID_OFFSET_Y + (safestClickY * Square.PIXEL_HEIGHT) + 8);
     }
 }
예제 #5
0
        /// <summary>
        /// Prepares game board and executes calculation logic
        /// </summary>
        /// <param name="windowRect"></param>
        /// <param name="os"></param>
        public void BeginSolving(User32.Rect windowRect)
        {
            // Get height and width properties of process
            int windowWidth  = windowRect.right - windowRect.left;
            int windowHeight = windowRect.bottom - windowRect.top;

            while (true)
            {
                {
                    Board gameBoard = CreateGameBoard(windowRect, windowWidth, windowHeight);
                    if (gameBoard == null)
                    {
                        continue;
                    }

                    bool gameRestarted = false;
                    if (!gameBoard.IsSmiling)
                    {
                        Thread.Sleep(5000);
                        // Click restart button
                        MouseOperations.PerformLeftClick(windowRect.left + (windowWidth / 2) + 2, windowRect.top + 77);
                        gameRestarted = true;
                    }

                    // If the game has been restarted, make initial click in the corner (statistically safest move)
                    if (gameRestarted)
                    {
                        MouseOperations.PerformLeftClick(
                            gameBoard.WindowRect.left + Solver.GRID_OFFSET_X + (gameBoard.Grid[gameBoard.Grid.GetLength(0) - 1, 0].PosX * Square.PIXEL_WIDTH) + 8,
                            gameBoard.WindowRect.top + Solver.GRID_OFFSET_Y + (gameBoard.Grid[gameBoard.Grid.GetLength(0) - 1, 0].PosY * Square.PIXEL_HEIGHT) + 8);
                        Thread.Sleep(100);
                    }

                    // Calculate optimal move and apply click
                    MoveCalculator moveCalculator = new MoveCalculator(gameBoard);
                    moveCalculator.CalculateMove();
                }
            }
        }