前言

这里给出教程原文地址

该项目已经放在github上托管。

绘制雷区

这一节我们主要涉及界面中雷区的绘制。绘制雷区需要三个变量来保存雷区行数、列数、以及地雷的数量。而且我们希望能够自动获取上次游戏的设置(初级,中级,高级,雷区的三个变量值不同)。因此这三个变量的值需要保存下来。我们在这里采用Setting文件来保存这些数据。工程创建的时候,系统会自动生成一个Setting文件。因此我们不需要自己创建,只需要使用原有的Setting文件即可。在右方解决方案资源管理器面板中展开Properties,右击Settings.settings,选择打开即可。

按照下图对它进行设置,设置完成后按Ctrl + S进行保存。

我们需要一个paint事件来进行绘制雷区,选中主窗口,在左边的属性面板中,单击事件按钮,并找到Paint事件,双击该条目,系统会自动创建一个事件,我们将在这里绘制雷区。如下图所示:

绘制雷区时我们需要考虑以下几点:

  • 我们需要定义三个基本变量行数、列数、地雷的数量,并初始化。
  • 我们需要一个二重的循环来绘制雷区,我们假定雷区为32×32的小方块,并且四周有一圈宽度为1的留白,用于与其它雷区区别,这样,每个雷区的实际大小为34×34。
  • 整个雷区距离上下左右边缘都应该有个间距,所以需要一个偏移量。
  • 我们需要Form窗口自动调整大小,来适应这个雷区的绘制。
private int Sweep_width;      //雷区中的列数
private int Sweep_high; //雷区中的行数
private int Sweep_num; //雷区中的地雷数量
private int nOffsetX; //雷区绘制时的偏移量,距离窗口左边缘的距离
private int nOffsetY; //雷区绘制时的偏移量,距离窗口上边缘的距离 public Form_Main()
{
//初始化操作
InitializeComponent();
nOffsetX = 6; //初始化偏移量
nOffsetY = 6 + UpMenu.Height; //初始化偏移量,UpMenu是菜单栏控件
Sweep_num = Properties.Settings.Default.Sweep_num; //初始化,从Settings读取地雷数量
Sweep_high = Properties.Settings.Default.Sweep_high; //初始化,从Settings读取行数
Sweep_width = Properties.Settings.Default.Sweep_width; //初始化,从Settings读取列数
UpdateSize(Sweep_width,Sweep_high); //自适应窗口大小
}
private void Form_Main_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics; //绘制句柄
for (int i = 0; i < Sweep_width; i++)
{
for (int j = 0; j < Sweep_high; j++)
{
g.FillRectangle(Brushes.Violet, new Rectangle(nOffsetX + 34 * i, nOffsetY + 34 * j + 1, 32, 32)); //绘制每一个小方块
}
}
}
private void UpdateSize(int width_temp, int high_temp)
{
//根据雷区行数,列数,来设置整个Form窗口的大小
int width_update = width_temp * 34 + 12;
int high_update = high_temp * 34 + 12;
Width = width_update + (this.Size.Width - this.ClientSize.Width);
Height = high_update + UpMenu.Height + TableLayoutPanel_Main.Height + (this.Size.Height - this.ClientSize.Height);
}

最后按Ctrl + F5编译运行,得到最终结果:

下面我们为了使鼠标移动到雷区上时,能有高亮的效果做一些修改。首先我们需要能找到鼠标当前所在的位置,因此我们需要MouseMove事件,找到MouseMove事件,双击该条目:

我们需要定义新的变量Point来方便我们标记鼠标的位置,鼠标的每次移动并不是都要重新刷新界面,当鼠标从某个32x32的小雷区移动到另一个32x32的小雷区时,我们就需要更改高亮的位置。我们需要采集的是当前鼠标处于哪一个32x32的小雷区,代码如下:

应增加变量:

 private Point mousefocus_new; //鼠标新位置
private Point mousefocus_old; //鼠标旧位置

应对这两个变量初始化,在public Form_Sweeper(){ }中增加如下代码:

mousefocus_new.X = mousefocus_old.X = 0;            //初始化鼠标位置
mousefocus_new.Y = mousefocus_old.Y = 0;

记录鼠标位置,其中变量mousefocus_new是此刻位置、moursefocus_old是上一时刻位置,两者进行对比,来判断当前鼠标处于的32x32的小雷区是否发生改变。代码如下:

private void Form_Main_MouseMove(object sender, MouseEventArgs e)
{
//x,y相当于雷区二维数组中的第几行,第几列。
int x = (e.X - nOffsetX) / 34 + 1;
int y = (e.Y - nOffsetY) / 34 + 1;
mousefocus_new.X = x;
mousefocus_new.Y = y;
if (e.X < nOffsetX || e.Y < nOffsetY)
{
//鼠标位置不在雷区时
mousefocus_new.X = mousefocus_new.Y = -1;
Refresh();
}
else if (mousefocus_new != mousefocus_old)
{
mousefocus_old = mousefocus_new;
Refresh();
}
}

Paint事件应做修改,代码如下:

for (int i = 0; i < Sweep_width; i++)
{
for (int j = 0; j < Sweep_high; j++)
{
if (i + 1 == mousefocus_new.X && j + 1 == mousefocus_new.Y)
{
g.FillRectangle(new SolidBrush(Color.FromArgb(100, Color.Violet)), new Rectangle(nOffsetX + 34 * i, nOffsetY + 34 * j + 1, 32, 32)); //产生高亮
}
else
{
g.FillRectangle(Brushes.Violet, new Rectangle(nOffsetX + 34 * i, nOffsetY + 34 * j + 1, 32, 32));
}
}
}

