예제 #1
0
        public IEnumerable<Movement> FindMoves(Board board)
        {
            List<Tuple<Block, FlagCombination>> allValidCombinations = new List<Tuple<Block, FlagCombination>>();
            for (int i = 0; i < board.Width; i++)
            {
                for (int j = 0; j < board.Height; j++)
                {
                    Block current = board.Grid[i, j];
                    if (current.State != BlockState.Value || current.Value == 0)
                        continue;

                    var neighbors = new NeighborList(board.Grid, current);
                    if (board.isBlockSolved(current, neighbors))
                        continue;

                    int flagCount = neighbors.GetFlagCount();
                    var unknown = neighbors.GetUnknownBlocks().ToList();

                    allValidCombinations.Add(new Tuple<Block, FlagCombination>(current,
                        board.getValidCombinations(unknown, current.Value - flagCount)));
                }
            }

            yield break;
        }
예제 #2
0
        /// <summary>
        /// This algorithm will loop through each unsolved value on the board.
        /// It will then lock one flag on the board, and check if the board is in a valid state.
        /// If the board is invalid, then that block should be cleared, and that move will be returned.
        /// </summary>
        /// <returns></returns>
        private Movement? getMoveLock1(Board board)
        {
            for (int i = 0; i < board.Width; i++)
            {
                for (int j = 0; j < board.Height; j++)
                {
                    Block current = board.Grid[i, j];
                    if (current.State != BlockState.Value || current.Value == 0)
                        continue;

                    var neighbors = new NeighborList(board.Grid, current);
                    var unknown = neighbors.Where(n => n.State == BlockState.Unknown).ToList();

                    var valid = board.getValidCombinations(unknown, 2);
                    //clearAllGuesses();

                    foreach (var comb in valid)
                    {
                        foreach (var flag in comb)
                        {
                            // Loop through each potential flag in a combiantion.
                            // If setting that block as a flag breaks the board, then it must not be a flag
                            flag.SetRoundGuess(BlockState.Flag, roundGuesses);

                            bool guessFailed = false;
                            try
                            {
                                getMovesLock0(board).ToList();
                            }
                            catch (InvalidBoardException ex)
                            {
                                guessFailed = true;
                            }

                            clearAllRoundGuesses();

                            if (guessFailed)
                            {
                                return new Movement(flag, MoveTypes.SetClear);
                            }
                        }
                    }
                }
            }

            return null;
        }
예제 #3
0
        public IEnumerable <Movement> FindMoves(Board board)
        {
            int          flagsLeft       = 0;
            List <Block> allUnknown      = board.getUnknownBlocks(out flagsLeft);
            float        overallFlagProb = (float)flagsLeft / allUnknown.Count;

            Block bestClearChance      = null;
            float bestClearProbability = 0f;
            Block bestFlag             = null;
            float bestFlagProbability  = 0f;

            //Dictionary<Block, float> probs = new Dictionary<Block, float>();

            for (int i = 0; i < board.Width; i++)
            {
                for (int j = 0; j < board.Height; j++)
                {
                    Block current = board.Grid[i, j];
                    if (current.State != BlockState.Value || current.Value == 0)
                    {
                        continue;
                    }

                    var neighbors = new NeighborList(board.Grid, current);

                    int flagCount = neighbors.GetFlagCount();
                    var unknown   = neighbors.GetUnknownBlocks().ToList();

                    var combinations = board.getValidCombinations(unknown, current.Value - flagCount).ToList();
                    foreach (var un in unknown)
                    {
                        int   count     = combinations.Count(c => c.Any(b => b == un));
                        float flagProb  = (float)count / combinations.Count;
                        float clearProb = 1 - flagProb;

                        //float existing;
                        //if (probs.TryGetValue(un, out existing))
                        //{
                        //	if (flagProb < existing)
                        //		probs[un] = flagProb;
                        //}
                        //else
                        //{
                        //	probs.Add(un, flagProb);
                        //}

                        if (clearProb > bestClearProbability)
                        {
                            bestClearChance      = un;
                            bestClearProbability = clearProb;
                        }
                        if (flagProb > bestFlagProbability)
                        {
                            bestFlag            = un;
                            bestFlagProbability = flagProb;
                        }
                    }
                }
            }

            float overallClearProb = 1 - overallFlagProb;
            float max = getHeighestProb(overallClearProb, overallFlagProb, bestFlagProbability, bestClearProbability);

            if (overallClearProb == max || overallFlagProb == max)
            {
                MoveTypes moveType = overallClearProb == max ? MoveTypes.SetClear : MoveTypes.SetFlag;
                Block     random   = getBestRandom(board, allUnknown);
                if (random != null)
                {
                    yield return(new Movement(random, moveType, overallClearProb == max ? overallClearProb : overallFlagProb));
                }
            }
            else if (bestClearProbability == max)
            {
                yield return(new Movement(bestClearChance, MoveTypes.SetClear, bestClearProbability));
            }
            else
            {
                yield return(new Movement(bestFlag, MoveTypes.SetFlag, bestFlagProbability));
            }
            yield break;
        }
