• C#版扫雷游戏


    知识点:

    1.  枚举类型的使用
    2. 当某个方法暂时不想去实现的时候,最好在方法体中写上:throw new NotImplementedException()
    3. 如何将图片资源引入到项目的属性中去
    4. 设置控件的大小:pane.Size = new Size(paneWidth,paneHeight);
    5. 设置控件的位置:pane.Location = new Point(paneLeft,paneTop);
    6. 事件的动态绑定:pane.MouseDown += pane_MouseDown;
    7. 如何定义事件并引发事

              public delegate void MineSweepedSuccessEventHandler(object sender,EventArgs e);
              public event MineSweepedSuccessEventHandler MineSweepedSucces;

    Form1(主窗体)代码: 

    View Code
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace 扫雷游戏
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                //注意:只有将自定义控件MineField拖到Form1中,才可以使用
                this.mineField1.Init(10,8);
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                this.mineField1.DisplayAll();
            }
    
        }
    }

    Pane.cs(继承自Button控件): 

    View Code
    /***************************************************************
     * 当前类用于封装方格,该方格继承自button控件(考虑到雷区中方格类似按钮)
     * 共有三个属性,三个方法
     * 注意事项:
     * 1.当某个方法暂时没去实现的时候,可以在方法体中写上:throw new NotImplementedException();
     * 2.表示方格状态的时候,使用到了枚举类型
     * *************************************************************/
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    namespace 扫雷游戏
    {
        /// <summary>
        /// 封装方格
        /// </summary>
        public class Pane:Button
        {
            /// <summary>
            /// 设置或获取当前方格是否埋有地雷
            /// </summary>
            public bool hasMine{get;set;}
            /// <summary>
            /// 设置或获取当前方格周围的地雷数
            /// </summary>
            public int aroundMineNums { get; set; }
    
            /// <summary>
            /// 获取或设置当前方格的状态
            /// </summary>
            public PaneState State{get;set;}
    
            public Pane()
            {
                this.BackgroundImageLayout = ImageLayout.Stretch;//设置方格的背景图以平铺的方式展现
            }
            /// <summary>
            /// 打开方格
            /// </summary>
            public void Open()
            {
                if (this.hasMine)//踩雷
                {
                    this.BackgroundImage = Properties.Resources.MineBomp;
                    this.Enabled=false;
                }
                else 
                {
                    switch (this.aroundMineNums)
                    {
                        case 0:
                            this.BackgroundImage=null;                       
                            break;
                        case 1:
                            this.BackgroundImage=Properties.Resources.Num1;
                            break;
                        case 2:
                            this.BackgroundImage=Properties.Resources.Num2;
                            break;
                        case 3:
                            this.BackgroundImage=Properties.Resources.Num3;
                            break;
                        case 4:
                            this.BackgroundImage=Properties.Resources.Num4;
                            break;
                        case 5:
                            this.BackgroundImage=Properties.Resources.Num5;
                            break;
                        case 6:
                            this.BackgroundImage=Properties.Resources.Num6;
                            break;
                        case 7:
                            this.BackgroundImage=Properties.Resources.Num7;
                            break;
                        case 8:
                            this.BackgroundImage=Properties.Resources.Num8;
                            break;
                    }
                    this.Enabled=false;
                }
            }
            /// <summary>
            /// 标记方格
            /// </summary>
            public void Mark()
            {
                this.BackgroundImage = Properties.Resources.Marked;
                this.State = PaneState.Marked;
            }
            /// <summary>
            /// 重置标记的方格
            /// </summary>
            public void Reset()
            {
                this.BackgroundImage = null;
                this.State = PaneState.Closed;
            }
        }
        /// <summary>
        /// 枚举类型
        /// 方格状态
        /// </summary>
        public enum PaneState 
        {
            /// <summary>
            /// 关闭状态
            /// </summary>
            Closed,
            /// <summary>
            /// 打开状态
            /// </summary>
            Opened,
            /// <summary>
            /// 标记状态
            /// </summary>
            Marked,
        }
    }

    用户自定义控件:MineField类(雷区) 

    View Code
    /***************************************************************
     * 自定义用户控件
     * 设计的时候,并没有往“雷区”中添加控件(即:小方格),控件主要是在运行的时候动态加载进来的
     * 要点:
     * 1.如何定义事件并引发事件
     * 2.综合考虑代码的可读性、可重用性,可将LayoutPane()方法独立出来
     * 3.设置方格的大小:pane.Size = new Size(paneWidth,paneHeight);
     * 4.设置方格的位置:pane.Location = new Point(paneLeft,paneTop);
     * 5.考虑到之后可能会对随机算法进行改变,故将随机布雷的方法抽象出来
     * 6.动态的事件绑定
     * *************************************************************/
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace 扫雷游戏
    {
        public partial class MineField : UserControl
        {
            /// <summary>
            /// 定义一个扫雷成功引发的事件
            /// </summary>
            /// <param name="sender">事件的发起者</param>
            /// <param name="e">事件向外部传递的参数</param>
            public delegate void MineSweepedSuccessEventHandler(object sender,EventArgs e);
            public event MineSweepedSuccessEventHandler MineSweepedSucces;
    
            /// <summary>
            /// 定义一个扫雷失败引发的事件
            /// </summary>
            /// <param name="sender">事件的发起者</param>
            /// <param name="e">事件向外部传递的参数</param>
            public delegate void MineSweepedFailEventHandler(object sender,EventArgs e);
            public event MineSweepedFailEventHandler MineSweepedFail;
    
            public MineField()
            {
                InitializeComponent();
            }
            
            /// <summary>
            /// 初始化雷区(即:将小方格动态加载到雷区中)
            /// </summary>
            /// <param name="paneLineCount">一个方向过去方格的数量</param>
            /// <param name="mineCount">整个雷区中地雷的数量</param>
            public void Init(int paneLineCount,int mineCount)
            {
                //根据指定的数量构建雷区中的方格
                for (int i = 0; i < paneLineCount * paneLineCount;i++ )
                {
                    Pane pane = new Pane();
                    this.Controls.Add(pane);//将自定义用户控件(方格)添加到"雷区"中
                }
                //布局雷区中方格的位置
                this.LayoutPane();
                //随机布雷
                this.LayoutMines(mineCount);
                //设置每个方格四周的地雷数
                foreach(Pane pane in this.Controls)
                {
                    pane.aroundMineNums = this.GetAroundMineCount(pane);
                }
            }
    
            /// <summary>
            /// 布局雷区中的所有方格的位置
            /// </summary>
            public void LayoutPane()
            {
                //初始化时,也会触发MineField_SizeChanged事件,而此时,雷区中的方格数为0
                if(this.Controls.Count==0)
                {
                    return;
                }
                int paneLineCount=(int)Math.Sqrt(this.Controls.Count);//获取一行或一列下来方格的数量
                int paneWidth=this.Width/paneLineCount;//方格的宽度
                int paneHeight=this.Height/paneLineCount;//方格的高度
                int paneIndex = 0;//方格的索引
                int paneTop = 0;
                int paneLeft = 0;
                for(int row=0;row<paneLineCount;row++)
                {
                    paneTop = row * paneHeight;//方格的TOP
                    for (int col = 0; col < paneLineCount; col++)
                    {
                        paneLeft = col * paneWidth;
                        Pane pane = this.Controls[paneIndex] as Pane;
                        //为每个方格动态的绑定MouseDown事件,当触发该事件时,会调用pane_MouseDown方法
                        //这其实是一个委托,将MouseDonw事件委托给pane_MouseDown方法
                        pane.MouseDown += pane_MouseDown;
                        //设置方格的大小                    
                        pane.Size = new Size(paneWidth,paneHeight);
                        //设置方格的位置
                        pane.Location = new Point(paneLeft,paneTop);
                        //索引递增
                        paneIndex++;
                    }
                }
            }
            /// <summary>
            /// 响应pane被鼠标点击时的操作
            /// </summary>
            /// <param name="sender">事件的发起对象</param>
            /// <param name="e"></param>
            private void pane_MouseDown(object sender, MouseEventArgs e)
            {
                Pane pane = sender as Pane;
                this.DisplayAround(pane);    
            }
    
            private void DisplayAround(Pane currentPane)
            {
                if(currentPane.State==PaneState.Opened||currentPane.hasMine)
                {
                    return;
                }
                currentPane.Open();
                List<Pane> panes = this.GetAroundPanes(currentPane);//得到当前pane四周的所有pane
                foreach(Pane p in panes)
                {
                    if (this.GetAroundMineCount(p) == 0)
                    {
                        DisplayAround(p);
                    }
                    else
                    {
                        if(p.State!=PaneState.Opened && !currentPane.hasMine)
                        {
                            p.Open();
                        }
                    }
                }
            }
    
            public void DisplayAll()
            { 
                foreach(Pane pane in this.Controls)
                {
                    if(pane.State!=PaneState.Opened)
                    {
                        pane.Open();
                    }
                }
            }
            /// <summary>
            /// 获取指定的方格四周的地雷数
            /// </summary>
            private int GetAroundMineCount(Pane pane)
            {
                List<Pane> panes = this.GetAroundPanes(pane);
                int mineCount = 0;
                foreach(Pane p in panes)
                {
                    if(p.hasMine)
                    {
                        mineCount++;
                    }
                }
                return mineCount;
            }
            /// <summary>
            /// 获取指定的方格四周的所有方格
            /// </summary>
            /// <returns></returns>
            private List<Pane> GetAroundPanes(Pane pane)
            { 
                List<Pane> result=new List<Pane>();
                foreach(Pane p in this.Controls)
                {
                    //左右方向
                    if(p.Top==pane.Top&&Math.Abs(p.Left-pane.Left)==p.Width)
                    {
                        result.Add(p);
                    }
                    //上下方向
                    if(p.Left==pane.Left&&Math.Abs(p.Top-pane.Top)==p.Height)
                    {
                        result.Add(p);
                    }
                    //45度斜角方向
                    if(Math.Abs(p.Top-pane.Top)==p.Height&&Math.Abs(p.Left-pane.Left)==p.Width)
                    {
                        result.Add(p);
                    }
                }
                return result;
            }
            /// <summary>
            /// 随机布雷:将HasMine的属性改为true即可
            /// </summary>
            /// <param name="mineCOunt">地雷的数量</param>
            private void LayoutMines(int mineCount)
            {
                Random rand = new Random();
                for (int i = 0; i < mineCount;i++ )
                {
                    int mineIndex=rand.Next(0,this.Controls.Count);
                    Pane pane=this.Controls[mineIndex] as Pane;
                    pane.hasMine = true;
                }
            }
            /// <summary>
            /// 当雷区的区域大小改变时,重新布置雷区中方格的大小和位置
            /// </summary>
            /// <param name="sender">事件的发起者</param>
            /// <param name="e"></param>
            private void MineField_SizeChanged(object sender, EventArgs e)
            {
                this.LayoutPane();
            }
        }
    }
  • 相关阅读:
    【读书笔记】iOS-网络-使用推送通知
    【读书笔记】iOS-网络-测试与操纵网络流量
    【读书笔记】iOS-网络-底层网络
    【读书笔记】iOS-网络-优化请求性能
    【读书笔记】iOS-网络-保护网络传输
    【读书笔记】iOS-网络-错误处理的经验法则
    【读书笔记】iOS-网络-三种错误
    【读书笔记】iOS-网络-理解错误源
    【读书笔记】iOS-网络-解析响应负载
    【读书笔记】iOS-网络-负载
  • 原文地址:https://www.cnblogs.com/hongfei/p/2822081.html
Copyright © 2020-2023  润新知