• 更新后的扫雷V2.0


    很久没有更新博客了,我都有些想她了

    回家时途经朋友那里,在北大青鸟教室里灵感迸发,扫雷 V2.0 由此而生,较V1.0 巨大革新,尤其是UI。新的窗体更好看,更人性化,工作去支持拖动,支持不同级别以及自定义方案扫雷,效能还可以。感觉相当好了!

    自己先赞一个!

    接下来看代码吧。





     

    //Mines.cs  主文件

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms;

     

    namespace Mines

    {

        public partial class Mines : Form

        {

            //分别用于存储左键单击数,右键单击数,左右键单击数之和,累计时间,剩余雷数,行,列,雷数,方块总数,完成正确判断的方块数

            int leftCounter, rightCounter, bothCounter, TimeCounter, RestOfMines, Row, Line, NumOfMines, BlockNumber, tmrCounter;

            //雷方块控件数组

            Label[,] lblBlock;

            //计算并存储数字方块周围的雷数目

            int[] MinesCounter;

            //存储对雷方块是否揭开,是否为雷,是否标示的判断值

            bool[] IsCovered,IsMine,IsJudge;

            //用于拖动窗体,前者记录鼠标的相对位置,后者记录鼠标左键的状态

            Point MouseOff;

            bool LeftFlag;

            //用来记录结束游戏的方式

            internal enum Result

            {

                Lose,

                Win

            }

     

            public Mines()

            {

                InitializeComponent();

            }

            //初始化函数,创建并初始化所有手动控件

            public void Compose(int numRow, int numLine, int numMines)

            {

                Row = numRow;

                Line = numLine;

                BlockNumber = Row * Line;

                NumOfMines = numMines;

                lblBlock = new Label[Row, Line];           //按需创建方块

                MinesCounter = new int[BlockNumber];

                IsCovered = new bool[BlockNumber];

                IsMine = new bool[BlockNumber];

                IsJudge = new bool[BlockNumber];

                this.Size = new Size(110 + 23 * Line, 162 + 23 * Row);  //窗体适应控件大小

     

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

                    for (int j = 0; j < Line; j++)

                    {

                        lblBlock[i, j] = new Label();

                        this.Controls.Add(lblBlock[i, j]);

                        lblBlock[i, j].Left = 49 + 23 * j;

                        lblBlock[i, j].Top = 66 + 23 * i;

                        lblBlock[i, j].Width = 24;

                        lblBlock[i, j].Height = 24;

                        lblBlock[i, j].Name = (i * Line + j).ToString();

                        lblBlock[i, j].BorderStyle = BorderStyle.FixedSingle;

                        lblBlock[i, j].TextAlign = ContentAlignment.MiddleCenter;

                        lblBlock[i, j].Font = new Font("微软雅黑", 10.6F, FontStyle.Regular);

                        lblBlock[i, j].MouseDown += new MouseEventHandler(this.lblBlock_MouseDown);           //手动添加事件,下同

                        lblBlock[i, j].MouseUp += new MouseEventHandler(this.lblBlock_MouseUp);                   

                        lblBlock[i, j].BackColor = Color.FromArgb(95, 170, 200);

                       

                        int index = i * Line + j;   //二维索引转换为一维索引

                        IsCovered[index] = true;

                        IsMine[index] = false;

                        IsJudge[index] = false;

                        MinesCounter[index] = 0;

                    }

                Startup();       //初始化其他变量

            }

            //轻量初始化其他变量

            public void Startup()

            {

                leftCounter = rightCounter = bothCounter = 0;

                TimeCounter = 0;

                RestOfMines = NumOfMines;

                lblTime.Text = "时间 0 s";

               

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

                    for(int j=0;j<Line;j++)

                    {                   

    lblBlock[i,j].Text="";

                        lblBlock[i, j].BackColor = Color.FromArgb(95,170,200);

     

                        int index=i*Line+j;

                        IsCovered[index]=true;

                        IsMine[index]=false;

    IsJudge[index]=false;

    MinesCounter[index]=0;

    }

                CreateMines();   //生成雷

                CountMines();   //计算剩下的方块上的数字

                tmrMines.Start();    //开始计算剩余雷数及其他事件

            }

            //生成雷

            public void CreateMines()

            {

                Random random=new Random();

                List<int> listMines = new List<int>(RestOfMines);

                int MineOrder;

                while (listMines.Count < RestOfMines)

                {

                    MineOrder = random.Next(0, BlockNumber);

                    if (!listMines.Contains(MineOrder))   //生成不重复的所需量的随机数

                    {

                        listMines.Add(MineOrder);

                        IsMine[MineOrder] = true;

                    }

                }

            }

            //计算剩余方块上的数字

            public void CountMines()

            {

                for(int index=0;index<BlockNumber;index++)

                    for(int i=index/Line-1;i<index/Line+2;i++)   //一维索引转换为二维索引,下同

                        for (int j = index % Line-1; j < index % Line + 2; j++)

                        {

                            if (i < 0 || i >= Row || j < 0 || j >= Line)  //避免数组越界

                                continue;

                            if (i * Line + j== index)

                                continue;

                            if (IsMine[i  * Line + j] == true)

                                MinesCounter[index]++;

                        }

            }

            //顾名思义,推零函数(方法),挖开数字为零的方块时向周围拓展

            public void PutZero(int p)

            {

                int index;

                for(int i=p/Line-1;i<p/Line+2;i++)

                    for (int j = p % Line-1; j < p % Line + 2; j++)

                    {

                        index = Line * i  + j;

                        if (i < 0 || i >= Row || j < 0 || j >= Line)

                            continue;

                        if (IsMine[index]||IsJudge[index])  //跳过含雷或者挖开的方块(或许判断含雷在这有些多余?)

                            continue;

                        if(MinesCounter[index]!=0)

                            lblBlock[i , j ].Text = MinesCounter[index].ToString();

                        lblBlock[i , j ].BackColor = Color.FromArgb(190,220,245);

                        IsCovered[index] = false;   //记录方块的状态

                    }

            }

            //结束游戏方法

            private void GameOver(Result result)

            {

                tmrMines.Stop();

                tmrTime.Stop();    //一轮游戏结束,计时器停止工作

                if (result==Result.Lose)

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

                        for(int j=0;j < Line;j++ )

                        {

                            if (IsMine[i*Line+j])

                            {

                                lblBlock[i,j].Text = "雷";

                                lblBlock[i,j].BackColor = Color.FromArgb(250,65,50);

                            }

                        }

                ResultBox boxResult = new ResultBox(result,ref TimeCounter);

                boxResult.ShowDialog();   //调用结果窗体,显示游戏结果

                Startup();

            }

            //程序启动时自动构建并初始化所有控件

            private void Mines_Load(object sender, EventArgs e)

            {

                Compose(16,16,40);

            }

     

            private void lblBlock_MouseDown(Object sender, MouseEventArgs e)

            {

                switch (e.Button)

                {

                    case MouseButtons.Left:

                        leftCounter++;

                        bothCounter++;

                        break;

                    case MouseButtons.Right:

                        rightCounter++;

                        bothCounter++;

                        break;

                }

            }

     

            private void lblBlock_MouseUp(Object sender, MouseEventArgs e)

            {

                Label bClick = (Label)sender;

                int index = int.Parse(bClick.Name);

                switch (e.Button)

                {

                    case MouseButtons.Left:

                        leftCounter++;

                        bothCounter++;

                        break;

                    case MouseButtons.Right:

                        rightCounter++;

                        bothCounter++;

                        break;

                }

                //推雷事件

                if (bothCounter >= 3)

                {

                    int counter = 0;

                    if (IsCovered[index] == false)

                    {

                        for (int i = index / Line-1; i < index / Line + 2; i++)

                            for (int j = index % Line-1; j < index % Line + 2; j++)

                            {

                                if (i < 0 || i >= Line || j < 0 || j >= Row)

                                    continue;

                                if (IsMine[Line * i + j ] && IsJudge[Line * i + j ])

                                    counter++;

                                if (!IsMine[Line * i + j] && IsJudge[Line * i + j ])

                                    counter = -9;

                            }

                        if (counter == MinesCounter[index])

                            PutZero(index);

                        if (counter < 0)

                            GameOver(Result.Lose);                   

                    }               

                }

                //单击方块事件

                else if (leftCounter == 2)

                {              

                    if (!tmrTime.Enabled)

                        tmrTime.Start();    //揭开第一个方块时开始计算时间

                    if (IsCovered[index] == false || IsJudge[index]) ;   //跳过揭开了的方块和标注了的方块

                    else if (IsMine[index])

                    {

                        GameOver(Result.Lose);            //不幸踩雷

                    }

                    else

                    {

                        if(MinesCounter[index]!=0 )

                            lblBlock[index / Line, index % Line].Text = MinesCounter[index].ToString();     //无雷的方块显示对应的数字(0除外)

                        bClick.BackColor = Color.FromArgb(190, 220, 250);

                        IsCovered[index] = false;

                    }               

                }

                //标注雷或取消标注事件

                else if (rightCounter == 2)

                {

                    if (IsCovered[index] == false) ;      //跳过揭开了的方块

                    else if (IsJudge[index])

                    {

                        bClick.Text = "";          //取消标注

                        bClick.BackColor = Color.FromArgb(95, 170, 200);

                        IsJudge[index] = false;

                        RestOfMines += 1;

                    }

                    else

                    {

                        bClick.Text = "!";          //标注雷

                        bClick.BackColor = Color.Orange;

                        IsJudge[index] = true;

                        RestOfMines -= 1;

                    }

                }

                leftCounter = rightCounter = bothCounter = 0;     //初始化状态变量

            }

     

            private void tmrMines_Tick(object sender, EventArgs e)

            {

                tmrCounter = 0;   //初始化该变量,用来记录完成正确判断的方块数

                lblMines.Text = "还有 " + RestOfMines.ToString() + "个雷";     //实时显示剩余雷数

                for (int index = 0; index < BlockNumber; index++)

                {

                    if (IsJudge[index] == true && IsMine[index] == true || IsCovered[index] == false)

                        tmrCounter++;

                    if (MinesCounter[index]==0&&IsCovered[index]==false)

                        PutZero(index);    //当有零方块被揭开时,调用推零函数挖开周围一圈

                }

                if (tmrCounter == BlockNumber)

                {     //正确判断并完成了所有扫雷工作

                    for (int index = 0; index < BlockNumber; index++)

                    {

                        IsMine[index] = false;

                        IsCovered[index] = true;

                    }

                    GameOver(Result.Win);      //游戏以赢的方式结束并重新开始

                    Startup();

                }           

            }

     

            private void tmrTime_Tick(object sender, EventArgs e)

            {           

                lblTime.Text = "时间 " + (TimeCounter++/10).ToString() + " s";    //实时显示时间

            }

            //开局

            private void tsmStartup_Click(object sender, EventArgs e)

            {

                if (tmrTime.Enabled)

                    tmrTime.Stop();

                Startup();

            }

            //退出

            private void tsmExit_Click(object sender, EventArgs e)

            {

                this.Close();

            }

            //关于

            private void tsmAbout_Click(object sender, EventArgs e)

            {

                AboutBox About = new AboutBox();

                About.ShowDialog();           

            }

            //设置(自定义)

            private void tsmCostom_Click(object sender, EventArgs e)

            {

                InitializeBox Initialize = new InitializeBox();

                Initialize.ShowDialog();

                if (Initialize.SetRow * Initialize.SetLine * Initialize.SetMines!=0)

                {

                    Row = Initialize.SetRow;

                    Line = Initialize.SetLine;

                    NumOfMines = Initialize.SetMines;

                    foreach(Label Block in lblBlock)

                        Block.Dispose();    //在重新创建控件前释放控件

                    Compose(Row, Line, NumOfMines);

                }

            }       

            //以下事件用于拖动窗体

            private void Mines_MouseDown(object sender, MouseEventArgs e)

            {           

                MouseOff = new Point(- (e.X+5), - (e.Y+27));   //记录鼠标开始时相对窗体的位置,常数为有框窗体的偏差

                LeftFlag = true;  //记录鼠标左键的状态,true为被按下

            }

     

            private void Mines_MouseMove(object sender, MouseEventArgs e)

            {

                if (LeftFlag)

                {

                    Point MouseSet = Control.MousePosition;   //记录鼠标的动态位置(引用)

                    MouseSet.Offset(MouseOff.X, MouseOff.Y);   //计算窗体相对于鼠标的新位置

                    Location = MouseSet;

                }

            }

     

            private void Mines_MouseUp(object sender, MouseEventArgs e)

            {

                if (LeftFlag)

                    LeftFlag = false;    //鼠标左键松开

            }

        }

    }


     


    //InitializeBox.cs  收集扫雷所需方案信息的窗体 重要

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms;

     

    namespace Mines

    {

        public partial class InitializeBox : Form

        {

            internal int SetRow, SetLine, SetMines;  //三个变量分别存储扫雷方案的行数,列数,和雷数

            Point MouseOff;

            bool LeftFlag;

     

            public InitializeBox()

            {

                SetRow = 0;

                SetLine = 0;

                SetMines = 0;

                InitializeComponent();

            }

            //低级扫雷方案,9*9网格 10个雷

            private void rbLow_CheckedChanged(object sender, EventArgs e)

            {

                lblLow.ForeColor = Color.Black;

                lblMiddle.ForeColor = Color.DimGray;

                lblAdvanced.ForeColor = Color.DimGray;

                lblRow.ForeColor = Color.DimGray;

                lblLine.ForeColor = Color.DimGray;

                lblMines.ForeColor = Color.DimGray;

                tbRow.Enabled = false ;

                tbLine.Enabled = false;

                tbMines.Enabled = false;      

                btnOK.Enabled = true;

            }

            //中级扫雷方案  16*16网格 40个雷

            private void rbMiddle_CheckedChanged(object sender, EventArgs e)

            {

                lblLow.ForeColor = Color.DimGray;

                lblMiddle.ForeColor = Color.Black;

                lblAdvanced.ForeColor = Color.DimGray;

                lblRow.ForeColor = Color.DimGray;

                lblLine.ForeColor = Color.DimGray;

                lblMines.ForeColor = Color.DimGray;           

                tbRow.Enabled = false;

                tbLine.Enabled = false;

                tbMines.Enabled = false;

                btnOK.Enabled = true;

            }

            //高级扫雷方案  16*30网格 99个雷

            private void rbAdvanced_CheckedChanged(object sender, EventArgs e)

            {

                lblLow.ForeColor = Color.DimGray;

                lblMiddle.ForeColor = Color.DimGray;

                lblAdvanced.ForeColor = Color.Black;

                lblRow.ForeColor = Color.DimGray;

                lblLine.ForeColor = Color.DimGray;

                lblMines.ForeColor = Color.DimGray;           

                tbRow.Enabled = false;

                tbLine.Enabled = false;

                tbMines.Enabled = false;

                btnOK.Enabled = true;

            }

            //自定义方案

            private void rbCostom_CheckedChanged(object sender, EventArgs e)

            {

                lblLow.ForeColor = Color.DimGray;

                lblMiddle.ForeColor = Color.DimGray;

                lblAdvanced.ForeColor = Color.DimGray;

                lblRow.ForeColor = Color.Black;

                lblLine.ForeColor = Color.Black;

                lblMines.ForeColor = Color.Black;

                tbRow.Enabled = true;

                tbLine.Enabled = true;

                tbMines.Enabled = true;

            }

            //计时器用于判定所需信息是否集齐

            private void tmr_Tick(object sender, EventArgs e)

            {

                if (tbRow.TextLength > 0 && tbLine.TextLength > 0 && tbMines.TextLength > 0 || !rbCostom.Checked)

                    btnOK.Enabled = true;

                else

                    btnOK.Enabled = false;

            }

            //收集扫雷所需方案信息

            private void btnOK_Click(object sender, EventArgs e)

            {

                if (rbLow.Checked)

                {

                    SetRow = 9;

                    SetLine = 9;

                    SetMines = 10;

                }

                else if (rbMiddle.Checked)

                {

                    SetRow = 16;

                    SetLine = 16;

                    SetMines = 40;

                }

                else if (rbAdvanced.Checked)

                {

                    SetRow = 16;

                    SetLine = 30;

                    SetMines = 99;

                }

                else

                {

                    SetRow = int.Parse(tbRow.Text);

                    SetLine = int.Parse(tbLine.Text);

                    SetMines = int.Parse(tbMines.Text);               

                }

                if (SetRow * SetLine > SetMines)

                    this.Close();

                else

                    lblInitialize.Text = "您输入有误,请重新输入!";

            }

     

            private void btnClose_Click(object sender, EventArgs e)

            {

                this.Close();

            }

     

            private void InitializeBox_MouseDown(object sender, MouseEventArgs e)

            {

                MouseOff = new Point(-e.X, -e.Y);

                LeftFlag = true;

            }

     

            private void InitializeBox_MouseMove(object sender, MouseEventArgs e)

            {

                if (LeftFlag)

                {

                    Point MouseSet = Control.MousePosition;

                    MouseSet.Offset(MouseOff.X, MouseOff.Y);

                    Location = MouseSet;

                }

            }

     

            private void InitializeBox_MouseUp(object sender, MouseEventArgs e)

            {

                if (LeftFlag)

                    LeftFlag = false;           

            }

     

            private void InitializeControl_MouseDown(object sender, MouseEventArgs e)

            {

                Control conTemp = (Control)sender;    //独创当前控件引用

                MouseOff = new Point(-(conTemp.Location.X + e.X), -(conTemp.Location.Y + e.Y));

                LeftFlag = true;

            }

        }

    }

    知识共享许可协议
    作品Wave创作,采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
  • 相关阅读:
    2-7-配置iptables防火墙增加服务器安全
    2-6-搭建无人执守安装服务器
    2-4-搭建FTP服务器实现文件共享
    第一阶段连接
    在mfc中如何显示出系统时间
    关于const
    第三章类图基础
    算法分析的数学基础
    第十二章 派生类
    学好C++该看什么书呢?
  • 原文地址:https://www.cnblogs.com/sanwave/p/2129095.html
Copyright © 2020-2023  润新知