예제 #4
0
파일: Board.cs 프로젝트: FUR10N/Minesweeper
        /// <summary>
        /// If the given block has a value, then this checks if the neighboring flags/potential flags 
        /// represents a valid block (ie if block is a 2 and there are 3 flags around it, then it is invalid).
        /// <para>If the given block does not have value, then assume it is a valid block.</para>
        /// </summary>
        /// <param name="block"></param>
        /// <param name="neighbors"></param>
        /// <returns></returns>
        private bool isValidGuess(Block block, NeighborList neighbors = null)
        {
            if (block.State == BlockState.Unknown || block.State == BlockState.Flag)
                return true;

            if (neighbors == null)
                neighbors = new NeighborList(Grid, block);

            int flags = neighbors.GetFlagCount(true);
            int unknown = neighbors.Count(n => n.State == BlockState.Unknown && n.Guess == GuessState.None);
            if (block.Value < flags || block.Value - flags > unknown)
                return false;
            return true;
        }
예제 #5
0
파일: Board.cs 프로젝트: FUR10N/Minesweeper
 private bool isBoardSolved()
 {
     for (int i = 0; i < Grid.GetLength(0); i++)
     {
         for (int j = 0; j < Grid.GetLength(1); j++)
         {
             if (Grid[i, j].State != BlockState.Value)
                 continue;
             var neighbors = new NeighborList(Grid, Grid[i, j]);
             int flagCount = neighbors.GetFlagCount();
             var unknown = neighbors.GetUnknownBlocks().ToList();
             if (Grid[i,j].Value - flagCount < unknown.Count)
                 return false;
         }
     }
     return true;
 }
예제 #6
0
파일: Board.cs 프로젝트: FUR10N/Minesweeper
        /// <summary>
        /// Gets a list of blocks that can be cleared if the given guess is performed.
        /// </summary>
        /// <param name="guess"></param>
        /// <returns></returns>
        private IEnumerable<Block> clearBlocksAroundGuess(Block guess)
        {
            List<Block> ret = new List<Block>();
            var adjacentToGuess = new NeighborList(Grid, guess);
            var allBlocksToCheck = new List<Block>();

            // Loop through each block around the guess
            foreach (var adj in adjacentToGuess)
            {
                allBlocksToCheck.AddRange(new NeighborList(Grid, adj));
            }

            // Loop through each neighbor of an adjacent block to the guess
            // Basically, search each block around the guess, and get blocks that can cleared around the blocks next to guess
            foreach (var t in allBlocksToCheck.Distinct())
            {
                if (t.State != BlockState.Value)
                    continue;

                var neighbors = new NeighborList(Grid, t);
                int flags = neighbors.Count(n => n.State == BlockState.Flag || n.Guess == GuessState.Flag);
                int unknown = neighbors.Count(n => n.State == BlockState.Unknown);

                if (flags == t.Value && unknown != 0)
                {
                    foreach (var clear in neighbors)
                        if (clear.State == BlockState.Unknown && clear.Guess == GuessState.None)
                            ret.Add(clear);
                }
            }

            return ret.Distinct();
        }
