⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 defaultmineengine.cs

📁 C#实现的扫雷游戏,可以做为C#编程的例子学习
💻 CS
字号:
using System;
using System.Windows.Forms;

namespace MinesWeeper
{
	/// <summary>
	/// MineMemento の概要の説明です。
	/// </summary>
	public class DefaultMineEngine : IMineEngine
	{
		#region Private Variables

		//内置计时器
		private Timer timer = new Timer();

		//布雷数据
		private byte[,] data;

		//是否已经失败
		private bool isFailed = false;

		//宽,高,雷总数,剩下区域,所用时间
		private int x,y,total,leaving,useTimes;
		#endregion

		#region Public Properties

		//宽属性
		public int X
		{
			get{ return x; }
		}

		
		//高属性
		public int Y
		{
			get{ return y; }
		}


		//所用时间属性
		public int UseTimes
		{
			get{ return useTimes; }
		}


		//构造函数
		public DefaultMineEngine()
		{
			this.timer.Interval = 1000;
			timer.Tick += new EventHandler(timer_Tick);
		}
		
		public byte[,] Mines
		{
			get{
				return this.data;
			}
		}


		//是否已经失败属性
		public bool IsFailed
		{
			get{ return isFailed; }
		}


		//部署雷数据属性
		public byte[,] MinesRank
		{
			get
			{
				return data;
			}
		}

		
		//内置计时器属性
		public Timer CalculaGraph
		{
			get
			{
				return timer;
			}
		}

		#endregion
		
		#region Public Events

		//扫雷动作事件
		public event WorkEventHandler Worked = null;
		#endregion

		#region Public Medthods

		//打开坐标(x,y)区域
		public void Open(int x, int y)
		{
			if(isFailed || x < 0 || y < 0 || x >= this.x || y >= this.y)
				return ;
			byte mine = data[x,y];
			if(leaving >= (X*Y-total))
			{
				timer.Start();
			}
			if(MineUtils.IsMine(mine))
			{
				OnWork(WorkType.Faile);
				return;
			}
			if(!MineUtils.IsOpened(mine))
			{
				OpenNotRefresh(x,y);
				OnWork(WorkType.Refresh);
			}
			if(leaving <= 0)
			{
				OnWork(WorkType.Done);
			}
		}

		
		//部署雷区(x:宽,y:高,total:雷个数)
		public void Deploy(int x,int y,int total)
		{
			DeployMine(x,y,total);
			DeployOther();
			this.total = total;
			OnWork(WorkType.Start);
		}


		//标记坐标(x,y)区域
		public void Flag(int x, int y)
		{
			if(isFailed || x < 0 || y < 0 || x >= this.x || y >= this.y)
				return;
			byte mine = data[x,y];
			if(!MineUtils.IsOpened(mine))
			{
				data[x,y] = MineUtils.Flag(mine);
				OnWork(WorkType.Refresh);
			}
		}

		
		//清除已知坐标(x,y)区域(打开x,y周围区域)
		public void Clear(int x, int y)
		{
			if(isFailed || x < 0 || y < 0 || x >= this.x || y >= this.y)
				return;
			int flg = statFlg(x-1,y-1,WeeperFlag.IsPuzzle);
			flg += statFlg(x,y-1,WeeperFlag.IsPuzzle);
			flg += statFlg(x+1,y-1,WeeperFlag.IsPuzzle);
			flg += statFlg(x-1,y,WeeperFlag.IsPuzzle);
			flg += statFlg(x+1,y,WeeperFlag.IsPuzzle);
			flg += statFlg(x-1,y+1,WeeperFlag.IsPuzzle);
			flg += statFlg(x,y+1,WeeperFlag.IsPuzzle);
			flg += statFlg(x+1,y+1,WeeperFlag.IsPuzzle);
			if(flg == MineUtils.getInside(data[x,y]))
			{
				OpenWhenNoMineFlg(x-1,y-1);
				OpenWhenNoMineFlg(x,y-1);
				OpenWhenNoMineFlg(x+1,y-1);
				OpenWhenNoMineFlg(x-1,y);
				OpenWhenNoMineFlg(x+1,y);
				OpenWhenNoMineFlg(x-1,y+1);
				OpenWhenNoMineFlg(x,y+1);
				OpenWhenNoMineFlg(x+1,y+1);
			}

			
		}

		#endregion
		
		#region Private Medthods
		//先将雷部署到区域中
		private void DeployMine(int x,int y,int total)
		{
			data = new byte[x,y];
			this.x = x;
			this.y = y;
			Random r = new Random();
			this.leaving = x * y - total;
			while(total > 0)
			{
				int a = r.Next() % x;
				int b = r.Next() % y;
				if(data[a,b] == 0)
				{
					data[a,b] = 9;
					total--;
				}
			}
		}


		//计算除雷以外的数据
		private void DeployOther()
		{
			for(int i=0;i<x;i++)
			{
				for(int j=0;j<y;j++)
				{
					if(data[i,j] != 9)
					{
						data[i,j] = (byte)stat(i,j);
					}
				}
			}
		}

		
		//计算(x,y)周围有多少雷
		private int stat(int x,int y)
		{
			int iRs = getMine(x-1,y-1);
			iRs += getMine(x,y-1);
			iRs += getMine(x+1,y-1);
			iRs += getMine(x-1,y);
			iRs += getMine(x+1,y);
			iRs += getMine(x-1,y+1);
			iRs += getMine(x,y+1);
			iRs += getMine(x+1,y+1);
			return iRs;
		}


