前言:扫雷游戏是Windows系统的一款经典游戏。搜索一下google,有94万条网页。包括本人也写过2个版本的扫雷游戏。其实我们注重的不是游戏本身,而是技术或者说是知识点。
先看看我要介绍的这款扫雷涉及哪些知识点。
1) 自定义控件
2) GDI+
3) 枚举
4) 集合
5) 属性
6) 递归
大致看来涉及这些。我在介绍的过程中尽量结合C#的知识点运用。
需求说明:
1) 有不同级别,不同级别有不同的砖块,地雷数也不同
2) 点击砖块,如果没有地雷显示周围地雷数
3) 右击砖块可以设置多种状态:标志、疑问、取消标志
4) 如果砖块周围无雷,则打开周围的无雷区
5) 鼠标移动到砖块上,砖块颜色变化
1.制作砖块
需求分析:
1) 为了实现“鼠标移动到砖块上,砖块颜色变化”,决定采用自定义控件,这样将每个砖块都作为一个控件,可以定义MouseEnter和MouseLeave事件
(1)创建自定义控件Brick
public
partial class Brick : UserControl{
……
}
(2)定义砖块状态的枚举
public
partial class Brick : UserControl{
///<summary>
///
砖块状态
///</summary>
public enum BrickState {
UnSwept = 0, //
未扫
Mark = 1, //
标记
Unknow = 2, //
未知
Swept = 3 //
已扫
}
}
(3)定义一些成员变量。如:状态、周围地雷数、位置以及是否有地雷
(4)根据不同的状态,显示不同的图片。这里我采用了属性设置。通过setter访问器实现状态与背景图片的关联。
[DefaultValue("UnSwept"), Description("
砖块状态
"
), Category("Appearance")]
public
BrickState State {
get { return state; }
set {
state = value;
if
(state == BrickState.UnSwept) {
BackgroundImage = images[0];
} else if(state == BrickState.Mark) {
BackgroundImage = images[1];
} else if(state == BrickState.Unknow) {
BackgroundImage = images[2];
} else if(state == BrickState.Swept && !IsMine) {
BackgroundImage = images[3];
} else if(state == BrickState.Swept && IsMine) {
BackgroundImage = images[11];
}
}
}
注意到
[DefaultValue("UnSwept"), Description("
砖块状态
"
), Category("Appearance")]
,这是为了让
VS2005
能看属性窗口中看到自定义的属性。
DefaultValue
是默认值,
Description
是说明
(
5
)鼠标事件:鼠标移动砖块上
(MouseEnter)
、鼠标移出砖块
(MouseLeave)
、鼠标点击
(
左击、右击、左右同击
)
这里说明一下,鼠标左右同击比较难以判断。现采用这种方式:当左键点击后记录下来,右键点击后也记录下来,再判断两个记录值,如果都为
true
表示左右同击。当鼠标键抬起时也要将记录改过来。
private
void Brick_MouseEnter(object sender, EventArgs e) {
if(state == BrickState.UnSwept) {
BackgroundImage = images[4];
}
}
private
void Brick_MouseLeave(object sender, EventArgs e) {
if(state == BrickState.UnSwept) {
BackgroundImage = images[0];
}
}
bool
leftButton = false, rightButton = false;
private
void Brick_MouseDown(object sender, MouseEventArgs e) {
if(e.Button == MouseButtons.Left) {
leftButton = true;
} else if(e.Button == MouseButtons.Right) {
rightButton = true;
}
if(state == BrickState.Swept && leftButton && rightButton) {
//
左右键同时双击数字
TogetherClick();
} else if(state != BrickState.Swept && leftButton) {
//
左键未扫砖块
LeftClick();
} else if(state != BrickState.Swept && rightButton) {
//
右键未扫砖块
RightClick();
}
}
private
void Brick_MouseUp(object sender, MouseEventArgs e) {
if(e.Button == MouseButtons.Left) {
leftButton = false;
} else if(e.Button == MouseButtons.Right) {
rightButton = false;
}
}
(
6
)后面就是不同点击的逻辑问题
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Data;
- using System.Text;
- using System.Windows.Forms;
-
- namespace MineSweeper {
-
-
-
- public partial class Brick : UserControl {
-
-
-
-
- public enum BrickState {
- UnSwept = 0,
- Mark = 1,
- Unknown = 2,
- Swept = 3
- }
-
- private BrickState state;
- private Bitmap[] images = new Bitmap[14];
- private int arroundMines;
- private int x;
- private int y;
- private bool isMine;
-
- [DefaultValue("UnSwept"), Description("砖块状态"), Category("Appearance")]
- public BrickState State {
- get { return state; }
- set {
- state = value;
- if(state == BrickState.UnSwept) {
- BackgroundImage = images[0];
- } else if(state == BrickState.Mark) {
- BackgroundImage = images[1];
- } else if(state == BrickState.Unknown) {
- BackgroundImage = images[2];
- } else if(state == BrickState.Swept && !IsMine) {
- if(ArroundMines == 0) {
- BackgroundImage = images[3];
- } else {
- BackgroundImage = images[ArroundMines + 4];
- }
- } else if(state == BrickState.Swept && IsMine) {
- BackgroundImage = images[13];
- }
- }
- }
- [DefaultValue("0"), Description("四周地雷数"), Category("Appearance")]
- public int ArroundMines {
- get { return arroundMines; }
- set { arroundMines = value; }
- }
- [DefaultValue("0"), Description("距离左边的个数"), Category("Appearance")]
- public int X {
- get { return x; }
- set { x = value; }
- }
- [DefaultValue("0"), Description("距离上方的个数"), Category("Appearance")]
- public int Y {
- get { return y; }
- set { y = value; }
- }
- [DefaultValue("false"), Description("标记该砖块是否是地雷"), Category("Appearance")]
- public bool IsMine {
- get { return isMine; }
- set { isMine = value; }
- }
-
- public Brick() {
- InitializeComponent();
-
- images[0] = global::MineSweeper.Properties.Resources.blank;
- images[1] = global::MineSweeper.Properties.Resources.Mark;
- images[2] = global::MineSweeper.Properties.Resources.Unknown;
- images[3] = global::MineSweeper.Properties.Resources.blankBack;
- images[4] = global::MineSweeper.Properties.Resources.move;
-
- images[5] = global::MineSweeper.Properties.Resources._1;
- images[6] = global::MineSweeper.Properties.Resources._2;
- images[7] = global::MineSweeper.Properties.Resources._3;
- images[8] = global::MineSweeper.Properties.Resources._4;
- images[9] = global::MineSweeper.Properties.Resources._5;
- images[10] = global::MineSweeper.Properties.Resources._6;
- images[11] = global::MineSweeper.Properties.Resources._7;
- images[12] = global::MineSweeper.Properties.Resources._8;
-
- images[13] = global::MineSweeper.Properties.Resources.mine;
-
- BackgroundImageLayout = ImageLayout.Stretch;
- BackgroundImage = images[0];
- }
-
-
-
- #region 鼠标相关事件
-
- private void Brick_MouseEnter(object sender, EventArgs e) {
- if(state == BrickState.UnSwept) {
- BackgroundImage = images[4];
- }
- }
- private void Brick_MouseLeave(object sender, EventArgs e) {
- if(state == BrickState.UnSwept) {
- BackgroundImage = images[0];
- }
- }
- bool leftButton = false, rightButton = false;
- private void Brick_MouseDown(object sender, MouseEventArgs e) {
- if(e.Button == MouseButtons.Left) {
- leftButton = true;
- } else if(e.Button == MouseButtons.Right) {
- rightButton = true;
- }
- if(state == BrickState.Swept && leftButton && rightButton) {
-
- TogetherClick();
- } else if(state != BrickState.Swept && leftButton) {
-
- LeftClick();
- } else if(state != BrickState.Swept && rightButton) {
-
- RightClick();
- }
- }
-
- private void Brick_MouseUp(object sender, MouseEventArgs e) {
- if(e.Button == MouseButtons.Left) {
- leftButton = false;
- } else if(e.Button == MouseButtons.Right) {
- rightButton = false;
- }
- }
-
- private void TogetherClick() {
-
- }
-
- private void LeftClick() {
- SweepBricks(X, Y);
- }
-
- private void SweepBricks(int x, int y) {
- int rows = Game.Bricks.GetLength(0);
- int cols = Game.Bricks.GetLength(1);
- if(x < 0 || x > rows - 1 || y < 0 || y > cols - 1)
- return;
- Brick brick = Game.Bricks[x, y];
- if(brick.state == BrickState.UnSwept) {
- brick.State = BrickState.Swept;
- Console.WriteLine("({0},{1})",x,y);
- if(brick.ArroundMines == 0) {
-
- SweepBricks(x - 1, y);
- SweepBricks(x + 1, y);
- SweepBricks(x, y - 1);
- SweepBricks(x, y + 1);
- }
- }
- }
-
- private void RightClick() {
- if(this.State != BrickState.Swept) {
- if(!this.isMine) {
- State = (BrickState)((((int)state) + 1) % 3);
- } else {
- State = BrickState.Swept;
- }
- }
- }
- #endregion
-
-
-
-
- }
- }