C#扫雷小游戏详细教程

利用 C# 写的扫雷小游戏(winform框架)

主要运用的知识点:
  • C#属性赋值
  • C#中数组的声明与使用
  • C#泛型集合的使用
  • C#继承关系
  • ,C#Random随机数对象

成功界面

游戏失败界面

有好多不足之处需要完善,欢迎大佬点评

本项目需要的全局变量

// 该项目的全局变量
        // 地雷数量
        int MinesS = 10;
        // 行
        int row=10;
        // 列
        int col = 8;
        // 格子的间隔
        int jiange = 2;
        // 边界
        int bodr = 10;
        // 格子的大小
        int sizes = 30;
        // 地图数组
        Minesbutton[,] mintarrery;
        // 随机数
        Random ran = new Random();
        // 存储所有格子的泛型集合
        List<Minesbutton> mineslist = new List<Minesbutton>();

声明继承于Button基类的Minesbutton

 public class Minesbutton : Button
        {
            // 横坐标
            public int abscissa  { get; set; }
            // 纵坐标
            public int ordinate { get; set; }
            // 内容信息
            public string content { get; set; }
            // 是否判定过
            public bool isbool { get; set; }
        }

地图布局

 // 地图布局
        private void Buju()
        {
            mintarrery = new Minesbutton[col,row];
            // 循环行
            for (int i = 0; i < row; i++)
            {
                // 循环列
                for (int j = 0; j < col; j++)
                {
                    // 初始化一个新的方格
                    Minesbutton minesbtn = new Minesbutton();

                    // 指定该方格的宽度和高度
                    minesbtn.Width = minesbtn.Height = sizes;

                    // 字体的颜色
                    minesbtn.ForeColor = Color.Black;

                    // 设置方格的位置
                    minesbtn.Location = new Point(bodr + ((sizes + jiange) * j), +bodr + ((sizes + jiange) * i));

                    // 格子的横坐标
                    minesbtn.abscissa = j;

                    //  格子的的纵坐标
                    minesbtn.ordinate = i;

                    // 默认格子显示的内容信息为空
                    minesbtn.content = string.Empty;
                    minesbtn.BackgroundImage = Image.FromFile(@"../../imgs/wall.png");
                    minesbtn.BackgroundImageLayout = ImageLayout.Stretch;

                    // 把初始化后的格子对象放入数组内
                    mintarrery[j, i] = minesbtn;
                    Controls.Add(minesbtn);
                    // 绑定单击事件
                    minesbtn.Click += Minesbtn_Click;
                    mineslist.Add(minesbtn);
                }
            }           
        }       

地雷的生成

// 地雷的生成
        private void Newmines()
        {
            // 地雷个数
            int mines = MinesS;
            while (mines > 0)
            {             
                int ranrow = ran.Next(row);

                int rancol = ran.Next(col);

                if (mintarrery[rancol, ranrow].content == string.Empty)
                {
                    // 设置显示内容为雷
                    mintarrery[rancol, ranrow].content = "雷";
                    //mintarrery[rancol, ranrow].BackgroundImage = Image.FromFile(@"../../imgs/Mines.png");
                    mines -= 1;
                }
            }
        }

每个格子的单击事件

 // 格子单击事件
        int x=0;
        private void Minesbtn_Click(object sender, EventArgs e)
        {
            x = 0;
            Minesbutton minesbtn = sender as Minesbutton;
            // 通过sender传递被点的格子的横坐标和纵坐标
            Saolei(minesbtn.abscissa, minesbtn.ordinate);
            //MessageBox.Show("横坐标" + minesbtn.abscissa.ToString() + "纵坐标" + minesbtn.ordinate.ToString());                                                     
               for (int i = 0; i < mineslist.Count; i++)
                {
                    if (mineslist[i].isbool == true)
                    {
                        x++;
                        if (x == col * row - MinesS)
                        {
                        MessageBox.Show("成功");
                            x = 0;
                            ShuaxinMap();
                        }
                    }
                }
        }

判断点击的是否是雷

// 判断是不是雷
        private bool ISmines(int hengzuobiao,int zongzuobiao)
        {
            // 先声明变量默认表示不是雷
            bool jieguo = false;
            // 指定范围在整个地图内
            if (hengzuobiao>=0&&hengzuobiao<col&&zongzuobiao>=0&&zongzuobiao<row)
            {
                // 是否被判断过
                if (mintarrery[hengzuobiao,zongzuobiao].isbool==false)
                {
                    // 判断内容是不是雷
                    if (mintarrery[hengzuobiao,zongzuobiao].content=="雷")
                    {
                        jieguo = true;
                    }
                }
            }
            return jieguo;
        }