此时,按Ctrl + F5编译运行,发现屏幕会闪屏,在初始化模块增加如下代码:

this.DoubleBuffered = true;                         //双缓冲技术,减少屏幕闪屏

最后按Ctrl + F5编译运行,得到最终结果:

扫雷游戏制作过程(C#描述):第三节、雷区绘制的更多相关文章

  1. 扫雷游戏制作过程(C#描述):第二节、界面设计

    前言 这里给出教程原文地址. 该项目已经放在github上托管. 扫雷界面设计 界面的设计,首先需要创建一个菜单栏.具体方法在左边找到工具箱窗口,展开其中的菜单和工具栏,找到MenuStrip选项,双 ...

  2. 扫雷游戏制作过程(C#描述):第五节、菜单操作(续)

    前言 这里给出教程原文地址. 该项目已经放在github上托管. 发布版已经分享到百度网盘 菜单操作(续) 接着节前一章节的内容,我们继续完善菜单栏的功能. 我们首先,先完善Rank的选项,我们希望我 ...

  3. 扫雷游戏制作过程(C#描述):第四节、菜单操作

    前言 这里给出教程原文地址. 该项目已经放在github上托管. 菜单操作 我们现在的程序单击菜单的时候不会有任何反应,这一节我们主要介绍菜单的相关代码,使得菜单能够正常使用. 现在我们希望在对应级别 ...

  4. 扫雷游戏制作过程(C#描述):第一节、创建项目

    前言 起初做扫雷是同学在做,我也跟着做了.做的比较low,其实第一次做这种东西,自己对自己的要求也不高,注重在了解一下,一个app应用程序是怎么产生的..net开发平台,用c#敲的.建议大家一些不懂的 ...

  5. Unity3D_(游戏)2D简单游戏制作过程:捕获高空掉落保龄球

      游戏介绍:通过鼠标的左右移动,可以控制帽子的移动,当帽子接到下落的保龄球时,会出现火花效果.没有接到保龄球时,保龄球落到草地上,过10S后会自动消失. 实现效果: 素材+Unity3D源代码:传送 ...

  6. [NOIP2015 普及组] 扫雷游戏

    [NOIP2015 普及组] 扫雷游戏 难度:入门 题目描述 扫雷游戏是一款十分经典的单机小游戏.在nn行mm列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开 ...

  7. C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式

    C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...

  8. 洛谷 P2670 扫雷游戏==Codevs 5129 扫雷游戏

    题目描述 扫雷游戏是一款十分经典的单机小游戏.在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有 ...

  9. 关于Cocos2d-x开发一个游戏的过程自述

    我在2016年12月6号完成了我的第一个自己独立完成的游戏,期间遇到各种各样的问题和困难,但是幸运的是问题都一一被解决了,现在我想总结一个整个的制作游戏的过程 使用的环境是VS2013+cocos2d ...

随机推荐

  1. VIM的字符编码设置

    vim 编码方式的设置和所有的流行文本编辑器一样,Vim 可以很好的编辑各种字符编码的文件,这当然包括UCS-2.UTF-8 等流行的 Unicode 编码方式.然而不幸的是,和很多来自 Linux ...

  2. python_求相邻数

    什么是相邻数? 比如5,相邻数为4和6,和5相差1的数,连续相差为1的一组数 需求: 遍历inputList 所有数字,取出所有数字,判断是否有相邻数, 不相邻数字 和 相邻数字 都以 “数组”形式 ...

  3. Masonry1.0.2 源码解析

    在了解Masonry框架之前,有必要先了解一下自动布局的概念.在iOS6之前,UI布局的方式是通过frame属性和Autoresizing来完成的,而在iOS6之后,苹果公司推出了AutoLayout ...

  4. java参数传递

    关于方法的参数传递,java中方法的参数传递均为值传递,根据传递的类型以及方法中对参数的处理可以分为2类: 1.传递参数为基本数据类型,因为是值传递,所以方法运行结束后对传递参数的值无影响. 2.传递 ...

  5. HTML的第一课

    今天是第一天学习HTML,老师讲的内容不是很多,内容也比较简单.但是标签的数量很多,在做作业时十分不熟练,很多标签需要重新看它的意思.而且有很多标签在一起用的时候容易搞混.学的标签中有很多地方是通用的 ...

  6. navicat for mysql只导出数据表结构(转)

    选中需要导出表结构的数据库,右键,在显示的菜单中选择"数据传输"这一项 ,在弹出窗口中"数据传输"单击选择"高级"一项,在"高级& ...

  7. SQL练习题完整(做完你就是高手)

    SQL 练习题答案 一.补充作业一.   设有三个关系:                S(SNO, SNAME, AGE, SEX,Sdept)                SC(SNO, CNO ...

  8. Fedora删除旧版本内核

    由于Fedora升级非常快,因此非常有必要清除陈旧的内核,否则的话,每次登录系统会出现多个引导项,看着烦人也占用内存: 1.查看当前使用的内核 [root@w ~]# uname -r 4.9.14- ...

  9. ACL权限控制列表

    1.查看文件系统是否支持ACL (xfs文件系统强制开启ACL,如果该分区已格式化为xfs,在使用dumpe2fs会看不到superblocks信息)zheng@ubuntu16:~$ sudo du ...

  10. 【Spring 核心】装配bean(二) JavaConfig装配

    前面介绍完了组件扫描和自动装配,这里再来看一下装配bean的另一种方式JavaConfig. 包路径: src/main/java com.bonc-|--config--|--CDPlayerCon ...