• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

C#可视化编程课设《扫雷》游戏的设计和实现

武飞扬头像
耕耘_2001
帮助1

随着期末的到来,可视化编程结课了,我们要做一个课设,我选择了《扫雷》游戏,在制作过程中也是参考网上的资源完成的,这里我做一个小总结,给我的大学留点证据。

首先第一步就是创建一个Form窗体,然后添加一个控件。这里我添加了一个Button控件和三个Lable控件,一个Timer控件,还有一个MenuStrip控件,如图所示

学新通

建立之后就要实现“方格”了,这里使用了一个二维的Button数组来生成这些方格,如图 

学新通

 以下是生成方块的代码

  1.  
    public partial class Form1 : Form
  2.  
    {
  3.  
    public Form1()
  4.  
    {
  5.  
    InitializeComponent();
  6.  
    }
  7.  
     
  8.  
    private int XNum; //一行方块的数目
  9.  
    private int YNum; //一列方块的数目
  10.  
    private int MineNum; //雷的总数
  11.  
    private int RestMine;//剩余的雷数
  12.  
    private int CostTime = 0; //所用时间
  13.  
    private int MineWidth = 40;//雷方块的大小(宽度为40)
  14.  
    private Button[,] Mines;
  15.  
    private int[,] Turn; //==-1 表示这个位置已经翻开;
  16.  
    //==0 表示这个位置没有翻开;
  17.  
    //==1 表示这个位置插上红旗;
  18.  
    private void Form1_Load(object sender, EventArgs e)
  19.  
    {
  20.  
    panel1.Visible=false;//游戏未开始时,panel里的控件不可见
  21.  
     
  22.  
    Turn = new int[XNum, YNum];
  23.  
    Mines = new Button[XNum, YNum];
  24.  
    for (int x = 0; x < XNum; x = 1)
  25.  
    for (int y = 0; y < YNum; y = 1)
  26.  
    {
  27.  
    Mines[x, y] = new Button();
  28.  
    this.Controls.Add(Mines[x, y]);
  29.  
    Mines[x, y].Left = 13 MineWidth * x;
  30.  
    Mines[x, y].Top = 75 MineWidth * y;
  31.  
    Mines[x, y].Width = MineWidth;
  32.  
    Mines[x, y].Height = MineWidth;
  33.  
    Mines[x, y].Font = new Font("7SEG76", 18F, FontStyle.Bold, GraphicsUnit.Point,130);
  34.  
    Mines[x, y].BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
  35.  
    Mines[x, y].Name = "Mines" (x y * XNum).ToString();
  36.  
    Mines[x, y].MouseUp = new MouseEventHandler(bt_MouseUp);
  37.  
    Mines[x, y].Visible = false;
  38.  
    Mines[x, y].BackColor = Color.Gray;
  39.  
    }
  40.  
    }

 然后是布雷

  1.  
    private void LayMines()// 布雷
  2.  
    {
  3.  
    int x, y;
  4.  
    Random s = new Random();
  5.  
    //取随机数
  6.  
    for (int i = 0; i < MineNum;)
  7.  
    {
  8.  
    //取随机数
  9.  
    x = s.Next(XNum);
  10.  
    y = s.Next(YNum);
  11.  
    if (Convert.ToInt16(Mines[x, y].Tag) != 1)//==1时,代表这个位置是地雷
  12.  
    {
  13.  
    Mines[x, y].Tag = 1;//修改属性为雷
  14.  
    i ;
  15.  
    }
  16.  
    }
  17.  
    }

获取方块周围的雷数

  1.  
    ///
  2.  
    /// 获取某个小方块区域相邻8个区域的雷个数
  3.  
    ///
  4.  
    private int GetAroundNum(int row, int col)
  5.  
    {
  6.  
    int i, j;
  7.  
    int around = 0;
  8.  
    int minRow = (row == 0) ? 0 : row - 1;
  9.  
    int maxRow = row 2;
  10.  
    int minCol = (col == 0) ? 0 : col - 1;
  11.  
    int maxCol = col 2;
  12.  
    for (i = minRow; i < maxRow; i )
  13.  
    {
  14.  
    for (j = minCol; j < maxCol; j )
  15.  
    {
  16.  
    if (!IsInMineArea(i, j))//判断是否在扫雷区域
  17.  
    continue;
  18.  
    if (Convert.ToInt16(Mines[i, j].Tag) == 1) around ;
  19.  
    }
  20.  
    }
  21.  
    return around;
  22.  
    }

判断是否在雷区以及无雷区的拓展

  1.  
    ///
  2.  
    /// 判断是否在扫雷区域
  3.  
    ///
  4.  
    private bool IsInMineArea(int row, int col)
  5.  
    {
  6.  
    return (row >= 0 && row < XNum && col >= 0 && col < YNum);
  7.  
    }
  8.  
     
  9.  
    ///
  10.  
    ///雷方块拓展(对于周围无雷的空白区域)
  11.  
    ///
  12.  
    private void ExpandMines(int row, int col)
  13.  
    {
  14.  
    int i, j;
  15.  
    int minRow = (row == 0) ? 0 : row - 1;
  16.  
    int maxRow = row 2;
  17.  
    int minCol = (col == 0) ? 0 : col - 1;
  18.  
    int maxCol = col 2;
  19.  
    int around = GetAroundNum(row, col);
  20.  
    //对周围一个雷都没有的空白区域拓展
  21.  
    if (around == 0)
  22.  
    {
  23.  
    Mines[row, col].Enabled = false;
  24.  
    for (i = minRow; i < maxRow; i )
  25.  
    {
  26.  
    for (j = minCol; j < maxCol; j )
  27.  
    {
  28.  
    //对于周围可以拓展的区域进行的规拓展
  29.  
    if (!IsInMineArea(i, j)) continue;
  30.  
    if (!(i == row && j == col) && Mines[i, j].Enabled != false)
  31.  
    //&& Convert.ToInt16(Mines[i,j].Tag)!= 1
  32.  
    {
  33.  
    ExpandMines(i, j);
  34.  
    Mines[i, j].BackColor = Color.White;
  35.  
    }
  36.  
    Mines[i, j].Enabled = false;//周围无雷的区域按钮无效
  37.  
    if (GetAroundNum(i, j) != 0) //周围无雷**********6--28
  38.  
    { Mines[i, j].Text = GetAroundNum(i, j).ToString();
  39.  
    Mines[i, j].BackColor = Color.White;
  40.  
    }
  41.  
    }
  42.  
    }
  43.  
    }
  44.  
    }

胜利判断以及事件的处理

  1.  
    ///
  2.  
    /// 胜利判断并处理
  3.  
    ///
  4.  
    private bool Victory()// 检测是否胜利
  5.  
    {
  6.  
    for (int i = 0; i < XNum; i )
  7.  
    for (int j = 0; j < YNum; j )
  8.  
    {
  9.  
    //没翻开且未标示,则未成功
  10.  
    if (Mines[i, j].Enabled == true && Turn[i, j] != 1) return false;
  11.  
    //不是雷却误标示为雷,则也未成功
  12.  
    if (Convert.ToInt16(Mines[i, j].Tag) != 1 && Turn[i, j] == 1) return false;
  13.  
    }
  14.  
    return true;
  15.  
    }

接下来是最重要的一个函数,就是鼠标点击的处理事件

  1.  
    //
  2.  
    //添加按钮控件Click事件与处理方法bt_Click:
  3.  
    //
  4.  
    private void bt_MouseUp(object sender, MouseEventArgs e) //这里处理事件方法
  5.  
    {
  6.  
    String btName;
  7.  
    Button bClick = (Button)sender;//将被击的按钮赋给定义的bClick变量
  8.  
    btName = bClick.Name;//获取按钮的Name
  9.  
    int n = Convert.ToInt16(btName.Substring(5));
  10.  
    int x = n % XNum;
  11.  
    int y = n / XNum;
  12.  
    switch (e.Button)//通过按钮Name属性来判断是哪个Button被点击,并执行相应的操作
  13.  
    {
  14.  
    case MouseButtons.Left:
  15.  
    System.Media.SoundPlayer sp = new System.Media.SoundPlayer(Properties.Resources.knock);
  16.  
    sp.Play();
  17.  
    sp.Dispose();
  18.  
    if (Convert.ToInt16(Mines[x, y].Tag) != 1)
  19.  
    {
  20.  
    Mines[x, y].BackgroundImage = null;
  21.  
    Mines[x, y].BackColor = Color.White;
  22.  
    if (GetAroundNum(x, y) != 0) //周围无雷**********6--28
  23.  
    Mines[x, y].Text = GetAroundNum(x, y).ToString();
  24.  
    Mines[x, y].Enabled = false;
  25.  
    ExpandMines(x, y);
  26.  
    if (Victory())
  27.  
    {
  28.  
    System.Media.SoundPlayer spp = new System.Media.SoundPlayer(Properties.Resources.victory);
  29.  
    spp.Play();
  30.  
    spp.Dispose();
  31.  
    show();// 判断是否胜利,是则将地图中所有雷标识出来
  32.  
    timer1.Enabled = false;//停止计时
  33.  
    MessageBox.Show("恭喜你!排雷成功!", "游戏结束");
  34.  
    Abate();
  35.  
    }
  36.  
    }
  37.  
    else
  38.  
    {
  39.  
    System.Media.SoundPlayer spp = new System.Media.SoundPlayer(Properties.Resources.bang);
  40.  
    spp.Play();
  41.  
    spp.Dispose();
  42.  
    Mines[x, y].BackgroundImage = Properties.Resources.mine1;
  43.  
    timer1.Enabled = false;//停止计时
  44.  
    show();
  45.  
    MessageBox.Show("很遗憾!您踩雷了!", "游戏结束");
  46.  
    Abate();
  47.  
    }
  48.  
    break;
  49.  
    case MouseButtons.Right:
  50.  
    System.Media.SoundPlayer ssp = new System.Media.SoundPlayer(Properties.Resources.flag1);
  51.  
    ssp.Play();
  52.  
    ssp.Dispose();
  53.  
    Mines[x, y].BackgroundImage = Properties.Resources.flag;
  54.  
    if (Turn[x, y] == 1)//表示这个位置插上红旗
  55.  
    {
  56.  
    Turn[x, y] = 0;//取消红旗,表示这个位置没有翻开
  57.  
    RestMine ;
  58.  
    Mines[x, y].BackgroundImage = null;
  59.  
    }
  60.  
    else
  61.  
    {
  62.  
    Turn[x, y] = 1;//表示这个位置插上红旗
  63.  
    RestMine--;
  64.  
    }
  65.  
    lblMine.Text = RestMine.ToString();
  66.  
    if (Victory())
  67.  
    {
  68.  
    System.Media.SoundPlayer spp = new System.Media.SoundPlayer(Properties.Resources.victory);
  69.  
    spp.Play();
  70.  
    spp.Dispose();
  71.  
    timer1.Enabled = false;//停止计时
  72.  
    MessageBox.Show("恭喜你!排雷成功!", "游戏结束");
  73.  
    Abate();
  74.  
    }
  75.  
    break;
  76.  
    }
  77.  
    }

还有一个游戏初始化函数

  1.  
    private void GameInit()//游戏初始化
  2.  
    {
  3.  
    for (int x = 0; x < XNum; x = 1)
  4.  
    for (int y = 0; y < YNum; y = 1)
  5.  
    {
  6.  
    Mines[x, y].Text = "";
  7.  
    Mines[x, y].Visible = true;
  8.  
    Mines[x, y].Enabled = true;
  9.  
    Mines[x, y].Tag = null;
  10.  
    Mines[x, y].BackgroundImage = null;
  11.  
    Turn[x, y] = 0;
  12.  
    Mines[x, y].BackColor = Color.Gainsboro;
  13.  
    }
  14.  
    LayMines();
  15.  
    }

接下来就是一些比较简单的函数了,比如雷区的显示,计时器计数等

  1.  
    private void show()//将地图中所有雷标识出来
  2.  
    {
  3.  
    for (int i = 0; i < XNum; i )
  4.  
    for (int j = 0; j < YNum; j )
  5.  
    if (Convert.ToInt16(Mines[i, j].Tag) == 1)//==1时,代表这个位置是地雷
  6.  
    {
  7.  
    Mines[i, j].BackgroundImage = Properties.Resources.mine;
  8.  
    }
  9.  
    }
  10.  
     
  11.  
    private void timer()//计时器计时,清零
  12.  
    {
  13.  
    lblTime.Text = "0";
  14.  
    CostTime = 0;
  15.  
    lblTime.Text = CostTime.ToString();
  16.  
    }
  17.  
    private void Abate()//游戏结束时使方块失效
  18.  
    {
  19.  
    for (int x = 0; x < XNum; x = 1)
  20.  
    for (int y = 0; y < YNum; y = 1)
  21.  
    {
  22.  
    Mines[x, y].Enabled = false;
  23.  
    }
  24.  
    }
  25.  
    private void clear() //清除方块
  26.  
    {
  27.  
    for (int x = 0; x < XNum; x = 1)
  28.  
    for (int y = 0; y < YNum; y = 1)
  29.  
    {
  30.  
    Mines[x, y].Enabled = false;
  31.  
    Mines[x, y].Visible = false;
  32.  
    }
  33.  
    }

最后就是一些按钮的Click事件

  1.  
    private void button2_Click(object sender, EventArgs e)
  2.  
    {
  3.  
    show();//将地图中所有雷标识出来
  4.  
    }
  5.  
     
  6.  
    private void btnStart_Click_1(object sender, EventArgs e)
  7.  
    {
  8.  
    System.Media.SoundPlayer sp = new System.Media.SoundPlayer(Properties.Resources.start);
  9.  
    sp.Play();
  10.  
    sp.Dispose();
  11.  
    GameInit();//游戏初始化
  12.  
    lblTime.Text = "0";
  13.  
    timer();
  14.  
    timer1.Enabled = true;
  15.  
    }
  16.  
     
  17.  
    private void timer1_Tick(object sender, EventArgs e)
  18.  
    {
  19.  
    CostTime ;
  20.  
    lblTime.Text = CostTime.ToString();
  21.  
    }

代码部分到这里就结束了,最后给大家来几张成品图

学新通学新通

 最后提醒一下,在程序中有音效的调用,如果你借用该代码的时候一到删除这些代码,否则会报错。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcacfk
系列文章
更多 icon
同类精品
更多 icon
继续加载