		//计算(x,y)周围有多少flg标志
		private int statFlg(int x,int y,WeeperFlag flg)
		{
			if(x < 0 || y < 0 || x >= this.x || y >= this.y)
				return 0;
			if(flg == MineUtils.getWeeperFlag(data[x,y]))
			{
				return 1;
			}
			return 0;
		}
		

		//判断(x,y)是否为雷,是则返回1
		private int getMine(int x,int y)
		{
			if(x < 0 || y < 0 || x >= this.x || y >= this.y)
				return 0;
			if(data[x,y] == 9)
				return 1;
			return 0;
		}

		
		//触发WorkEventHandler事件句柄
		protected void OnWork(WorkType workType)
		{
			if(workType == WorkType.Faile)
			{
				isFailed = true;
				timer.Stop();
			}
			else if(workType == WorkType.Start)
			{
				isFailed = false;
				this.useTimes = 0;
			}else if(workType == WorkType.Done)
			{
				isFailed = false;
				timer.Stop();
			}
			if(null != Worked)
			{
				Worked(this,new WorkEventArgs(workType,useTimes));
			}
		}


		//打开坐标(x,y)区域但不刷新
		private void OpenNotRefresh(int x, int y)
		{
			if(x < 0 || y < 0 || x >= this.x || y >= this.y)
				return;
			byte mine = data[x,y];
			if(!MineUtils.IsOpened(mine))
			{
				data[x,y] = MineUtils.Open(mine);
				leaving --;
				if(MineUtils.getInside(mine) == 0)
				{
					OpenNotRefresh(x-1,y-1);
					OpenNotRefresh(x,y-1);
					OpenNotRefresh(x+1,y-1);
					OpenNotRefresh(x-1,y);
					OpenNotRefresh(x+1,y);
					OpenNotRefresh(x-1,y+1);
					OpenNotRefresh(x,y+1);
					OpenNotRefresh(x+1,y+1);
				}
			}			
		}


		//打开坐标(x,y)区域周围没有标志为雷的区域
		private void OpenWhenNoMineFlg(int x, int y)
		{
			if(statFlg(x,y,WeeperFlag.IsPuzzle) <= 0)
			{
				Open(x,y);
			}
		}


		//计时(每秒+1)
		private void timer_Tick(object sender, EventArgs e)
		{
			useTimes ++;
		}

		#endregion

	}


	//Work 事件代理
	public delegate void WorkEventHandler(object sender, WorkEventArgs args);

	//Work 事件参数
	public class WorkEventArgs
	{
		//Work 类型
		private WorkType workType = WorkType.None;

		//所用时间
		private int useTimes = 0;

		public WorkEventArgs(WorkType workType)
		{
			this.workType = workType;
		}


		public WorkEventArgs(WorkType workType, int useTimes)
		{
			this.workType = workType;
			this.useTimes = useTimes;
		}


		public int UseTimes
		{
			get{ return useTimes; }
		}


		public WorkType Works
		{
			get{ return workType; }
		}
	}


	//Work 类型
	public enum WorkType
	{
		//无
		None = -1,
		//开始
		Start = 0,
		//刷新
		Refresh = 1,
		//失败
		Faile = 2,
		//扫雷成功
		Done
	}


	//标记类型
	public enum WeeperFlag
	{
		//无标志
		Blank = 0,
		//雷标志
		IsPuzzle = 1,
		//未知
		UnKnow = 2
	}


	//解析雷的工具(当前解析一个字节)
	internal class MineUtils
	{
		//雷的值
		public const int mineVal	= 0x9;
		//一个byte中打开标记的值
		const int openMask			= 0x40;
		//一个byte中部署的值
		const int innerMask			= 0xF;
		//一个byte中标记的值
		const int flagMask			= 0x30;

		//打开后byte的操作
		public static byte Open(byte data)
		{
			return (byte)((1 << 6) | (data & innerMask));
		}


		//标记后byte的操作
		public static byte Flag(byte data)
		{
			int status = data >> 4;
			switch(status)
			{
				case 0:
					return (byte)((1 << 4) | (data & innerMask));
				case 1:
					return (byte)((2 << 4) | (data & innerMask));
				case 2:
					return (byte)(data >> 4);
				default:
					return data;
			}
		}


		//判断此区域是否打开
		public static bool IsOpened(byte data)
		{
			return ((data >> 6) > 0);
		}


		//判断此区域是否是雷
		public static bool IsMine(byte data)
		{
			return ((data & innerMask) == mineVal);
		}


		//取得byte中部署部分的值
		public static int getInside(byte data)
		{
			return (data & innerMask);
		}


		//取得byte中标记类型
		public static WeeperFlag getWeeperFlag(byte data)
		{
			return (WeeperFlag)((data & flagMask) >> 4);
		}


		//取得byte中标记类型的显示字符串
		public static String getFlgString(byte data)
		{
			WeeperFlag flg = getWeeperFlag(data);
			switch(flg)
			{
				case WeeperFlag.IsPuzzle:
					return "※";
				case WeeperFlag.UnKnow:
					return "?";
				default:
					return String.Empty;
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -