现在的位置: 首页 > 综合 > 正文

C#扫雷游戏-1(砖块部分)

2014年03月15日 ⁄ 综合 ⁄ 共 8817字 ⁄ 字号 评论关闭

 

    前言:扫雷游戏是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)后面就是不同点击的逻辑问题

 

Code:
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.ComponentModel;   
  4. using System.Drawing;   
  5. using System.Data;   
  6. using System.Text;   
  7. using System.Windows.Forms;   
  8.   
  9. namespace MineSweeper {   
  10.     /// <summary>   
  11.     /// 砖块   
  12.     /// </summary>   
  13.     public partial class Brick : UserControl {   
  14.   
  15.         /// <summary>   
  16.         /// 砖块状态   
  17.         /// </summary>   
  18.         public enum BrickState {   
  19.             UnSwept = 0,   
  20.             Mark = 1,   
  21.             Unknown = 2,   
  22.             Swept = 3   
  23.         }   
  24.   
  25.         private BrickState state;   
  26.         private Bitmap[] images = new Bitmap[14];   
  27.         private int arroundMines;   
  28.         private int x;   
  29.         private int y;   
  30.         private bool isMine;   
  31.   
  32.         [DefaultValue("UnSwept"), Description("砖块状态"), Category("Appearance")]   
  33.         public BrickState State {   
  34.             get { return state; }   
  35.             set {   
  36.                 state = value;   
  37.                 if(state == BrickState.UnSwept) {   
  38.                     BackgroundImage = images[0];   
  39.                 } else if(state == BrickState.Mark) {   
  40.                     BackgroundImage = images[1];   
  41.                 } else if(state == BrickState.Unknown) {   
  42.                     BackgroundImage = images[2];   
  43.                 } else if(state == BrickState.Swept && !IsMine) {   
  44.                     if(ArroundMines == 0) {   
  45.                         BackgroundImage = images[3];   
  46.                     } else {   
  47.                         BackgroundImage = images[ArroundMines + 4];   
  48.                     }   
  49.                 } else if(state == BrickState.Swept && IsMine) {   
  50.                     BackgroundImage = images[13];   
  51.                 }   
  52.             }   
  53.         }   
  54.         [DefaultValue("0"), Description("四周地雷数"), Category("Appearance")]   
  55.         public int ArroundMines {   
  56.             get { return arroundMines; }   
  57.             set { arroundMines = value; }   
  58.         }   
  59.         [DefaultValue("0"), Description("距离左边的个数"), Category("Appearance")]   
  60.         public int X {   
  61.             get { return x; }   
  62.             set { x = value; }   
  63.         }   
  64.         [DefaultValue("0"), Description("距离上方的个数"), Category("Appearance")]   
  65.         public int Y {   
  66.             get { return y; }   
  67.             set { y = value; }   
  68.         }   
  69.         [DefaultValue("false"), Description("标记该砖块是否是地雷"), Category("Appearance")]   
  70.         public bool IsMine {   
  71.             get { return isMine; }   
  72.             set { isMine = value; }   
  73.         }   
  74.   
  75.         public Brick() {   
  76.             InitializeComponent();   
  77.   
  78.             images[0] = global::MineSweeper.Properties.Resources.blank;   
  79.             images[1] = global::MineSweeper.Properties.Resources.Mark;   
  80.             images[2] = global::MineSweeper.Properties.Resources.Unknown;   
  81.             images[3] = global::MineSweeper.Properties.Resources.blankBack;   
  82.             images[4] = global::MineSweeper.Properties.Resources.move;   
  83.   
  84.             images[5] = global::MineSweeper.Properties.Resources._1;   
  85.             images[6] = global::MineSweeper.Properties.Resources._2;   
  86.             images[7] = global::MineSweeper.Properties.Resources._3;   
  87.             images[8] = global::MineSweeper.Properties.Resources._4;   
  88.             images[9] = global::MineSweeper.Properties.Resources._5;   
  89.             images[10] = global::MineSweeper.Properties.Resources._6;   
  90.             images[11] = global::MineSweeper.Properties.Resources._7;   
  91.             images[12] = global::MineSweeper.Properties.Resources._8;   
  92.   
  93.             images[13] = global::MineSweeper.Properties.Resources.mine;   
  94.   
  95.             BackgroundImageLayout = ImageLayout.Stretch;   
  96.             BackgroundImage = images[0];   
  97.         }  
  98.  
  99.  
  100.  
  101.         #region 鼠标相关事件   
  102.         //鼠标Hover事件   
  103.         private void Brick_MouseEnter(object sender, EventArgs e) {   
  104.             if(state == BrickState.UnSwept) {   
  105.                 BackgroundImage = images[4];   
  106.             }   
  107.         }   
  108.         private void Brick_MouseLeave(object sender, EventArgs e) {   
  109.             if(state == BrickState.UnSwept) {   
  110.                 BackgroundImage = images[0];   
  111.             }   
  112.         }   
  113.         bool leftButton = false, rightButton = false;   
  114.         private void Brick_MouseDown(object sender, MouseEventArgs e) {   
  115.             if(e.Button == MouseButtons.Left) {   
  116.                 leftButton = true;   
  117.             } else if(e.Button == MouseButtons.Right) {   
  118.                 rightButton = true;   
  119.             }   
  120.             if(state == BrickState.Swept && leftButton && rightButton) {   
  121.                 //左右键同时双击数字   
  122.                 TogetherClick();   
  123.             } else if(state != BrickState.Swept && leftButton) {   
  124.                 //左键未扫砖块   
  125.                 LeftClick();   
  126.             } else if(state != BrickState.Swept && rightButton) {   
  127.                 //右键未扫砖块   
  128.                 RightClick();   
  129.             }   
  130.         }   
  131.   
  132.         private void Brick_MouseUp(object sender, MouseEventArgs e) {   
  133.             if(e.Button == MouseButtons.Left) {   
  134.                 leftButton = false;   
  135.             } else if(e.Button == MouseButtons.Right) {   
  136.                 rightButton = false;   
  137.             }   
  138.         }   
  139.         //左右键同时按键事件   
  140.         private void TogetherClick() {   
  141.                
  142.         }   
  143.         //左键事件   
  144.         private void LeftClick() {   
  145.             SweepBricks(X, Y);   
  146.         }   
  147.         //   
  148.         private void SweepBricks(int x, int y) {   
  149.             int rows = Game.Bricks.GetLength(0);   
  150.             int cols = Game.Bricks.GetLength(1);   
  151.             if(x < 0 || x > rows - 1 || y < 0 || y > cols - 1)   
  152.                 return;   
  153.             Brick brick = Game.Bricks[x, y];   
  154.             if(brick.state == BrickState.UnSwept) {   
  155.                 brick.State = BrickState.Swept;   
  156.                 Console.WriteLine("({0},{1})",x,y);   
  157.                 if(brick.ArroundMines == 0) {   
  158.   
  159.                     SweepBricks(x - 1, y);   
  160.                     SweepBricks(x + 1, y);   
  161.                     SweepBricks(x, y - 1);   
  162.                     SweepBricks(x, y + 1);   
  163.                 }   
  164.             }   
  165.         }   
  166.         //右键标记   
  167.         private void RightClick() {   
  168.             if(this.State != BrickState.Swept) {   
  169.                 if(!this.isMine) {   
  170.                     State = (BrickState)((((int)state) + 1) % 3);   
  171.                 } else {   
  172.                     State = BrickState.Swept;   
  173.                 }   
  174.             }   
  175.         }  
  176.         #endregion   
  177.   
  178.   
  179.   
  180.   
  181.     }   
  182. }   

 

抱歉!评论已关闭.