欢迎来到 IT实训基地-南通科迅教育
咨询电话:0513-81107100
WinForm做的扫雷
2018/4/17
科迅教育
1186
南通Java培训课程有用吗

今天来做一个扫雷程序。先放图:

 图片1.jpg

为了方便识别每个变量的意思,这里起名中文,为了方便,但是各位同学不要培养自己用中文起名字的坏习惯:

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 WindowsFormsApplication2

{

   

public partial class Form1 : Form

{

/// <summary>

/// 我们自己定义一个雷的方格按钮控件 继承自Button按钮

/// </summary>

public class 雷方格 : Button

{

// 在原来的基础上添加三个变量 

// 当前方格所在的横坐标

public int 横坐标 { get; set; }

 

// 当前方格所在的纵坐标

public int 纵坐标 { get; set; }

 

// 当前方格显示的内容信息 有无雷 雷的个数等等

public string 内容信息 { get; set; }

 

// 标记此雷有没有被判过

public bool 是否判定过 { get; set; }

}

 

private const int 雷数量 = 36;

private const int 字体大小 = 7;

private const int 矩阵边界 = 10;

private const int 矩阵行数 = 12;

private const int 矩阵列数 = 9;

private const int 矩阵间隙 = 2;

private const int 方格宽度 = 30;

private 雷方格[,] 方格矩阵数组;

private FontFamily 字体样式 = FontFamily.Families[0];

 

 

public Form1()

{

InitializeComponent();

this.矩阵布局();

this.随机布雷();

this.注册点击事件();

}

 

/// <summary>

/// 把方格矩阵布局到窗体的方法函数

/// </summary>

private void 矩阵布局()

{

// 矩阵数组初始化一个新的对象 列乘以行的一个矩阵

this.方格矩阵数组 = new 雷方格[矩阵列数, 矩阵行数];

 

// 循环添加每一行 每一行的列数自然取决于列的个数

for (int  = 0;  < 矩阵行数; ++)

{

// 同理循环添加每一列

for (int  = 0;  < 矩阵列数; ++)

{

// 初始化一个新的方格

雷方格 方格 = new 雷方格();

 

// 指定该方格的宽度和高度

方格.Width = 方格.Height = 方格宽度;

 

// 设置方格上显示的信息的字体样式

方格.Font = new Font(this.字体样式, 字体大小, FontStyle.Bold);

 

// 字体的颜色

方格.ForeColor = Color.FromArgb(0x9A, 0xCD, 0x32);

 

// 设置方格的位置

方格.Location = new Point(矩阵边界 + ((方格宽度 + 矩阵间隙) * ), +矩阵边界 + ((方格宽度 + 矩阵间隙) * ));

 

// 指定方格的横坐标

方格.横坐标 = ;

 

//  指定方格的纵坐标

方格.纵坐标 = ;

 

// 指定方格显示的内容信息 暂且为什么都不显示为空

方格.内容信息 = string.Empty;

 

// 把初始化后的方格对象放入数组内

this.方格矩阵数组[, ] = 方格;

 

// 最终把这些方格全部放到窗体上

this.Controls.Add(方格);

}

}

 

// 设置窗体宽度 可以更具自己的情况来计算和放偏移量

this.Width = 矩阵边界 * 3 + (方格宽度 + 矩阵间隙) * 矩阵列数 + 矩阵间隙 * 2;

 

// 设置窗体高度

this.Height = SystemInformation.CaptionHeight + 矩阵边界 * 3 + (方格宽度 + 矩阵间隙) * 矩阵行数 + 矩阵间隙 * 2;


}

 

/// <summary>

///  矩阵布雷方法

/// </summary>

private void 随机布雷()

{

// 新声明一个随机对象

System.Random 随机 = new System.Random();

 

// 新建一个临时变量“雷数量临时变量”取值与 之前定义的“雷数量”

int 雷数量临时变量 = 雷数量;

 

// 开始循环随机布雷 只要这个临时变量大于0 也就是还有雷需要布

while (雷数量临时变量 > 0)

{

// 随机生成一个行数 0到行数的上限

int 随机行 = 随机.Next(矩阵行数);

 

// 同理生成一个随机列数

int 随机列 = 随机.Next(矩阵列数);

 

// 然后再判断是否有重复 如果内容是空的 则表示没有随机过这个坐标

if (this.方格矩阵数组[随机列, 随机行].内容信息 == string.Empty)

{

// 就给个 这个标记表示 当前这个方格为雷

this.方格矩阵数组[随机列, 随机行].内容信息 = "";

 

 // 测试代码 

 //this.方格矩阵数组[随机列, 随机行].Text = "";

 

// 成功随机一个雷后 临时变量减去一个 

雷数量临时变量 -= 1;

}

}

}

 

private void 方格点击事件(object sender, System.EventArgs e)

{

// 测试代码

雷方格 当前方格 = (雷方格)sender;

//MessageBox.Show(当前方格.横坐标.ToString()+"--"+ 当前方格.纵坐标.ToString());

 

this.踩雷与扫雷(当前方格.横坐标, 当前方格.纵坐标);

 

}

 

private void 注册点击事件()

{

// 遍历窗体下所有方格

foreach (雷方格 方格 in this.Controls)

{

// 每个方格注册一个点击事件

方格.Click += 方格点击事件;

}

}

 

/// <summary>

/// 判定当前点击的方格是否是雷

/// </summary>

/// <param name="横坐标"></param>

/// <param name="纵坐标"></param>

/// <returns></returns>

private bool 是否是雷(int 横坐标, int 纵坐标)

{

// 申明一个判定结果假设不是雷

bool 判定结果 = false;

 

// 坐标范围限制,不能是负数 也不能超过矩阵的行数和列数的上限

if (横坐标 >= 0 && 横坐标 < 矩阵列数 && 纵坐标 >= 0 && 纵坐标 < 矩阵行数)

{

// 如果指定的方格没有判定过的才可以判定

if (this.方格矩阵数组[横坐标,纵坐标].是否判定过 == false)

{

// 如果是随机布局的雷

if (this.方格矩阵数组[横坐标, 纵坐标].内容信息 == "")

{

// 那么返回是雷

判定结果 = true;

}

}

}

// 最后返回这个结果

return 判定结果;

}

 

/// <summary>

/// 把周围的雷全部收集起来放入一个列表里

/// </summary>

/// <param name="横坐标"></param>

/// <param name="纵坐标"></param>

/// <returns></returns>

private List<雷方格> 收集周围雷群(int 横坐标, int 纵坐标)

{

// 申明一个放群雷的列表 满打满算有8

List<雷方格> 群雷列表 = new List<雷方格>(8);

 

// 如果点击的方格不是最左边

if (横坐标 > 0)

{

// 如果点击的方格不是最上边的方格

if (纵坐标 > 0)

{

// 那么左上角是有方格的 又如果这个方格没有判定过

if (this.方格矩阵数组[横坐标 - 1, 纵坐标 - 1].是否判定过 == false)

{

// 则把这个方格放入列表里

群雷列表.Add(this.方格矩阵数组[横坐标 - 1, 纵坐标 - 1]);

}

}

// 如果点击的方格不是最下面的方格

if (纵坐标 + 1 < 矩阵行数)

{

// 并且左下方是有方格的 又如果这个方格没有判定过的话

if (this.方格矩阵数组[横坐标 - 1, 纵坐标 +1].是否判定过 == false)

{

// 这个左下方的方格就放入列表里

群雷列表.Add(this.方格矩阵数组[横坐标 - 1, 纵坐标 + 1]);

}

}

// 点击的方格不是最左边的话 左边还有一个方格 并且没有判定过的话

if (this.方格矩阵数组[横坐标 - 1, 纵坐标 ].是否判定过 == false)

{

// 把左边这个方格放入列表里

群雷列表.Add(this.方格矩阵数组[横坐标 - 1, 纵坐标]);

}

}


// 点击的方格+1小于列数的话说明点击的方格是最右边的左边一个方格

if (横坐标 + 1 < 矩阵列数)

{

// 再如果不是最上边的那个的话

if (纵坐标 > 0)

{

// 那么右上角是有方格的 这个方格没有判定过的话

if (this.方格矩阵数组[横坐标 + 1, 纵坐标 - 1].是否判定过 == false)

{

// 把这个方格放入列表

群雷列表.Add(this.方格矩阵数组[横坐标 + 1, 纵坐标 - 1]);

}

}

// 再如果点击的这个方格是最下面的上面一个的话

if (纵坐标 + 1 < 矩阵行数)

{

// 那么点击的方格的右下方是有方格的 这个方格没有判定过的话

if (this.方格矩阵数组[横坐标 + 1, 纵坐标 + 1].是否判定过 == false)

{

// 把这个方格放入列表里

群雷列表.Add(this.方格矩阵数组[横坐标 + 1, 纵坐标 + 1]);

}

}

// 右边一定是有方格的 这个方格没有判定过的话

if (this.方格矩阵数组[横坐标 + 1, 纵坐标].是否判定过 == false)

{

// 把这个方格放入列表里

群雷列表.Add(this.方格矩阵数组[横坐标 + 1, 纵坐标]);

}

}

 

// 左右两边的都计算过了 剩下上面和下面的了 

// 如果点击的不是最上面的方格 上面方是有方格的

if (纵坐标 > 0)

{

// 如果上方的方格没有判定过

if (this.方格矩阵数组[横坐标 , 纵坐标 - 1].是否判定过 == false)

{

// 把上方的方格放入列表里

群雷列表.Add(this.方格矩阵数组[横坐标 , 纵坐标 - 1]);

}

}

 

// 同样的判定是否是最下面的上面一个方格

if (纵坐标 + 1 < 矩阵行数)

{

// 如果下面有方格且没有判定过

if (this.方格矩阵数组[横坐标, 纵坐标 + 1].是否判定过 == false)

{

// 把这个方格放入列表里

群雷列表.Add(this.方格矩阵数组[横坐标, 纵坐标 + 1]);

}

}

// 最终方法得到这个周围雷群的列表集合

return 群雷列表;

}

 

/// <summary>

/// 扫雷游戏的核心代码-踩雷与扫雷

/// </summary>

/// <param name="横坐标"></param>

/// <param name="纵坐标"></param>

private void 踩雷与扫雷(int 横坐标, int 纵坐标)

{

// 首先需要创建一个缓存列表用来把所有需要递归

// 遍历的雷方格通通塞到这个缓存列表里慢慢消化

List<雷方格> 缓存列表 = new List<雷方格>();

 

// 当前这个也不列外先放进来

缓存列表.Add(this.方格矩阵数组[横坐标, 纵坐标]);

 

// 开始循环遍历,退出的条件当然是没有可以循环的

// 方格了也就是说列表成员=0了就没有了可以退出了

while (缓存列表.Count > 0)

{

//  我们总是从列表的第一个方格开始判定起,程序里第0个就是第一个

// 我的先得到第一个方格的横坐标的值

int 当前横坐标 = 缓存列表[0].横坐标;

 

// 以及纵坐标的值

int 当前纵坐标 = 缓存列表[0].纵坐标;

 

// 声明一个雷数计数变量 一开始假设没有雷

int 周围雷数 = 0;

 

// 这里就用到了之前写的辅助方法 判定当前坐标下的方格是不是雷 如果是

if (this.是否是雷(当前横坐标, 当前纵坐标) == true)

{

// 把列表清除掉 工作结束了。

缓存列表.Clear();

 

// 弹出框 展示噩耗。

MessageBox.Show("失败了");

}

else

{

// 如果不是雷 那么就开始 周围一圈一个个判定是不是雷 是的话 计数变量就加1

if (this.是否是雷(当前横坐标 - 1, 当前纵坐标) == true) 周围雷数++;

// 以下是周围八个方向的方格是否雷的判定 省略。。。 

if (this.是否是雷(当前横坐标 - 1, 当前纵坐标 - 1) == true) 周围雷数++;

if (this.是否是雷(当前横坐标, 当前纵坐标 - 1) == true) 周围雷数++;

if (this.是否是雷(当前横坐标 + 1, 当前纵坐标 - 1) == true) 周围雷数++;

if (this.是否是雷(当前横坐标 + 1, 当前纵坐标) == true) 周围雷数++;

if (this.是否是雷(当前横坐标 + 1, 当前纵坐标 + 1) == true) 周围雷数++;

if (this.是否是雷(当前横坐标, 当前纵坐标 + 1) == true) 周围雷数++;

if (this.是否是雷(当前横坐标 - 1, 当前纵坐标 + 1) == true) 周围雷数++;

 

// 判定过了的话,那么把“是否判定过”的标帜置成true;

缓存列表[0].是否判定过 = true;

 

// 不管当前是不是雷踩过了就设置背景颜色为暗灰色来区别对待

缓存列表[0].BackColor = SystemColors.ScrollBar;

 

// 如果雷数是0的话收集周围的雷群

if (周围雷数 == 0)

{

// 把之前写的收集雷的方法带进去,方法返回的是雷方格的集合

// 所以缓存列表用的是AddRange方法-即添加范围

缓存列表.AddRange(this.收集周围雷群(当前横坐标, 当前纵坐标));

}

// 如果周围有雷

else

{

// 那么当前点击的方格也就是踩的雷显示周围雷的数量

// 记住“周围雷数”是int 整型变量要.ToString()转成字符串类型

this.方格矩阵数组[当前横坐标, 当前纵坐标].Text = 周围雷数.ToString();

 

// 为了把周围雷数看清楚点我们把雷数量的字体用深色显示出来

this.方格矩阵数组[当前横坐标, 当前纵坐标].ForeColor = SystemColors.WindowText;

}

// 处理完一个当前踩的雷后 把它从缓存里移除

缓存列表.RemoveAt(0);

}

}

}

}

}

这期就到这里,下期再见。

 

 

 

 


77
关闭
先学习,后交费申请表
每期5位名额
在线咨询
免费电话
QQ联系
先学习,后交费
TOP
您好,您想咨询哪门课程呢?
关于我们
机构简介
官方资讯
地理位置
联系我们
0513-91107100
周一至周六     8:30-21:00
微信扫我送教程
手机端访问
南通科迅教育信息咨询有限公司     苏ICP备15009282号     联系地址:江苏省南通市人民中路23-6号新亚大厦三楼             法律顾问:江苏瑞慈律师事务所     Copyright 2008-