private static SolverTile OffEdgeGuess(SolverInfo information, HashSet <SolverTile> witnessedSet) { // see if the corners are available SolverTile bestGuess = information.GetTile(0, 0); if (bestGuess.IsHidden() && !witnessedSet.Contains(bestGuess)) { return(bestGuess); } bestGuess = information.GetTile(0, information.description.height - 1); if (bestGuess.IsHidden() && !witnessedSet.Contains(bestGuess)) { return(bestGuess); } bestGuess = information.GetTile(information.description.width - 1, 0); if (bestGuess.IsHidden() && !witnessedSet.Contains(bestGuess)) { return(bestGuess); } bestGuess = information.GetTile(information.description.width - 1, information.description.height - 1); if (bestGuess.IsHidden() && !witnessedSet.Contains(bestGuess)) { return(bestGuess); } bestGuess = null; int bestGuessCount = 9; for (int x = 0; x < information.description.width; x++) { for (int y = 0; y < information.description.height; y++) { SolverTile tile = information.GetTile(x, y); if (tile.IsHidden() && !witnessedSet.Contains(tile)) { AdjacentInfo adjInfo = information.AdjacentTileInfo(tile); if (adjInfo.hidden < bestGuessCount) { bestGuess = tile; bestGuessCount = adjInfo.hidden; } } } } return(bestGuess); }
private static List <SolverAction> ScanForTrivialActions(SolverInfo information, HashSet <SolverTile> set) { List <SolverAction> actions = new List <SolverAction>();; HashSet <SolverTile> alreadyProcessed = new HashSet <SolverTile>(); foreach (SolverTile tile in set) { AdjacentInfo adjInfo = information.AdjacentTileInfo(tile); if (tile.GetValue() == adjInfo.mines) // if we have the correct number of mines then the remaining hidden tiles can be cleared { foreach (SolverTile adjTile in information.GetAdjacentTiles(tile)) { if (!alreadyProcessed.Contains(adjTile) && adjTile.IsHidden() && !adjTile.IsMine()) { alreadyProcessed.Add(adjTile); // avoid marking as cleared more than once //Utility.Write(adjTile.AsText() + " can be cleared"); actions.Add(new SolverAction(adjTile, ActionType.Clear, 1)); } } } if (tile.GetValue() == adjInfo.mines + adjInfo.hidden) // If Hidden + Mines we already know about = tile value then the rest must be mines { foreach (SolverTile adjTile in information.GetAdjacentTiles(tile)) { if (!alreadyProcessed.Contains(adjTile) && adjTile.IsHidden() && !adjTile.IsMine()) { alreadyProcessed.Add(adjTile); // avoid marking as a mine more than once //Utility.Write(adjTile.AsText() + " is a mine"); if (!information.MineFound(adjTile)) { actions.Add(new SolverAction(adjTile, ActionType.Flag, 0)); // and request it is flagged } } } } // 2 mines to find and only 3 tiles to put them if (tile.GetValue() - adjInfo.mines == 2 && adjInfo.hidden == 3) { foreach (SolverTile adjTile in information.GetAdjacentTiles(tile)) { if (!adjTile.IsHidden() && !adjTile.IsMine() && !adjTile.IsExhausted()) { AdjacentInfo tileAdjInfo = information.AdjacentTileInfo(adjTile); if (adjTile.GetValue() - tileAdjInfo.mines == 1) // an adjacent tile only needs to find one mine { int notAdjacentCount = 0; SolverTile notAdjTile = null; foreach (SolverTile adjTile2 in information.GetAdjacentTiles(tile)) { if (adjTile2.IsHidden() && !adjTile2.IsAdjacent(adjTile)) { notAdjacentCount++; notAdjTile = adjTile2; } } if (notAdjacentCount == 1 && !alreadyProcessed.Contains(notAdjTile)) // we share all but one tile, so that one tile must contain the extra mine { alreadyProcessed.Add(notAdjTile); // avoid marking as a mine more than once if (!information.MineFound(notAdjTile)) { actions.Add(new SolverAction(notAdjTile, ActionType.Flag, 0)); // and request it is flagged break; // restrict to finding one mine at a time (the action of marking the mine throws any further analysis out) } } } } } } // Subtraction method //continue; // skip this bit foreach (SolverTile adjTile in information.GetAdjacentTiles(tile)) { if (!adjTile.IsHidden() && !adjTile.IsMine() && !adjTile.IsExhausted()) { AdjacentInfo tileAdjInfo = information.AdjacentTileInfo(adjTile); if (adjTile.GetValue() - tileAdjInfo.mines == tile.GetValue() - adjInfo.mines) // if the adjacent tile is revealed and shares the same number of mines to find // If all the adjacent tiles adjacent tiles are also adjacent to the original tile { bool allAdjacent = true; foreach (SolverTile adjTile2 in information.GetAdjacentTiles(adjTile)) { if (adjTile2.IsHidden() && !adjTile2.IsAdjacent(tile)) { allAdjacent = false; break; } } if (allAdjacent) { //information.Write(tile.AsText() + " can be subtracted by " + adjTile.AsText()); foreach (SolverTile adjTile2 in information.GetAdjacentTiles(tile)) { if (adjTile2.IsHidden() && !adjTile2.IsAdjacent(adjTile) && !alreadyProcessed.Contains(adjTile2)) { alreadyProcessed.Add(adjTile2); // avoid marking as a mine more than once actions.Add(new SolverAction(adjTile2, ActionType.Clear, 1)); } } } } } } } return(actions); }