Пример #1
0
        /// <summary>
        /// Reveals all unrevealed, non-flagged cells and returns the cells that were revealed.
        /// </summary>
        /// <returns></returns>
        private List <Cell> RevealAllNonFlaggedCells()
        {
            var revealedCells = new List <Cell>(Minefield.CellCount);

            for (var fy = 0; fy < Settings.Height; fy++)
            {
                for (var fx = 0; fx < Settings.Width; fx++)
                {
                    var cell = Minefield.Get(fx, fy);
                    if (!cell.IsFlagged && !cell.IsRevealed)
                    {
                        cell.IsRevealed = true;
                        revealedCells.Add(cell);
                    }
                }
            }
            return(revealedCells);
        }
Пример #2
0
        /// <summary>
        /// Reveals a cell at the specified location. If cell is a mine, the game ends with a failed result.
        /// If the cell is a blank (no adjacent mines), all adjacent unrevealed non-mine cells are also revealed.
        /// If only mines are left, regardless of flag status, the game ends with a success result.
        /// </summary>
        /// <param name="x">X co-ordinate of cell.</param>
        /// <param name="y">Y co-ordinate of cell.</param>
        /// <param name="confident">If true, will reveal all non-flagged non-revealed neighbour cells if the number
        /// of flagged cells equals at least the number of mines in the neighbourhood, regardless if the flags are
        /// set on the correct cells. Traditionally this occurred when both left and right mouse buttons were pressed.
        /// </param>
        /// <returns>An array of cells that were revealed. First element is always the specified cell, the rest
        /// in the order they were revealed in.</returns>
        public Cell[] Reveal(int x, int y, bool confident = false)
        {
            if (State != GameState.Running)
            {
                throw new InvalidOperationException("Game is not running");
            }
            if (x < 0 || x > Settings.Width - 1)
            {
                throw new ArgumentOutOfRangeException("x");
            }
            if (y < 0 || y > Settings.Height - 1)
            {
                throw new ArgumentOutOfRangeException("y");
            }

            // reveal cell
            var cell = Minefield.Get(x, y);

            if (cell.IsRevealed)
            {
                throw new InvalidOperationException("Cell is already revealed");
            }
            if (cell.IsFlagged)
            {
                throw new InvalidOperationException("Cell is flagged as a mine");
            }
            cell.IsRevealed = true;
            _numRevealed++;
            var revealedCells = new List <Cell>(Minefield.CellCount)
            {
                cell
            };

            // is the game over? if so, reveal all unrevealed cells
            if (cell.IsMine || Minefield.CellCount - Settings.MineCount == _numRevealed)
            {
                State  = GameState.Stopped;
                Result = cell.IsMine ? GameResult.Failure : GameResult.Success;
                revealedCells.AddRange(RevealAllNonFlaggedCells());
                return(revealedCells.ToArray());
            }

            // reveal any unrevealed non-mine neighbours if cell is blank
            var neighbours = Field.GetAdjacentPoints(cell.Location, Settings.Width, Settings.Height);

            if (cell.Neighbours == 0)
            {
                neighbours.ToList().ForEach(p =>
                {
                    // recursively reveal adjacent cell
                    var adjacent = Minefield.Get(p.X, p.Y);
                    if (!adjacent.IsFlagged && !adjacent.IsMine && !adjacent.IsRevealed)
                    {
                        revealedCells.AddRange(Reveal(adjacent.Location, confident));
                    }
                });
            }

            // confident reveal?
            if (confident)
            {
                // get neighbours and count mines and flags
                var flagCount = neighbours.Where(p => Minefield.Get(p).IsFlagged).Count();
                var mineCount = neighbours.Where(p => Minefield.Get(p).IsMine).Count();
                if (flagCount >= mineCount)
                {
                    neighbours.ToList().ForEach(p =>
                    {
                        // recursively reveal even if it is a mine
                        var adjacent = Minefield.Get(p.X, p.Y);
                        if (!adjacent.IsFlagged && !adjacent.IsRevealed)
                        {
                            revealedCells.AddRange(Reveal(adjacent.Location, confident));
                        }
                    });
                }
            }

            return(revealedCells.ToArray());
        }