예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        public void AddInformation(GameResult information)
        {
            //long start = DateTime.Now.Ticks;

            gameStatus = information.status;

            this.probabilityEngine = null; // previous probability engine invalidated

            newClears.Clear();

            // the game results tell us when a tile is cleared, flagged or unflagged
            foreach (ActionResult ar in information.actionResults)
            {
                if (ar.resultType == ResultType.Cleared)
                {
                    tilesLeft--;
                    tiles[ar.x, ar.y].SetValue(ar.value);

                    SolverTile tile = tiles[ar.x, ar.y];
                    newClears.Add(tile);
                    if (tile.IsDead())
                    {
                        deadTiles.Remove(tile);
                    }
                    //if (tile.IsExcluded()) {
                    //    excludedTiles.Remove(tile);
                    //}
                    //pendingClears.Remove(tile);
                }
                else if (ar.resultType == ResultType.Flagged)
                {
                    tiles[ar.x, ar.y].SetFlagged(true);
                }
                else if (ar.resultType == ResultType.Hidden)
                {
                    tiles[ar.x, ar.y].SetFlagged(false);
                }
                else if (ar.resultType == ResultType.Exploded)
                {
                    SolverTile tile = tiles[ar.x, ar.y];
                    tile.SetFlagged(false);
                    MineFound(tile);
                    this.bfa = null;   // can't walk the bfa tree if we've trodden on a mine
                }
            }

            // find and mark tiles as exhausted
            //int removed = 0;
            //if (newClears.Count > 0) {

            foreach (SolverTile tile in livingWitnesses)
            {
                if (AdjacentTileInfo(tile).hidden == 0)
                {
                    tile.SetExhausted();
                }
            }
            // remove all exhausted tiles from the list of witnesses
            livingWitnesses.RemoveWhere(x => x.IsExhausted());

            //}

            // add new witnesses which aren't exhausted
            foreach (SolverTile newTile in newClears)
            {
                AdjacentInfo adjInfo = AdjacentTileInfo(newTile);
                if (adjInfo.hidden != 0)
                {
                    if (adjInfo.excluded != adjInfo.hidden)
                    {
                        livingWitnesses.Add(newTile);
                    }
                    else
                    {
                        //excludedWitnesses.Add(newTile);
                    }
                }
            }

            //Write("There are " + livingWitnesses.Count + " living witnesses (" + removed + " deleted)");
            //Write("Adding Information to Solver took " + (DateTime.Now.Ticks - start) + " ticks");
        }