zoukankan      html  css  js  c++  java
  • 扫雷程序实现之 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();
                    }

                }

            }

        }

    }



  • 相关阅读:
    babel-loader的原理
    js弱类型转换的知识点
    个人说明
    嗯三月的小计划
    bzoj2326 [HNOI2011]数学作业
    bzoj2654 tree
    bzoj1018[SHOI2008]堵塞的交通traffic
    bzoj1937[Shoi2004]Mst 最小生成树
    一般图最大匹配-带花树-带注释模板
    FFT快速傅里叶变换-递归版-带注释模板
  • 原文地址:https://www.cnblogs.com/RChen/p/188107.html
Copyright © 2011-2022 走看看