C#如何开发扫雷游戏-创新互联

简单的总结一下,如何利用C#进行WinForm 扫雷小游戏的开发:

目前成都创新互联已为1000+的企业提供了网站建设、域名、虚拟空间、网站托管运营、企业网站设计、南乐网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

扫雷游戏的主要设计的类有三个: Main、Pane 、MineField

1)Main 是主控窗体,负责项目的启动和关闭;并协调内部各个组建模块的协调工作。

2)Pane是一个方格的封装,是雷区的重要组建;它表示一个方格的当前状态,以及是否布雷等信息。

3)MineField是雷区的封装,是游戏的核心组建;它负责方格的布局以及地雷的分布;并控制玩家的基本操作以及正确的响应。

类的实现:

一、 Pane类

功能描述:Pane是一个方格的封装,是雷区的重要组建;它表示一个方格的当前状态,以及是否布雷等信息

One.它所具有的公共属性:

名称

可见性

返回值类型

功能描述

AroundMineCount

public

int

获取或设置当前方块周围地雷的数量

HasMine

Public

bool

获取或设置当前方块是否又雷

State

Public

PaneState

获取或设当前方块扫雷的状态

Two.它所具有的公共方法:

名称

可见性

返回类型

参数

功能描述

Mark

public

void

把当前方块标记为【有雷】状态,即:插上一个小红旗。

Open

public

void

打开该方块。

打开后如果如果有雷,则显示地理图标;否则如果周围有相邻的地理,则显示地雷数量。

Reset

public

void

恢复关闭状态,即:取消Mark()的操作结果。

Three:源码:

//默认的构造方法

public Pane()

        {InitializeComponent();

this.BackgroundImageLayout = ImageLayout.Stretch;

}

//公有属性:

        Public  bool  HasMine { get; set; }

Public  int  AroundMineCount { get; set; }

Public  PaneState  State { get; set; }  //由于它有几种状态,设置一个枚举类型属性

public enum PaneState

        {

           Closed,   //关闭状态

           Opened,  //打开状态

           Marked,  //标记状态

     }

//共有方法:

public void Mark()    //标记当前方格为又雷状态,插个小红旗

        {

            this.BackgroundImage = Properties.Resources.Marked;

            this.State = PaneState.Marked;

        }

  public void Reset()   //恢复标记状态,取消小红旗标记

        {

            this.BackgroundImage = null;

            this.State = PaneState.Closed;

        }

//打开方法

     //打开后如果如果有雷,则显示地理图标;否则如果周围有相邻的地理,则显示地雷数量。

      public void Open()

        {

            if (this.HasMine)

            {

                this.BackgroundImage = Properties.Resources.MineBomp;

                this.Enabled = false;

            }

            else

            {

                switch (this.AroundMineCount)

                {

                    case 0:

                        this.BackgroundImage = null;

                        this.Enabled = false;

                        break;

                    case 1:

                        this.BackgroundImage = Properties.Resources.Num1;

                        this.Enabled = false;

                        break;

                    case 2:

                        this.BackgroundImage = Properties.Resources.Num2;

                        this.Enabled = false;

                        break;

                    case 3:

                        this.BackgroundImage = Properties.Resources.Num3;

                        this.Enabled = false;

                        break;

                    case 4:

                        this.BackgroundImage = Properties.Resources.Num4;

                        this.Enabled = false;

                        break;

                    case 5:

                        this.BackgroundImage = Properties.Resources.Num5;

                        this.Enabled = false;

                        break;

                    case 6:

                        this.BackgroundImage = Properties.Resources.Num6;

                        this.Enabled = false;

                        break;

                    case 7:

                        this.BackgroundImage = Properties.Resources.Num7;

                        this.Enabled = false;

                        break;

                    case 8:

                        this.BackgroundImage = Properties.Resources.Num8;

                        this.Enabled = false;

                        break;

                }

            }

       }

二、 MineField类

功能描述:CrlMineField是雷区的封装,是游戏的核心组建;它负责方格的布局以及地雷的分布;并控制玩家的基本操作以及正确的响应。

One.它所具有的公有方法

名称

可见性

返回值类型

参数

功能描述

InitMineField

Public

Void

int paneNumber, int mineNumber

初始化雷区。布局方格并随机分布地理。

DisplayAll

Public

Void

明示雷区的全部方块里的内容。当踩雷以后,给玩家显示所有地雷位置。

DisplayAround

Pubic

Void

Pane pane

明示与给定方格相关联的无地雷的方格。玩家点击一个无雷方格后使用。

Two.它有具有的私有方法

名称

可见性

返回值类型

参数

功能描述

GetPanesAround

Private

List

Pane pane

获取与当前方格相邻的所有方格。

GetMineCountAround

Private

int

Pane pane

获取周围地雷的总数量

