📄 defaultmineengine.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 + -