基于C#—WPF的扫雷游戏
自学教材:《C#入门经典(第六版)》,1月28日购入,1月29日到2月9日学习了前十六章,由于有C语言基础,在语法阶段学习起来比较轻松,不过在接触到面向对象的时候遇到了一些困难,对于一些概念的理解着实费了一些功夫,不过最后还是成功的理解了。整个程序的设计从2月10日开始,在2月12日程序基本完成。2月13日将已知的BUG都清除完毕。
扫雷很简单。一个程序的核心就是数据结构与算法,我选择的数据结构是二维数组,算法也很简单,就是很简单的利用bool属性做标记以及翻牌的递归。
首先是雷块类的实现,因为翻开雷块是利用单击,所以我在雷块类中继承了Button基类,使它具有Button类的所有特性。同时定义了几个bool属性,分别表示是不是雷(IsMine),有没有被翻开(IsOpened),有没有被标记(IsFlagged)。还有int属性代表周围雷数(MineAround),最大的行列数(MaxRow、MaxColumn),不是雷的个数(MaxNoMineNum),以及翻开之后显示的图片背景back,代码如下:
class Pane :Button
{
public Image back = new Image();
public int MaxNoMineNum
{ get; set; }
public int MaxRow
{ get; set; }
public int MaxColumn
{ get; set; }
public bool IsMine
{ get; set; }
public int MineAround
{ get; set; }
public bool IsFlagged
{ get; set; }
public bool IsOpened
{ get; set; }
public Pane(bool isMine)
{
IsMine = isMine; } }
Pane Class
另外一个非常重要的类就是雷区类,为了方便,我将雷区做成了一个窗口,并根据用户选择难度的不同,向里面的Canvas控件动态加载我的雷块“Button”,同时在上面实现了计时器和重新开始按钮。
根据难度不同,在初始化函数里定义了int形参Level,传递参数0为初级,1为中级,2为高级,分别按不同的雷数以及雷区大小初始化。初始化函数比较简单故不将代码列出。
最重要的是单击事件,每次单击至少翻开一个雷块,如果该雷块周围没有雷(MineAround==0),则翻开他周围的雷块。这就要用到递归。同时应注意,一旦该雷块被翻开之后就不应该再次翻开他。否则就会无限递归下去直到栈溢出抛出StackOverFlow异常。所以应该在单击的事件处理程序中加入一个条件判断,在没有翻开(IsFlagged==false)的时候才执行。同时应注意边界上的雷块递归的处理,不能让数组越界。具体代码见下:
private void PaneField_Click(object sender, RoutedEventArgs e)
{
if(IsTimerStart==false)
{
IsTimerStart = true;
myTimer.Start();
}
if(IsWining()&&WiningJudge==true&&IsGameOver==false)
{
IsGameOver = true;
WiningJudge = false;
for (int i = ; i < paneField[,].MaxRow; i++)
for (int j = ; j < paneField[,].MaxColumn; j++)
{
PaneField_Click(paneField[i, j], e);
}
System.Threading.Thread.Sleep();
Wining w = new Wining();
w.Show();
System.Threading.Thread.Sleep();
this.Close();
}
if (!Field.Children.Contains((sender as Pane).back))
{
int Row, Column;
Pane t = (sender as Pane);
(sender as Pane).IsOpened = true;
Field.Children.Remove((UIElement)sender);
Field.Children.Add((sender as Pane).back);
if(t.IsMine==true && LosingJudge==true&&IsGameOver==false)
{
IsGameOver = true;
LosingJudge = false;
for(int i=;i<t.MaxRow;i++)
for(int j=;j<t.MaxColumn;j++)
{ PaneField_Click(paneField[i, j], e);
}
Losing l = new Losing();
l.Show();
Thread.Sleep();
this.Close();
}
//递归
if (t.MineAround == )
{
GetRowAndColumn(t, out Row, out Column, t.MaxRow, t.MaxColumn);
#region 四个角
if (Row == && Column == && t.IsMine == false) //左上角
{
PaneField_Click(paneField[, ], e);
PaneField_Click(paneField[, ], e);
PaneField_Click(paneField[, ], e);
}
else if (Row == && Column == t.MaxColumn - && t.IsMine == false) //右上角
{
PaneField_Click(paneField[, t.MaxColumn - ], e);
PaneField_Click(paneField[, t.MaxColumn - ], e);
PaneField_Click(paneField[, t.MaxColumn - ], e);
}
else if (Row == t.MaxRow - && Column == && t.IsMine == false) //左下角
{
PaneField_Click(paneField[t.MaxRow - , ], e);
PaneField_Click(paneField[t.MaxRow - , ], e);
PaneField_Click(paneField[t.MaxRow - , ], e);
}
else if (Row == t.MaxRow - && Column == t.MaxColumn - && t.IsMine == false) //右下角
{
PaneField_Click(paneField[t.MaxRow - , t.MaxColumn - ], e);
PaneField_Click(paneField[t.MaxRow - , t.MaxColumn - ], e);
PaneField_Click(paneField[t.MaxRow - , t.MaxColumn - ], e);
}
#endregion
#region 四条边
else if (Row == && Column != && Column != t.MaxColumn - && t.IsMine == false) //上边
{
for (int p = Row; p <= Row + ; p++)
for (int q = Column - ; q <= Column + ; q++)
{
bool b = Field.Children.Contains(paneField[p, q].back);
if (!(p == Row && q == Column) && b == false)
PaneField_Click(paneField[p, q], e);
}
}
else if (Row == t.MaxRow - && Column != && Column != t.MaxColumn - && t.IsMine == false) //下边
{
for (int p = Row - ; p <= Row; p++)
for (int q = Column - ; q <= Column + ; q++)
{
bool b = Field.Children.Contains(paneField[p, q].back);
if (!(p == Row && q == Column) && b == false)
PaneField_Click(paneField[p, q], e);
}
}
else if (Column == && Row != t.MaxRow - && Row != && t.IsMine == false) //左边
{
for (int p = Row - ; p <= Row + ; p++)
for (int q = Column; q <= Column + ; q++)
{
bool b = Field.Children.Contains(paneField[p, q].back);
if (!(p == Row && q == Column) && b == false)
PaneField_Click(paneField[p, q], e);
}
}
else if (Column == t.MaxColumn - && Row != t.MaxRow - && Row != && t.IsMine == false) //右边
{
for (int p = Row - ; p <= Row + ; p++)
for (int q = Column - ; q <= Column; q++)
{
bool b = Field.Children.Contains(paneField[p, q].back);
if (!(p == Row && q == Column) && b == false)
PaneField_Click(paneField[p, q], e);
}
}
#endregion
#region 其他位置
else if (t.IsMine == false)
for (int p = Row - ; p <= Row + ; p++)
for (int q = Column - ; q <= Column + ; q++)
{
bool b = Field.Children.Contains(paneField[p, q].back);
if (!(p == Row && q == Column) && b == false)
PaneField_Click(paneField[p, q], e);
}
#endregion
}
}
}
PaneField_Click
其中的GetRowAndColumn方法在PaneField中定义,通过Pane对象的Equals方法来得到该元素在二维数组中的下标并利用out形参返回。IsWining方法也在类中定义为私有方法,通过统计翻开数与不是雷的个数是否相等来判断是否胜利。
至此,扫雷中比较复杂和重要的两个类就介绍完毕了。其他的类or窗口(难度选择,输赢提示)都非常简单,故不再赘述。通过编写这个程序,让我很好的应用了这十几天学习的.Net知识,自己的编程功夫也有了一些长进。希望开学之后能够继续进步,取得更大的成就!
基于C#—WPF的扫雷游戏的更多相关文章
- wpf版扫雷游戏
近来觉得wpf做出来的界面很拉风,自己也很喜欢搞些小游戏,感觉这做出来的会很炫,很装逼,(满足自己的一点小小的虚荣心)于是就去自学,发现感觉很不错,可是属性N多,太多了,而且质料也少,很多不会用,只会 ...
- 基于jQuery经典扫雷游戏源码
分享一款基于jQuery经典扫雷游戏源码.这是一款网页版扫雷小游戏特效代码下载.效果图如下: 在线预览 源码下载 实现的代码. html代码: <center> <h1>j ...
- (转载)WinformGDI+入门级实例——扫雷游戏(附源码)
本文将作为一个入门级的.结合源码的文章,旨在为刚刚接触GDI+编程或对相关知识感兴趣的读者做一个入门讲解.游戏尚且未完善,但基本功能都有,完整源码在文章结尾的附件中. 整体思路: 扫雷的游戏界面让我从 ...
- 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 ...
- WinformGDI+入门级实例——扫雷游戏(附源码)
写在前面: 本文将作为一个入门级的.结合源码的文章,旨在为刚刚接触GDI+编程或对相关知识感兴趣的读者做一个入门讲解.游戏尚且未完善,但基本功能都有,完整源码在文章结尾的附件中. 整体思路: 扫雷的游 ...
- 洛谷 P2670 扫雷游戏==Codevs 5129 扫雷游戏
题目描述 扫雷游戏是一款十分经典的单机小游戏.在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有 ...
- 原生javascript扫雷游戏
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 使用Visual Studio Code调试基于ActionScript的LayaAir HTML5游戏
使用Visual Studio Code(VS Code)调试的优势 使用VS Code我们可以极大地提高LayaAir Html5游戏项目的调试效率,VS Code的优势有以下几点: 在发生Java ...
- 在基于TypeScript的LayaAir HTML5游戏开发中使用AMD
在基于TypeScript的LayaAir HTML5游戏开发中使用AMD AMD AMD是"Asynchronous Module Definition"的缩写,意思就是&quo ...
随机推荐
- OSharp 学习(一)
OSharp3.0 由郭明峰组织开发,已经相对比较完整,从底层代码开始阅读难度比较大. 故采用自上而下的方式,使用到的时候再完善相关功能.希望通过此教程能够找到志同道合的人. 注:请勿抄袭 请参看OS ...
- 安装wampserver2时出现的问题
提示丢失MSVCR100.dll 如果安装其他软件也是同样的提示情况,估计也是这个原因,以下分别是32位与64位的VC10下载地址: VC10 SP1 vcredist_x86.exe 32 bits ...
- Win8/Win8.1都有哪些版本?我该选择哪个?(二)
Windows版本分类比较复杂,下文主要为大家理清Win8/Win8.1的版本种类.如果想了解更多,可以结合<Win7/Win8/Win8.1众多版本,我该选择哪个?>一文来了解. 细数W ...
- Linux下编译第三方库的问题
因为各个Linux发行版之间的差异还是挺大的,有一些预安装在系统上的基本库是不一样的(不仅仅是版本,有一些是有和无的区别). 那么问题来了: 编译第三方库./configure的时候一般我们不会定制那 ...
- perl 获取阿里云主机信息
use LWP::UserAgent; use Data::UUID; use Data::GUID; use HTTP::Date qw(time2iso str2time time2iso tim ...
- 深入浅出Node.js (4) - 异步编程
4.1 函数式编程 4.1.1 高阶函数 4.1.2 偏函数用法 4.2 异步编程的优势与难点 4.2.1 优势 4.2.2 难点 4.3 异步编程解决方案 4.3.1 事件发布/订阅模式 4.3.2 ...
- KDTree详解及java实现
本文内容基于An introductory tutoril on kd-trees 1.KDTree介绍 KDTree根据m维空间中的数据集D构建的二叉树,能加快常用于最近邻查找(在加快k-means ...
- HDOJ-1015 Safecracker(DFS)
http://acm.hdu.edu.cn/showproblem.php?pid=1015 题意:给出一个目标值target和一个由大写字母组成的字符串 A-Z分别对应权值1-26 要求从给出的字符 ...
- javascrpit开发连连看记录-小游戏
工作之余,总想做点什么有意思的东西.但是苦于不知道做什么,也就一直没有什么动作.在一个午饭后,跟@jedmeng和@墨尘聊天过程中,发现可以写一些小东西来练练手,有以下几点好处: 1. ...
- Android基础之退出应用程序Demo
对于Android我也不是很熟悉,只是学习一些基本内容就OK.所以写的内容也很简单.本Demo要实现的效果就是双击返回键弹出提示框确认是否退出程序. 一.废话少说直接上代码.至于涉及到的相关包在Ecl ...