GetPaneSize

Private

Size

获取每个小方格的大小

LayoutPanes

Private

Void

排列有所方格,完成布雷

LayMines

Private

Void

int mineNumber

随机布雷

IsAllMineSweeped

Private

Bool

判断是否扫雷成功

Three.事件处理

名称

可见性

返回值类型

参数

功能描述

MineField_SizeChanged

Private

Void

object sender, EventArgs e

如果雷区面板尺寸有变化,则重新进行布局。

OnPaneMouseDown

Private

Void

object sender, EventArgs e

仅处理鼠标左键和右键事件,忽略其他按键。

Four.源码

//事件的委托

public delegate void MineSweepingCompletedEventHandler(object sender, EventArgs e);

public delegate void MineSweepingFailedEventHandler(object sender, EventArgs e);

public partial class CrlMineField : UserControl

{

//成功和失败两个委托事件的申明

        public event MineSweepingCompletedEventHandler MineSweepingCompleted;

        public event MineSweepingFailedEventHandler MineSweepingFailed;

        public CrlMineField()

        {

            InitializeComponent();

        }

        /// 

        /// 初始化雷区

        /// 

        /// 每排方块的数量

        /// 地雷的数量

        public void InitMineField(int paneNumber, int mineNumber)

        {

            if (mineNumber >= paneNumber * paneNumber)

            {

                throw new ApplicationException("地雷太多了,不合法游戏规则。");

            }

            // 清空现有的所有方块

            if (this.Controls.Count > 0)

            {

                this.Controls.Clear();

            }

            //添加雷区方格

            for (int i = 0; i < paneNumber * paneNumber; i++)

            {

                Pane pane = new Pane();

                pane.MouseDown += new MouseEventHandler(OnPaneMouseDown);

                this.Controls.Add(pane);

            }

          // 布局方格

            this.LayoutPanes();

            // 随机部署地雷

            this.LayMines(mineNumber);

            // 设置每个方格周边的地雷数

            foreach (Pane p in this.Controls)

            {

                p.AroundMineCount = this.GetMineCountAround(p);

            }

        }

        /// 

        /// 明示雷区的全部方块里的内容

        /// 

        public void DisplayAll()

        {

            foreach (Pane pane in this.Controls)

            {

                if (pane.State != PaneState.Opened)

                {

                    pane.Open();

                }

            }

        }

        /// 

        /// 明示与给定方格相关联的无地雷的方格

        /// 

        /// 

        public void DisplayAround(Pane pane)

        {

            if (pane.State == PaneState.Opened || pane.HasMine)

            {

                return;

            }

            // 明示当前方格本身

            pane.Open();

            // 通过递归明示当前方格四周的所有方格

            List panesAround = this.GetPanesAround(pane);

            foreach (Pane p in panesAround)

            {

                // 如果该方格四周没有相邻的地雷,则递归

                if (this.GetMineCountAround(p) == 0)

                {

                    this.DisplayAround(p);

                }

                else

                {

                    if (p.State != PaneState.Opened && !p.HasMine)

                    {

                        p.Open();

                    }

                }

            }

}

#region 私有方法

        /// 

        /// 获取与当前方格相邻的所有方格。

        /// 

        /// 当前方格

        /// 

        private List GetPanesAround(Pane pane)

        {

            List result = new List();

            // 通过递归明示当前方格四周的所有方格

            int paneHeight = this.GetPaneSize().Height;

            int paneWidth = this.GetPaneSize().Width;

            foreach (Pane p in this.Controls)

            {

                逐个扫描当前方格四周地雷数目

                if (Math.Abs(p.Top - pane.Top) == 0 && Math.Abs(p.Left - pane.Left) == paneWidth

                    ||

                    Math.Abs(p.Left - pane.Left) == 0 && Math.Abs(p.Top - pane.Top) == paneHeight

                    ||

                    Math.Abs(p.Top - pane.Top) == paneHeight && Math.Abs(p.Left - pane.Left) == paneWidth

                    ||

                    Math.Abs(p.Left - pane.Left) == paneWidth && Math.Abs(p.Top - pane.Top) == paneHeight)

                {

                    result.Add(p);

                }

            }

            return result;

        }

        /// 

        /// 获取当前方格四周地雷数量

        /// 

        /// 当前方格

        /// 

        private int GetMineCountAround(Pane pane)

        {

            int result = 0;

            List panes = this.GetPanesAround(pane);

            foreach (Pane p in panes)

            {

                if (p.HasMine)

                {

                    result++;

                }

            }

            return result;

        }

        /// 

        /// 获取当前每个方格的尺寸

        /// 

        /// 

        private Size GetPaneSize()