예제 #7
0
파일: Board.cs 프로젝트: FUR10N/Minesweeper
        /// <summary>
        /// Checks if the block and all neighboring blocks are in a valid state given
        /// the current board state plus any guesses that have been made this round.
        /// <para>The idea is the come up with some guess (of where a flag or value is). Whoever calls this will make the guess (using SetGuess).</para>
        /// <para>After making the guess, this function will check the game board around that block to see if it is in a valid state.</para>
        /// <para>If it is not in a valid state, then we can assume that guess is incorrect and the caller can gain some information about a potential move.</para>
        /// </summary>
        /// <param name="block">The block to check. All 2-order neighbors around the block will be also checked.</param>
        /// <param name="potentialvalues">When checking valid blocks, this algorithm marks necessary neighbors as values 
        /// (if a block was solved by the guess)
        /// <para>Each block that was marked as a value will be added to this parameter.</para>
        /// </param>
        /// <returns>True if the block is valid.</returns>
        internal bool isValidBlock(Block block, List<Block> potentialvalues = null)
        {
            var n = new NeighborList(Grid, block);

            // If the given block is solved, then mark all unknown neighbors as values (using SetGuess)
            if (isBlockSolved(block, n, true))
            {
                for (int i = 0; i < n.Count; i++)
                {
                    if (n[i].State == BlockState.Unknown && n[i].Guess != GuessState.Flag)
                    {
                        if (potentialvalues != null)
                            potentialvalues.Add(n[i]);
                        n[i].SetGuess(GuessState.Value, tempGuesses);
                    }
                }
            }
            // Now loop through each neighbor of the block, and perform what was done above.
            for (int i = 0; i < n.Count; i++)
            {
                var test = new NeighborList(Grid, n[i]);
                if (isBlockSolved(n[i], test, true))
                {
                    for (int j = 0; j < test.Count; j++)
                    {
                        if (test[j].State == BlockState.Unknown && test[j].Guess != GuessState.Flag)
                        {
                            if (potentialvalues != null)
                                potentialvalues.Add(test[j]);
                            test[j].SetGuess(GuessState.Value, tempGuesses);
                        }
                    }
                    if (!isValidGuess(n[i], test))
                        return false;
                }
            }

            return isValidGuess(block, n) && new NeighborList(Grid,block,2).All(b=>isValidGuess(b));
        }
예제 #8
0
파일: Board.cs 프로젝트: FUR10N/Minesweeper
        internal bool isBlockSolved(Block block, NeighborList neighbors, bool useGuesses = false)
        {
            if (block.State != BlockState.Value)
                return false;

            if (neighbors == null)
                new NeighborList(Grid, block);

            return neighbors.GetFlagCount(useGuesses) == block.Value;
        }
예제 #9
0
        /// <summary>
        /// This is the fastest step and is done at the start of ever pass.
        /// <para></para>
        /// </summary>
        /// <returns></returns>
        private IEnumerable<Movement> getMovesLock0(Board board)
        {
            foreach (Block current in board.nonZeroValues)
            {
                var neighbors = new NeighborList(board.Grid, current);

                var unknown = neighbors.GetUnknownBlocks().ToList();
                if (unknown.Count == 0) // Already solved
                    continue;

                int flagCount = neighbors.GetFlagCount();

                // Check if all neighboring mines have been found
                if (flagCount == current.Value && unknown.Count != 0)
                {
                    yield return new Movement(current, MoveTypes.DoubleClick);
                }
                // Check if rest of unknown neighbors should be flags
                else if (current.Value - flagCount == unknown.Count)
                {
                    foreach (var n in neighbors)
                    {
                        if (n.State == BlockState.Unknown)
                        {
                            yield return new Movement(n, MoveTypes.SetFlag);
                        }
                    }
                }
                else if (unknown.Count != 0 && current.Value - flagCount > 0)
                {
                    var combinationMoves = board.getCombinationMoves(unknown, current.Value - flagCount);
                    foreach (var c in combinationMoves)
                        yield return c;
                }
            }
        }
