更新后的扫雷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 国际许可协议进行许可。欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
原文地址:https://www.cnblogs.com/sanwave/p/2129095.html