C#实现内置音乐播放功能的新型扫雷游戏
程序员文章站
2024-03-19 16:47:46
...
程序视频展示链接
http://v.youku.com/v_show/id_XNDA2ODQwODYwNA==.html?spm=a2h3j.8428770.3416059.1
程序描述及代码展示
1、扫雷游戏设计的内容主要包含在两个大类上,即程序代码中的Game类和Square类。Game类表示一局扫雷游戏,其中包含游戏数据,游戏等级,雷区数,布雷方法等等。Square类表示游戏中的一个小方格,小方格中可能埋有地雷。Game类来实现一个游戏实例,Square类则代表一个游戏实例中的元素。用二维数组来保存游戏界面的信息,定义一个二维数组public static Square[,] gameData,游戏界面的宽度和高度即二维数组的第一维和第二维的长度。
2、扫雷游戏设计要求共有四个方面:
① 能够实现游戏中雷区和非雷区的分布,且能够在第一次点击时不踩中雷。
② 能够实现计时功能,即一局游戏结束时,能给出用户进行这局游戏所花费的时间。
③ 能实现标记计数功能,即每次鼠标右击方格时,在方格中画一个小旗标记时,主界面中相应的雷数也要减1,而再次点击质疑时,主界面中雷数又要相应的加1。
④ 当游戏正在进行时,如果用户做任何终止本次游戏的行为,则程序应该能够弹出提示框,询问用户是否继续进行正在进行的游戏,根据用户的选择,执行相应的操作。
2、扫雷程序设计流程:
#主窗口程序
using System;
using System.Windows.Forms;
using System.Media;
namespace SweepingMine
{
public partial class FormMain : Form
{
public Game game1;
public static int SquareColor;
public static FormMain fm1 = null;
public static DateTime beginTime;
public GameLevel formmerLevel = GameLevel.Beginner;
public GameLevel nowLevel = GameLevel.Beginner;
SetSize size = new SetSize();
public FormMain()
{
InitializeComponent();
fm1 = this;
}
/// <summary>
/// 游戏开局
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 开局NF2ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (userControl12.gameLevel == GameLevel.Customize)
{
timer1.Enabled = false;
this.textBox1.Text = "0";
textBox2.Text = Properties.Settings.Default.MinesCount.ToString();
userControl12.NewGameC(userControl12.logicalSize, userControl12.MineCount);
}
else
{
timer1.Enabled = false;
this.textBox1.Text = "0";
userControl12.NewGameL(userControl12.gameLevel);
switch (userControl12.gameLevel)
{
case GameLevel.Beginner:
textBox2.Text = "10";
break;
case GameLevel.Intermediate:
textBox2.Text = "40";
break;
case GameLevel.Expert:
textBox2.Text = "99";
break;
}
}
}
/// <summary>
/// 游戏等级初级
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 初级BToolStripMenuItem_Click(object sender, EventArgs e)
{
nowLevel = GameLevel.Beginner;
if (timer1.Enabled != false)
{
FormTips ft = new FormTips();
ft.Show();
}
else
{
userControl12.gameLevel = formmerLevel = GameLevel.Beginner;
size.GetGameLevel(userControl12.gameLevel);
}
}
/// <summary>
/// 游戏等级中级
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 中级IToolStripMenuItem_Click(object sender, EventArgs e)
{
nowLevel = GameLevel.Intermediate;
if (timer1.Enabled != false)
{
FormTips ft = new FormTips();
ft.Show();
}
else
{
userControl12.gameLevel = formmerLevel = GameLevel.Intermediate;
size.GetGameLevel(userControl12.gameLevel);
}
}
/// <summary>
/// 游戏等级高级
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 高级EToolStripMenuItem_Click(object sender, EventArgs e)
{
nowLevel = GameLevel.Expert;
if (timer1.Enabled != false)
{
FormTips ft = new FormTips();
ft.Show();
}
else
{
userControl12.gameLevel = formmerLevel = GameLevel.Expert;
size.GetGameLevel(userControl12.gameLevel);
}
}
/// <summary>
/// 自定义游戏设置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 自定义CToolStripMenuItem_Click(object sender, EventArgs e)
{
nowLevel = GameLevel.Customize;
if (timer1.Enabled != false)
{
FormCustomize f = new FormCustomize();
if (f.ShowDialog() == DialogResult.OK)
{
FormTips ft = new FormTips();
ft.Show();
}
}
else
{
userControl12.gameLevel = formmerLevel = GameLevel.Customize;
FormCustomize f = new FormCustomize();
if (f.ShowDialog() != DialogResult.OK)
return;
size.GetGameLevel(userControl12.gameLevel);
}
}
private void 银色ToolStripMenuItem_Click(object sender, EventArgs e)
{
SquareColor = 0;
userControl12.game.Draw();
}
private void 蓝色ToolStripMenuItem_Click(object sender, EventArgs e)
{
SquareColor = 1;
userControl12.game.Draw();
}
private void 粉色ToolStripMenuItem_Click(object sender, EventArgs e)
{
SquareColor = 2;
userControl12.game.Draw();
}
private void 紫色ToolStripMenuItem_Click(object sender, EventArgs e)
{
SquareColor = 3;
userControl12.game.Draw();
}
/// <summary>
/// 窗体初始化加载内容设置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormMain_Load(object sender, EventArgs e)
{
textBox1.Text = "0";
textBox2.Text = "10";
formmerLevel = GameLevel.Beginner;
}
/// <summary>
/// 游戏计时功能
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer1_Tick(object sender, EventArgs e)
{
try
{
this.textBox1.Text = (((int)DateTime.Now.Subtract(beginTime).TotalSeconds) + 1).ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// 帮助信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 帮助ToolStripMenuItem1_Click(object sender, EventArgs e)
{
MessageBox.Show("哈哈哈,我就不告诉你怎么玩!!!");
}
/// <summary>
/// 退出游戏系统
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 退出XToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
/// <summary>
/// 播放在线音乐
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 在线播放ToolStripMenuItem_Click(object sender, EventArgs e)
{
FormMusic fmusic_ = new FormMusic();
fmusic_.Show();
}
/// <summary>
/// 播放本地音乐
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 本地ToolStripMenuItem_Click(object sender, EventArgs e)
{
FileDialog open = new OpenFileDialog();
open.Filter = "*.mp3|*.mp3";
open.Title = "打开文件";
if (open.ShowDialog() == DialogResult.OK)
{
axWindowsMediaPlayer1.URL = open.FileName;
axWindowsMediaPlayer1.Ctlcontrols.play();//播放文件
}
}
/// <summary>
/// 暂停音乐
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 暂停ToolStripMenuItem_Click(object sender, EventArgs e)
{
axWindowsMediaPlayer1.Ctlcontrols.pause();//暂停
FormMusic.fmusic.Close();
}
/// <summary>
/// 显示游戏信息内容
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 游戏信息MToolStripMenuItem_Click(object sender, EventArgs e)
{
FormMessage fms = new FormMessage();
fms.Show();
}
/// <summary>
/// 中止游戏提示
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (textBox1.Text != "0" && timer1.Enabled != false)
{
if (MessageBox.Show("游戏正在进行,你确定要退出游戏吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
{
SaveSweepMineInfo ss = new SaveSweepMineInfo();
ss.SaveInformation(textBox1.Text, DateTime.Now.ToString("yyyy-M-d"), "-1", userControl12.gameLevel);
Environment.Exit(0);
}
else
{
e.Cancel = true;
}
}
else
{
Environment.Exit(0);
}
}
}
}
#Square类
using System;
using System.Drawing;
using System.Runtime.Serialization;
namespace SweepingMine
{
/// <summary>
/// 表示游戏中一个方块区, 在类声明中使用sealed可防止其它类继承此类
/// </summary>
public sealed class Square
{
/// <summary>
/// 方块区状态
/// </summary>
public enum SquareStatus
{
/// <summary>
/// 闲置
/// </summary>
Idle,
/// <summary>
/// 已打开
/// </summary>
Opened,
/// <summary>
/// 已标记
/// </summary>
Marked,
/// <summary>
/// 已质疑
/// </summary>
Queried,
/// <summary>
/// 游戏结束
/// </summary>
GameOver,
/// <summary>
/// 标记失误(仅在游戏结束时用于绘制)
/// </summary>
MarkMissed
}
private static readonly Font Font = new Font(new FontFamily("Arial"), SquareSize / 1.5f, FontStyle.Bold);
public const int SquareSize = 25;
private readonly Point location;
private readonly bool minedS;
private readonly int minesAroundS;
private SquareStatus status;
private bool isBombPoint;
//仅用于调试时在对象查看器中显示对象摘要
#if DEBUG
public override string ToString()
{
return string.Format("[{0},{1}]是否雷区:{2},周围雷数:{3},状态:{4}", location.X, location.Y, minedS, minesAroundS, status);
}
#endif
/// <summary>
/// 是否为雷区
/// </summary>
public bool Mined
{
get { return minedS; }
}
/// <summary>
/// 状态
/// </summary>
public SquareStatus Status
{
get { return status; }
}
/// <summary>
/// 周围雷数
/// </summary>
public int MinesAround
{
get { return minesAroundS; }
}
/// <summary>
/// 逻辑坐标(对应二维数组索引)
/// </summary>
public Point Location
{
get { return location; }
}
/// <summary>
/// 初始化一个方块区
/// </summary>
/// <param name="loc">位置</param>
/// <param name="mined">是否为雷区</param>
/// <param name="minesAround">周围雷区数</param>
public Square(Point loc, bool mined, int minesAround)
{
location = loc;
minedS = mined;
minesAroundS = minesAround;
status = SquareStatus.Idle;
isBombPoint = false;
}
/// <summary>
/// 左键单击
/// </summary>
/// <returns>是否踩到雷</returns>
public bool LeftClick()
{
switch (status)
{
case SquareStatus.Idle:
case SquareStatus.Queried:
status = SquareStatus.Opened;
return minedS;
case SquareStatus.Opened:
case SquareStatus.Marked:
case SquareStatus.GameOver:
return false;
default:
throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// 右键单击
/// </summary>
public void RightClick()
{
switch (status)
{
case SquareStatus.Idle:
{
status = SquareStatus.Marked;
FormMain.fm1.textBox2.Text = ((int.Parse(FormMain.fm1.textBox2.Text.ToString()) - 1).ToString());
break;
}
case SquareStatus.Opened:
case SquareStatus.GameOver:
break;
case SquareStatus.Marked:
{
status = SquareStatus.Queried;
FormMain.fm1.textBox2.Text = (int.Parse(FormMain.fm1.textBox2.Text.ToString()) + 1).ToString();
break;
}
case SquareStatus.Queried:
{
status = SquareStatus.Idle;
break;
}
default:
throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// 绘制
/// </summary>
/// <param name="g">图面</param>
public void Draw(Graphics g)
{
Rectangle rect = new Rectangle(location.X * SquareSize, location.Y * SquareSize, SquareSize, SquareSize);
switch (status)
{
case SquareStatus.Idle:
DrawIdleBackground(g, rect);
break;
case SquareStatus.Marked:
{
DrawIdleBackground(g, rect);
Point[] flagTriangle =
{
new Point(rect.X + SquareSize / 2, rect.Y + 1),
new Point(rect.X + SquareSize / 2, rect.Y + SquareSize / 2 + 1),
new Point(rect.X + SquareSize / 4 - 1, rect.Y + SquareSize / 4)
};
Point[] flagBaseTriangle =
{
new Point(rect.X + SquareSize / 2, rect.Y + SquareSize / 2),
new Point(rect.X + SquareSize / 4 - 3, rect.Y + SquareSize - 3),
new Point(rect.X + SquareSize / 4 * 3, rect.Y + SquareSize - 3)
};
g.FillPolygon(Brushes.Red, flagTriangle);
g.FillPolygon(Brushes.Black, flagBaseTriangle);
break;
}
case SquareStatus.Queried:
{
DrawIdleBackground(g, rect);
SizeF querySize = g.MeasureString("?", Font);
g.DrawString("?", Font, Brushes.Black, rect.X + SquareSize / 2 - querySize.Width / 2 - 1, rect.Y + SquareSize / 2 - querySize.Height / 2);
break;
}
case SquareStatus.Opened:
{
g.FillRectangle(Brushes.Silver, rect);
g.DrawRectangle(new Pen(Color.Gray, 2f), rect);
if (minesAroundS > 0)
{
string numStr = minesAroundS.ToString();
SizeF numSize = g.MeasureString(numStr, Font);
g.DrawString(numStr, Font, GetNumberBrush(), rect.X + SquareSize / 2 - numSize.Width / 2 - 1, rect.Y + SquareSize / 2 - numSize.Height / 2);
}
break;
}
case SquareStatus.GameOver:
{
if (!minedS) break;
g.FillRectangle(isBombPoint ? Brushes.Red : Brushes.Silver, rect);
g.DrawRectangle(new Pen(Color.Gray, 2f), rect);
g.FillEllipse(Brushes.Black, new Rectangle(rect.X + 2, rect.Y + 2, rect.Width - 2 * 2, rect.Height - 2 * 2));
break;
}
case SquareStatus.MarkMissed:
{
g.FillRectangle(Brushes.Silver, rect);
g.DrawRectangle(new Pen(Color.Gray, 2f), rect);
g.FillEllipse(Brushes.Black, new Rectangle(rect.X + 2, rect.Y + 2, rect.Width - 2 * 2, rect.Height - 2 * 2));
g.DrawLine(Pens.Red, rect.X, rect.Y, rect.Right, rect.Bottom);//左上到右下
g.DrawLine(Pens.Red, rect.Right, rect.Y, rect.X, rect.Bottom);//右上到左下
break;
}
default:
throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// 游戏结束
/// </summary>
/// <param name="bombPt">爆炸点</param>
public void GameOver(Point bombPt)
{
status = SquareStatus.GameOver;
isBombPoint = bombPt == location;
}
/// <summary>
/// 指定标记失误
/// </summary>
public void IndicateMarkMissed()
{
status = SquareStatus.MarkMissed;
}
/// <summary>
/// 获取附近雷数数字颜色画刷
/// </summary>
/// <returns>画刷</returns>
private Brush GetNumberBrush()
{
switch (minesAroundS)
{
case 1:
return Brushes.Blue;
case 2:
return Brushes.Green;
case 3:
return Brushes.Red;
case 4:
return Brushes.Navy;
case 5:
return Brushes.Maroon;
case 6:
return Brushes.Teal;
case 7:
return Brushes.Black;
case 8:
return Brushes.Gray;
}
return null;
}
/// <summary>
/// 绘制闲置时的背景图
/// </summary>
/// <param name="g">图面</param>
/// <param name="rect">矩形</param>
private static void DrawIdleBackground(Graphics g, Rectangle rect)
{
switch (FormMain.SquareColor)
{
case 0:
g.FillRectangle(Brushes.Silver, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 4, rect.Height - 4));
break;
case 1:
g.FillRectangle(Brushes.Green, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 4, rect.Height - 4));
break;
case 2:
g.FillRectangle(Brushes.Pink, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 4, rect.Height - 4));
break;
case 3:
g.FillRectangle(Brushes.Purple, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 4, rect.Height - 4));
break;
}
g.DrawLine(new Pen(Color.White, 2f), rect.X, rect.Y, rect.Right - 2, rect.Y);
g.DrawLine(new Pen(Color.White, 2f), rect.X, rect.Y, rect.X, rect.Bottom - 2);
g.DrawLine(new Pen(Color.Gray, 2f), rect.Right - 2, rect.Y, rect.Right - 2, rect.Bottom - 1);
g.DrawLine(new Pen(Color.Gray, 2f), rect.X, rect.Bottom - 2, rect.Right - 1, rect.Bottom - 2);
}
}
}
#Game类
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace SweepingMine
{
public sealed class Game
{
public static Square[,] _gameData;
private readonly GameLevel _level;
private readonly int _minesCount;
private readonly Size _gameFieldOffset;
private readonly Graphics _wndGraphics;
private readonly Bitmap buffer;
private readonly Graphics _bufferGraphics;
private static readonly Random Rnd = new Random();
public bool _gameStarted;
public bool _gameStoped;
public const int
MaxWidth = 30,
MaxHeight = 24,
MinWidth = 9,
MinHeight = 9,
MinMinesCount = 10;
/// <summary>
/// 从预设等级初始化游戏
/// </summary>
/// <param name="level">预设等级</param>
/// <param name="g">图面</param>
/// <param name="gameFieldOffset">游戏区偏移</param>
public Game(GameLevel level, Graphics g, Size gameFieldOffset)
{
_level = level;
_gameFieldOffset = gameFieldOffset;
_wndGraphics = g;
switch (level)
{
case GameLevel.Beginner:
_gameData = new Square[9, 9];
_minesCount = 10;
break;
case GameLevel.Intermediate:
_gameData = new Square[16, 16];
_minesCount = 40;
break;
case GameLevel.Expert:
_gameData = new Square[30, 16];
_minesCount = 99;
break;
case GameLevel.Customize:
break;
default:
throw new ArgumentOutOfRangeException("level", level, null);
}
buffer = new Bitmap(_gameData.GetLength(0) * Square.SquareSize, _gameData.GetLength(1) * Square.SquareSize);
_bufferGraphics = Graphics.FromImage(buffer);
}
/// <summary>
/// 创建自定义游戏实例
/// </summary>
/// <param name="gameSize">游戏宽高</param>
/// <param name="minesCount">雷数</param>
/// <param name="g">图面</param>
/// <param name="gameFieldOffset">游戏区偏移</param>
/// <exception cref="ArgumentOutOfRangeException">游戏尺寸或雷数非法</exception>
public Game(Size gameSize, int minesCount, Graphics g, Size gameFieldOffset)
{
_level = GameLevel.Customize;
_gameFieldOffset = gameFieldOffset;
_wndGraphics = g;
if (gameSize.Width > MaxWidth)
gameSize.Width = MaxWidth;
else if (gameSize.Width < MinWidth)
gameSize.Width = MinWidth;
if (gameSize.Height > MaxHeight)
gameSize.Height = MaxHeight;
else if (gameSize.Height < MinHeight)
gameSize.Height = MinHeight;
if (minesCount < MinMinesCount)
minesCount = MinMinesCount;
else if (minesCount > (gameSize.Width - 1) * (gameSize.Height - 1))
minesCount = (gameSize.Width - 1) * (gameSize.Height - 1);
_gameData = new Square[gameSize.Width, gameSize.Height];
_minesCount = minesCount;
buffer = new Bitmap(_gameData.GetLength(0) * Square.SquareSize, _gameData.GetLength(1) * Square.SquareSize);
_bufferGraphics = Graphics.FromImage(buffer);
}
/// <summary>
/// 开始游戏
/// </summary>
public void Start()
{
//假设所有方块区均非雷区
for (int i = 0; i < _gameData.GetLength(0); i++)
for (int j = 0; j < _gameData.GetLength(1); j++)
_gameData[i, j] = new Square(new Point(i, j), false, 0);
}
/// <summary>
/// 获取游戏区像素尺寸,即雷区的尺寸
/// </summary>
/// <returns></returns>
public Size GetGamePixcelSize()
{
return new Size(_gameData.GetLength(0) * Square.SquareSize, _gameData.GetLength(1) * Square.SquareSize);
}
/// <summary>
/// 左键单击
/// </summary>
/// <param name="pixelPt">鼠标单击像素点</param>
/// <returns>
/// 0:空白处
/// 1:获胜
/// -1:游戏结束
/// </returns>
public int LeftClick(Point pixelPt)
{
if (_gameStoped) return 0;
Point gameFieldpt = new Point(pixelPt.X - _gameFieldOffset.Width, pixelPt.Y - _gameFieldOffset.Height);
Point logicalPt = new Point(gameFieldpt.X / Square.SquareSize, gameFieldpt.Y / Square.SquareSize);
if (!_gameStarted)
{
FormMain.beginTime = DateTime.Now;
FormMain.fm1.timer1.Enabled = true;
Mine(logicalPt);
}
if (!_gameData[logicalPt.X, logicalPt.Y].LeftClick())
{
if ((_gameData[logicalPt.X, logicalPt.Y].MinesAround == 0) && _gameData[logicalPt.X, logicalPt.Y].Status!=Square.SquareStatus.Marked)
AutoOpenAround(logicalPt);
for (int i = 0; i < _gameData.GetLength(0); i++)
{
for (int j = 0; j < _gameData.GetLength(1); j++)
{
if (_gameData[i, j].Mined)
continue;
if (_gameData[i, j].Status == Square.SquareStatus.Opened)
continue;
return 0;
}
}
return 1;
}
for (int i = 0; i < _gameData.GetLength(0); i++)
for (int j = 0; j < _gameData.GetLength(1); j++)
if (_gameData[i, j].Mined)
_gameData[i, j].GameOver(logicalPt);
else
if (_gameData[i, j].Status == Square.SquareStatus.Marked)
_gameData[i, j].IndicateMarkMissed();
return -1;
}
/// <summary>
/// 右键单击
/// </summary>
/// <param name="pixelPt">鼠标单击像素点</param>
public void RightClick(Point pixelPt)
{
if (_gameStoped) return;
Point pt = new Point(pixelPt.X - _gameFieldOffset.Width, pixelPt.Y - _gameFieldOffset.Height);
_gameData[pt.X / Square.SquareSize, pt.Y / Square.SquareSize].RightClick();
}
/// <summary>
/// 结束游戏
/// </summary>
public void Stop()
{
_gameStoped = true;
}
/// <summary>
/// 绘制一帧
/// </summary>
public void Draw()
{
for (int i = 0; i < _gameData.GetLength(0); i++)
for (int j = 0; j < _gameData.GetLength(1); j++)
_gameData[i, j].Draw(_bufferGraphics);
_wndGraphics.DrawImage(buffer, new Point(_gameFieldOffset.Width, _gameFieldOffset.Height));
}
/// <summary>
/// 布雷
/// </summary>
/// <param name="startPt">首次单击点</param>
private void Mine(Point startPt)
{
Size area = new Size(_gameData.GetLength(0), _gameData.GetLength(1));
List<Point> excluded = new List<Point> { startPt };
for (int i = 0; i < _minesCount; i++)
{
Point pt = GetRandomPoint(area, excluded);
_gameData[pt.X, pt.Y] = new Square(pt, true, 0);
excluded.Add(pt);
}
for (int i = 0; i < _gameData.GetLength(0); i++)
for (int j = 0; j < _gameData.GetLength(1); j++)
if (!_gameData[i, j].Mined)
{
int minesAround = EnumSquaresAround(new Point(i, j)).Cast<Square>().Count(square => square.Mined);//周围雷数
_gameData[i, j] = new Square(new Point(i, j), false, minesAround);
}
_gameStarted = true;
}
/// <summary>
/// 自动打开周围非雷区方块(递归)
/// </summary>
/// <param name="squarePt">原方块逻辑坐标</param>
private void AutoOpenAround(Point squarePt)
{
foreach (Square square in EnumSquaresAround(squarePt))
{
if (square.Mined || square.Status == Square.SquareStatus.Marked || square.Status == Square.SquareStatus.Opened)
continue;
square.LeftClick();
if (square.MinesAround == 0)
AutoOpenAround(square.Location);
}
}
/// <summary>
/// 枚举某一方块的周围所有方块区
/// </summary>
/// <param name="squarePt">原方块区</param>
/// <returns>枚举数</returns>
private IEnumerable EnumSquaresAround(Point squarePt)
{
int i = squarePt.X, j = squarePt.Y;
for (int x = i - 1; x <= i + 1; ++x)
{
if (x < 0 || x >= _gameData.GetLength(0))
continue;
for (int y = j - 1; y <= j + 1; ++y)
{
if (y < 0 || y >= _gameData.GetLength(1))
continue;
if (x == squarePt.X && y == squarePt.Y)
continue;
yield return _gameData[x, y];
}
}
}
/// <summary>
/// 获取指定区域内的一个不在排除项列表中的随机点
/// </summary>
/// <param name="areaSize">区域大小,指定了随机点坐标的范围</param>
/// <param name="excluded">排除项</param>
/// <returns>随机点</returns>
/// <exception cref="ArgumentNullException">排除项为空</exception>
private static Point GetRandomPoint(Size areaSize, List<Point> excluded)
{
if (excluded == null)
throw new ArgumentNullException("excluded");
int x, y;
do
{
x = Rnd.Next(0, areaSize.Width);
y = Rnd.Next(0, areaSize.Height);
} while (excluded.Any(pt => pt.X == x && pt.Y == y));
return new Point(x, y);
}
}
}
推荐阅读