예제 #10
0
 private bool isValidMacroGuess(Board board, IEnumerable<Block> unsolvedBlocks, IList<Block> comb)
 {
     foreach (Block b in unsolvedBlocks)
     {
         var neighbors = new NeighborList(board.Grid, b);
         int flags = neighbors.Count(i => i.State == BlockState.Flag || i.Guess == GuessState.Flag);
         if (flags != b.Value)
             return false;
     }
     return true;
 }
예제 #11
0
        public IEnumerable<Movement> FindMoves(Board board)
        {
            int flagsLeft = 0;
            List<Block> allUnknown = board.getUnknownBlocks(out flagsLeft);
            float overallFlagProb = (float)flagsLeft / allUnknown.Count;

            Block bestClearChance = null;
            float bestClearProbability = 0f;
            Block bestFlag = null;
            float bestFlagProbability = 0f;
            //Dictionary<Block, float> probs = new Dictionary<Block, float>();

            for (int i = 0; i < board.Width; i++)
            {
                for (int j = 0; j < board.Height; j++)
                {
                    Block current = board.Grid[i, j];
                    if (current.State != BlockState.Value || current.Value == 0)
                        continue;

                    var neighbors = new NeighborList(board.Grid, current);

                    int flagCount = neighbors.GetFlagCount();
                    var unknown = neighbors.GetUnknownBlocks().ToList();

                    var combinations = board.getValidCombinations(unknown, current.Value - flagCount).ToList();
                    foreach (var un in unknown)
                    {
                        int count = combinations.Count(c => c.Any(b => b == un));
                        float flagProb = (float)count / combinations.Count;
                        float clearProb = 1 - flagProb;

                        //float existing;
                        //if (probs.TryGetValue(un, out existing))
                        //{
                        //	if (flagProb < existing)
                        //		probs[un] = flagProb;
                        //}
                        //else
                        //{
                        //	probs.Add(un, flagProb);
                        //}

                        if (clearProb > bestClearProbability)
                        {
                            bestClearChance = un;
                            bestClearProbability = clearProb;
                        }
                        if (flagProb > bestFlagProbability)
                        {
                            bestFlag = un;
                            bestFlagProbability = flagProb;
                        }
                    }
                }
            }

            float overallClearProb = 1 - overallFlagProb;
            float max = getHeighestProb(overallClearProb, overallFlagProb, bestFlagProbability, bestClearProbability);

            if (overallClearProb == max || overallFlagProb == max)
            {
                MoveTypes moveType = overallClearProb == max ? MoveTypes.SetClear : MoveTypes.SetFlag;
                Block random = getBestRandom(board, allUnknown);
                if (random != null)
                    yield return new Movement(random, moveType, overallClearProb == max ? overallClearProb : overallFlagProb);
            }
            else if (bestClearProbability == max)
            {
                yield return new Movement(bestClearChance, MoveTypes.SetClear, bestClearProbability);
            }
            else
            {
                yield return new Movement(bestFlag, MoveTypes.SetFlag, bestFlagProbability);
            }
            yield break;
        }
예제 #12
0
        private Block getBestRandom(Board board, List<Block> allUnknown)
        {
            Block onlyUknownNeighbors = null;

            foreach (var un in allUnknown)
            {
                var neighbors = new NeighborList(board.Grid, un);
                if (neighbors.All(i => i.State == BlockState.Unknown))
                {
                    if (onlyUknownNeighbors == null)
                        onlyUknownNeighbors = un;
                }
                // Sugest it if no neighbars are values and it is not surrounded by flags
                else if (!neighbors.Any(i => i.State == BlockState.Value) && !neighbors.All(i=>i.State == BlockState.Flag))
                {
                    // best choice because if not a flag, then it can open up non-guesses
                    return un;
                }
            }

            return onlyUknownNeighbors;
        }