代码改变世界

单机版扫雷

2010-01-06 08:12  【当耐特】  阅读(3582)  评论(16编辑  收藏  举报


今天的主要任务就是把单击版的搞定,这是过渡到网络版的必备过程。

如果没有玩过扫雷的,建议先去体验一下;体验完后,自己尝试写出扫雷的算法;经过思考揣摩推敲才能有收获。不建议一上来就下载源码剖析,跟踪代码!

 

 

【一】单机版扫雷划为两层

第一层为Button,Button盖在Lable上,Lable被隐藏在Button下面;

第二层为Lable,  Lable上的背景图片改成地雷图案表示有雷。

雷区的大家我定为20*20.

        private const int Xcount = 20;
        
private const int Ycount = 20;

添加Lable的代码如下:

代码
 1  private Label[] labels2 = new Label[Xcount * Ycount];
 2  private Label[,] labels = new Label[Xcount, Ycount];
 3         int indexOfLable = 0;
 4         private void CreateLable()
 5         {
 6             int[] ints = new int[400];
 7             Random rd = new Random();
 8             for (int i = 0; i < 400; i++)
 9             {
10                
11                 ints[i] = rd.Next(1400);
12             }
13             for (int i = 0; i < Xcount; i++)
14             {
15                 for (int j = 0; j < Ycount; j++)
16                 {
17                     Label lb = new Label();
18                     lb.Location = new Point(i * 3030 * j);
19                     lb.Size = new Size(3030);
20                     lb.BorderStyle = BorderStyle.Fixed3D;
21                     this.Controls.Add(lb);
22                     labels[i, j] = lb;
23                     labels2[indexOfLable] = lb;
24                     indexOfLable++;
25                 }
26             }
27             for (int i = 0; i < ints.Length; i++)
28             {
29                 if (ints[i] < 40)
30                 {
31                     labels2[i].Image = Properties.Resources.标准地雷;
32                 }
33             }
34         }

 

添加Button的代码如下:

代码
 1    private Button[,] buttons = new Button[Xcount, Ycount];     
 2         private void AddButton()
 3         {
 4             for (int i = 0; i < Xcount; i++)
 5             {
 6                 for (int j = 0; j < Ycount; j++)
 7                 {
 8                     Button btn = new Button();
 9                     btn.Click += new EventHandler(btn_Click);
10                     //btn.Click +=new EventHandler(btn_MouseDown);
11                     btn.MouseUp += new MouseEventHandler(btn_MouseUp);
12                     btn.Location = new Point(i * 3030 * j);
13                     btn.Size = new Size(3030);
14                     this.Controls.Add(btn);
15                     //利用Tag使按钮和坐标建立联系
16                     Point pt = new Point(i, j);
17                     btn.Tag = pt;
18                     buttons[i, j] = btn;
19                 }
20             }
21         }

 

实现按钮注册的事件,代码如下:

代码
 1    void btn_MouseUp(object sender, MouseEventArgs e)
 2         {
 3             if (e.Button == MouseButtons.Right)
 4             {
 5                 Button btn = (Button)sender;
 6                 if (btn.BackgroundImage == null)
 7                 {
 8                     btn.BackgroundImage = Properties.Resources.挖雷工兵;
 9                 }
10                 else
11                 {
12                     btn.BackgroundImage = null;
13                 }
14             }
15         }
16 
17 
18  void btn_Click(object sender, EventArgs e)
19         {
20             Button btn = (Button)sender;
21             this.Controls.Remove(btn);
22             Point pt = (Point)btn.Tag;
23             x = pt.X;
24             y = pt.Y;
25             if (labels[x, y].Image != null)
26             {
27                 MessageBox.Show("游戏结束,果然是踩雷高手");
28                 ReStart();
29                 return;
30             }
31             CheckLable(x, y);
32         }

 

 

单击Button按钮判断在其下面的Lable上的图像是否为地雷,图像为空------递归寻找,图像不为空------游戏失败!

代码
 1     void btn_Click(object sender, EventArgs e)
 2         {
 3             Button btn = (Button)sender;
 4             this.Controls.Remove(btn);
 5             Point pt = (Point)btn.Tag;
 6             x = pt.X;
 7             y = pt.Y;
 8             if (labels[x, y].Image != null)
 9             {
10                 MessageBox.Show("游戏结束,果然是踩雷高手");
11                 ReStart();
12                 return;
13             }
14             CheckLable(x, y);
15         }

 

 

【二】单击的后果

这里是指左键的单击,右键的很简单,仅仅改变一下Button的背景图片而已,表示你任务下面有地雷。

左键单击后------1.移除被单击的按钮(大家都知道!)

1    void btn_Click(object sender, EventArgs e)
2         {
3             Button btn = (Button)sender;
4             this.Controls.Remove(btn);
5         }

 

 

              ------2.判断周围8格有没有雷,如果有---计算出有多少个,显示在lable上

                                                     如果没有---则移除周围8个button,并自动判断周围的8格的周围8格是否有地雷,一直递归下去!

 虽然很绕口,但也是扫雷的核心算法。

 

【三】遍历周围8格

代码
 1     private void CheckLable(int x, int y)
 2         {
 3             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
 4             {
 5                 num = 0;
 6                 num = GetCount(x, y);
 7                 if (num == 8)
 8                 {
 9                     num = 0;
10                     string tag = buttons[x, y].Tag.ToString();
11                     buttons[x, y].Tag = 0;
12                     if (labels[x, y].Image == null && tag != "0")
13                     {
14                         x++;
15                         RemoveButton(x, y);
16                         y++;
17                         RemoveButton(x, y);
18                         x--;
19                         RemoveButton(x, y);
20                         x--;
21                         RemoveButton(x, y);
22                         y--;
23                         RemoveButton(x, y);
24                         y--;
25                         RemoveButton(x, y);
26                         x++;
27                         RemoveButton(x, y);
28                         x++;
29                         RemoveButton(x, y);
30                         if (tag != "0")
31                         {
32                             num = 0;
33                             Recursion(x, y);
34                         }
35                     }
36                 }
37                 else
38                 {
39                     if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
40                     {
41                         labels[x, y].Text = (8 - num).ToString();
42 
43                         num = 0;
44                         return;
45                     }
46                 }
47             }
48         }

 

 

【四】计算雷的个数

代码
 1   private int GetCount(int x, int y)
 2         {
 3 
 4             temp2 = 0;
 5             x++;
 6             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
 7             {
 8                 if (labels[x, y].Image == null)
 9                 {
10                     temp2++;
11                 }
12             }
13             else
14             { temp2++; }
15 
16             y++;
17             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
18             {
19                 if (labels[x, y].Image == null)
20                 {
21                     temp2++;
22                 }
23             }
24             else
25             { temp2++; }
26 
27             x--;
28             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
29             {
30                 if (labels[x, y].Image == null)
31                 {
32                     temp2++;
33                 }
34             }
35             else
36             { temp2++; }
37             x--;
38             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
39             {
40                 if (labels[x, y].Image == null)
41                 {
42                     temp2++;
43                 }
44             }
45             else
46             { temp2++; }
47             y--;
48             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
49             {
50                 if (labels[x, y].Image == null)
51                 {
52                     temp2++;
53                 }
54             }
55             else
56             { temp2++; }
57             y--;
58             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
59             {
60                 if (labels[x, y].Image == null)
61                 {
62                     temp2++;
63                 }
64             }
65             else
66             { temp2++; }
67             x++;
68             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
69             {
70                 if (labels[x, y].Image == null)
71                 {
72                     temp2++;
73                 }
74             }
75             else
76             { temp2++; }
77             x++;
78             if (x < Xcount && x >= 0 && y >= 0 && y < Ycount)
79             {
80                 if (labels[x, y].Image == null)
81                 {
82                     temp2++;
83                 }
84             }
85             else
86             { temp2++; }
87 
88             return temp2;
89         }

 

   

【五】递归

代码
 1    private void Recursion(int x, int y)
 2         {
 3             CheckLable(x, y);
 4             y++;
 5             CheckLable(x, y);
 6             y++;
 7             CheckLable(x, y);
 8             x--;
 9             CheckLable(x, y);
10             x--;
11             CheckLable(x, y);
12             y--;
13             CheckLable(x, y);
14             y--;
15             CheckLable(x, y);
16             x++;
17             CheckLable(x, y);
18 
19         }

 

 

 【六】重新来一盘

代码
 1    public void ReStart()
 2         {
 3             this.Controls.Clear();
 4             InitializeComponent();
 5             temp2 = 0;
 6             x = 0;
 7             y = 0;
 8             indexOfLable = 0;
 9             num = 0;
10             AddButton();
11             CreateLable();
12         }

 

 

留两件事情给大家做,一改成用户控件,二给Lable添加双击事件(左右键一起按)!源码下载 ==> /Files/zhanglei644213943/单机版扫雷.rar