        {

            if (this.Controls.Count == 0)

            {

                return new Size();

            }

            else

            {

                int paneNumber = (int)Math.Sqrt(this.Controls.Count);

                int paneWidth = this.Width / paneNumber;

                int paneHeight = this.Height / paneNumber;

                return new Size(paneWidth, paneHeight);

            }

        }

        /// 

        /// 排列所有雷区的方格,完成布局。

        /// 

        private void LayoutPanes()

        {

            if (this.Controls.Count <= 0)

            {

                return;

            }

            int paneNumber = (int)Math.Sqrt(this.Controls.Count);

            int paneHeight = this.GetPaneSize().Height;

            int paneWidth = this.GetPaneSize().Width;

            int paneIndex = 0;

            // 绘制雷区方块

            int paneLeft = 0;

            int paneTop = 0;

            for (int colNum = 0; colNum < paneNumber; colNum++)

            {

                paneTop = colNum * paneHeight;

                for (int rowNum = 0; rowNum < paneNumber; rowNum++)

                {

                    paneLeft = rowNum * paneWidth;

                    Pane pane = this.Controls[paneIndex] as Pane;

                    pane.Location = new Point(paneLeft, paneTop);//设置方块位置

                    pane.Size = new Size(paneWidth, paneHeight);//设置方块大小

                    paneIndex++;

                }

            }

        }

        /// 

        /// 随机部署地雷

        /// 

        /// 

        private void LayMines(int mineNumber)

        {

            Random rdm = new Random();

            for (int i = 0; i < mineNumber; i++)

            {

                while (true)

                {

                    int index = rdm.Next(0, this.Controls.Count);

                    Pane pane = this.Controls[index] as Pane;

                    if (!pane.HasMine)

                    {

                        pane.HasMine = true;

                        break;

                    }

                }

            }

        }

        /// 

        /// 是否扫雷成功。即:所有地雷都已经正确作出标记

        /// 

        /// 

        private bool IsAllMineSweeped()

        {

            int markedCount = 0;

            int mineCount = 0;

            foreach (Pane pane in this.Controls)

            {

                if (pane.HasMine)

                {

                    mineCount++;

                }

                if (pane.State == PaneState.Marked)

                {

                    markedCount++;

                    if (!pane.HasMine)

                    {

                        //存在做了标记但没有地雷的方格,扫雷没有正确完成。

                        return false;

                    }

                }

            }

            return mineCount == markedCount;

        }

        #endregion

        #region 事件处理

        /// 

        /// 如果雷区面板尺寸有变化,则重新进行布局。

        /// 使得通过改变方格大小来整体适应雷区面板的尺寸。

        /// 

        /// 

        /// 

        private void CrlMineField_SizeChanged(object sender, EventArgs e)

        {

            try

            {

                this.LayoutPanes();

            }

            catch (Exception ex)

            {

                ExceptionHandler.OnException(ex);

            }

        }

        private void OnPaneMouseDown(object sender, MouseEventArgs e)

        {

            // 仅处理鼠标左键和右键事件,忽略其他按键。

            if (e.Button != MouseButtons.Left && e.Button != MouseButtons.Right)

            {

                return;

            }

            try

            {

                Pane pane = sender as Pane; //获取当前被鼠标点中的方格

                if (e.Button == MouseButtons.Left)//鼠标左键

                {

                    if (pane.HasMine) //踩地雷了

                    {

                        pane.Open();

                        this.DisplayAll();

                        if (this.MineSweepingFailed != null)

                        {

                            this.MineSweepingFailed(this, EventArgs.Empty);

                        }

                    }

                    else

                    {

                        //明示当前方格相邻的所有无地雷的方格

                        this.DisplayAround(pane);

                    }

                }

                else if (e.Button == MouseButtons.Right)//鼠标右键

                {

                    if (pane.State == PaneState.Marked)

                    {

                        pane.Reset();//取消小红旗标记

                    }

                    else

                    {

                        pane.Mark(); //插个小红旗做标记

                    }

                }

                // 所有地雷扫除成功

                if (this.IsAllMineSweeped())

                {

                    if (this.MineSweepingCompleted != null)

                    {

                        this.MineSweepingCompleted(this, EventArgs.Empty);

                    }

                }

            }

            catch (Exception ex)

            {

               ExceptionHandler.OnException(ex);

            }

        }

        #endregion

三、Main类

      还未完善,负责各个模块的协调工作,如导航菜单里面设置游戏的开始,结束,时间计时,保存结果,查看排行榜,游戏的级别等,由于周末两天的时间还未能将其完善,只实现了一个大体的功能,当然还存在一些Bug,有待调试!

附属插图:

C#如何开发扫雷游戏C#如何开发扫雷游戏C#如何开发扫雷游戏C#如何开发扫雷游戏

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


本文题目:C#如何开发扫雷游戏-创新互联
转载来源:http://pwwzsj.com/article/csdjjp.html