扫雷(主要逻辑)

  // 扫雷
        private void Saolei(int hengzuobiao,int zongzuobiao)
        {
            List<Minesbutton> minesbuttons = new List<Minesbutton>();
            minesbuttons.Add(mintarrery[hengzuobiao,zongzuobiao]);
            // 循环集合成员
            while (minesbuttons.Count>0)
            {
                int heng = minesbuttons[0].abscissa;
                int zong = minesbuttons[0].ordinate;
                // 周围雷数
                int mines = 0;
                if (ISmines(heng,zong)==true)
                {
                    minesbuttons.Clear();
                    mintarrery[heng, zong].BackgroundImage = Image.FromFile(@"../../imgs/Mines.png");
                    MessageBox.Show("游戏结束!");
                    ShuaxinMap();
                }
                // 不是雷的情况
                else
                {
                    // 判断周围的雷八个方向
                    if (ISmines(heng - 1,zong)==true)
                    {
                        mines += 1;
                    }
                    if (ISmines(heng, zong-1) == true)
                    {
                        mines += 1;
                    }
                    if (ISmines(heng-1 , zong +1) == true)
                    {
                        mines += 1;
                    }
                    if (ISmines(heng-1,zong-1)==true)
                    {
                        mines += 1;
                    }
                    if (ISmines(heng + 1, zong) == true)
                    {
                        mines += 1;
                    }
                    if (ISmines(heng, zong +1) == true)
                    {
                        mines += 1;
                    }
                    if (ISmines(heng + 1, zong-1) == true)
                    {
                        mines += 1;
                    }
                    if (ISmines(heng + 1, zong + 1) == true)
                    {
                        mines += 1;
                    }

                 
                    minesbuttons[0].isbool = true;
                    minesbuttons[0].BackColor = Color.Wheat;
                    minesbuttons[0].BackgroundImage = null;
                    // 周围没雷
                    if (mines==0)
                    {
                         minesbuttons.AddRange(zhouweimines(heng,zong));
                    }
                    else
                    {
                        mintarrery[heng, zong].Text = mines.ToString();
                    }
                    
                    minesbuttons.RemoveAt(0);
                }

            }
        }

周围格子(主要逻辑)

      // 周围格子
        private List<Minesbutton> zhouweimines(int heng,int zong)
        {
            // 存储周围格子
            List<Minesbutton> mineslist = new List<Minesbutton>(8);
            // 点击的不是最左边
            if (heng > 0)
            {
                // 点击的不是最上边的格子
                if (zong > 0)
                {
                    // 左上方有格子,没被判断过
                    if (mintarrery[heng - 1, zong - 1].isbool == false)
                    {
                        mineslist.Add(mintarrery[heng - 1, zong - 1]);
                    }
                }
                // 点击的不是最下面
                if (zong + 1 < row)
                {
                    // 左下方有格子,没被判断过
                    if (mintarrery[heng - 1, zong + 1].isbool == false)
                    {
                        mineslist.Add(mintarrery[heng - 1, zong + 1]);
                    }
                }
                // 点击的不是最左边,左边还有,没被判断过
                if (mintarrery[heng - 1,zong].isbool==false)
                {
                    mineslist.Add(mintarrery[heng-1,zong]);
                }
            }
            // 点击的格子的行数加1小于列数,为最右边的左边的格子
            if (heng+1<col)
            {
                // 点击的为不是最上面的格子
                if (zong>0)
                {
                    // 右上角有格子,没被判断过
                    if (mintarrery[heng+1,zong-1].isbool==false)
                    {
                        mineslist.Add(mintarrery[heng +1, zong - 1]);
                    }
                    // 点击的为最下面的上一个
                    if (zong+1<row)
                    {
                        // 右下角有格子,没被判断过
                        if (mintarrery[heng + 1, zong + 1].isbool == false)
                        {
                            mineslist.Add(mintarrery[heng + 1, zong + 1]);
                        }
                    }
                    // 点击的为右边的格子,没被判断过
                    if (mintarrery[heng+1,zong].isbool==false)
                    {
                        mineslist.Add(mintarrery[heng + 1, zong]);
                    }
                }
            }
            // 点击的不是最上面的格子,上面还有格子
            if (zong>0)
            {
                // 上方有格子,没被判断过
                if (mintarrery[heng,zong-1].isbool==false)
                {
                    mineslist.Add(mintarrery[heng , zong-1]);
                }
            }
            // 点击的不是最下面的格子,下面还有格子
            if (zong+1<row)
            {
                // 下方有格子,没被判断过
                if (mintarrery[heng,zong+1].isbool==false)
                {
                    mineslist.Add(mintarrery[heng, zong + 1]);
                }
            }
           
            return mineslist;
        }

刷新地图

 private void ShuaxinMap()
        {
            foreach (Minesbutton item in mineslist)
            {
                item.Dispose();
            }
            Buju();
            Newmines();
        }

窗体加载事件

  private void Form1_Load(object sender, EventArgs e)
        {
            Buju();
            Newmines();
        }
  • 27
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值