扫雷程序实现之 part 1

先贴一点上来。随后我会抽时间做一些设计模式的分析:)

////////////////////////////////////////////////////////////////////
// 
//    Project:    扫雷
//    Author:        Chen Rong
//    History:    
//        v1.0    2004,3,7    基本实现扫雷逻辑
//        v1.1    2005,7,7    重构
//
////////////////////////////////////////////////////////////////////
using System;

namespace ChenRong.WinMine {
    
/// <summary>
    
/// 扫雷游戏对象
    
/// </summary>

    public class MineGame {        
        
public MineCell[,] Board {
            
get return _board; }
        }


        MineCell[,] _board;

        
int _rows, _cols, _mines;        
        GameResult _gameResult 
= GameResult.None;

        
public int Rows {
            
get return _rows; }
        }


        
public int Cols {
            
get return _cols; }
        }


        
public int Mines {
            
get return _mines; }
        }


        
public GameResult Result {
            
get return _gameResult; }
        }


        
/// <summary>
        
/// 初始化雷区, 随机摆放地雷
        
/// </summary>
        
/// <param name="rows"></param>
        
/// <param name="cols"></param>
        
/// <param name="mines"></param>

        public void Reset(int rows, int cols, int mines) {
            
if (rows <= 0 || cols <= 0)            
                
throw new Exception("雷区的长,宽必须为正整数。");    
        
            
if (mines >= rows * cols)            
                
throw new Exception("您设定的雷数目太多!");                

            _gameResult 
= GameResult.None;
            _mines 
= mines;
            _rows 
= rows;
            _cols 
= cols;
            _board 
= new MineCell[rows, cols];

            InitializeCells();
            PlaceRandomMines();    
            UpdateNearbyMinesCount();            
        }


        
/// <summary>
        
/// 更新每个位置周围地雷的统计数字
        
/// </summary>

        private void UpdateNearbyMinesCount() {
            
for (int i = 0; i < _rows; i++{
                
for (int j = 0; j < _cols; j++{
                    _board[i, j].NearbyMines 
= GetNearbyMines(i, j);            
                }

            }

        }


        
/// <summary>
        
/// 摆放随机地雷
        
/// </summary>

        private void PlaceRandomMines() {
            
int count = 0;            
            Random r 
= new Random((int)DateTime.Now.Ticks);            

            
while (count < _mines) {                
                
int    row = r.Next(0, _rows);                
                
int    col = r.Next(0, _cols);

                
if (!_board[row, col].IsMine) {
                    _board[row, col].IsMine 
= true;
                    count
++;
                }
            
            }

        }


        
/// <summary>
        
/// 判断一个点是否为有效位置
        
/// </summary>
        
/// <param name="row"></param>
        
/// <param name="col"></param>
        
/// <returns></returns>

        private bool IsValidCell(int row, int col) {
            
return (row >= 0 && col >= 0 && row < _rows && col < _cols);
        }


        
/// <summary>
        
/// 从一个格子出发向四周的可能的位移
        
/// </summary>

        private int[,] moves = new int[82{{-1-1}{-10},{-11}{0-1}{01}{1-1}{10}{11}};

        
/// <summary>
        
/// 得到某个位置周围的地雷数    
        
/// </summary>
        
/// <param name="row"></param>
        
/// <param name="col"></param>
        
/// <returns></returns>

        private int GetNearbyMines(int row, int col) {
            
int minesFound = 0;

            
for (int i = 0; i < moves.GetLength(0); i++{
                
int r = row + moves[i, 0];
                
int c = col + moves[i, 1];

                
if (IsValidCell(r, c) && _board[r, c].IsMine)
                    minesFound
++;
            }

            
return minesFound;
        }

        
        
/// <summary>
        
/// 揭开某个点, 相当于鼠标左键单击触发的行为
        
/// </summary>
        
/// <param name="row"></param>
        
/// <param name="col"></param>

        public void Uncover(int row, int col) {                
            
if (! IsValidCell(row, col))
                
return;

            MineCell cell 
= _board[row, col];

            
if (cell.Uncovered) 
                
return;
            
            cell.Uncovered 
= true;    
            
            
// 如果周围雷数是 0, 那么顺便把周围的 8 个位置都翻开
            if (!cell.IsMine && cell.NearbyMines == 0{
                
for (int i = 0; i < moves.GetLength(0); i++)
                    Uncover(row 
+ moves[i, 0], col + moves[i, 1]);
            }
            
        }

    
        
/// <summary>
        
/// 设定或取消标志, 相当于鼠标右键单击的行为
        
/// </summary>
        
/// <param name="row"></param>
        
/// <param name="col"></param>

        public void ChangeMark(int row, int col) {
            MineCell cell 
= _board[row, col];
            
            
if (cell.Uncovered)
                
return;
            
            
// 轮换几种标志
            if (cell.Mark == Mark.None)
                cell.Mark 
= Mark.Mine;
            
else if (cell.Mark == Mark.Mine)
                cell.Mark 
= Mark.Question;
            
else if (cell.Mark == Mark.Question)
                cell.Mark 
= Mark.None;
        }

        
/// <summary>
        
/// 检验游戏结果
        
/// </summary>

        public void CheckGameResult() {
            
int iUncovered = 0;
            
int iMarkedAsMine = 0;            

            
// 先检测是否已经标出全部地雷
            for (int i = 0; i < _rows; i++{
                
for (int j = 0; j < _cols; j++{
                    MineCell cell 
= _board[i, j];

                    
if (cell.Uncovered) {
                        iUncovered
++;
                        
continue;
                    }
            
                    
if (cell.Mark == Mark.Mine) {
                        iMarkedAsMine
++;

                        
if (!cell.IsMine) {
                            _gameResult 
= GameResult.Lose;
                            
return;
                        }

                    }

                }

            }

            
// 所有的点都已经探测到,而且标注没有失误, 就是赢了
            if ((iUncovered + iMarkedAsMine) == _rows * _cols)
                _gameResult 
= GameResult.Win;            
        }

    

        
/// <summary>
        
/// 初始化每个单元格对象
        
/// </summary>

        private void InitializeCells() {
            
for (int i = 0; i < _rows; i++{
                
for (int j = 0; j < _cols; j++{
                    _board[i, j] 
= new MineCell();
                }

            }

        }

    }

}



posted on 2005-07-07 20:31  NeilChen  阅读(3062)  评论(15编辑  收藏  举报

导航