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); } }
/// <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(); } } }