一直觉得扫雷的算法很神奇,研究了一下,其实就是简单的递归算法。核心在于遍历每个格子周围的八个格子,计算雷数:雷数大于0时显示雷数,雷数等于0时不显示数字,并且利用递归方法自动点开周围的格子。
格子类
public class Grid
{
public bool IsLei;
public bool IsClicked;
public int Count;
}
扫雷地图类
public class Map:MonoBehaviour,IPointerClickHandler
{
//地图行数
public const int RowCount;
//地图列数
public const int ColCount;
//将格子类存入一个数组
public Grid[,] grids = new Grids[RowCount,ColCount];
//将按钮作为格子UI部分,用于点击
public GameObject[,] tiles = new GameObject[RowCount,ColCount];
//格子周围的八个方向
private Vector2[] dirs = new Vector2[] { Vector2.up, Vector2.down, Vector2.left,
Vector2.right ,new Vector2(-1,1),new Vector2(-1,-1),new Vector2(1,1),new Vector2(1,-1)};
//格子的容器
[SerializeField]
private Transform gridContainer;
//格子预制体Button
[SerializeField]
private GameObject gridPrefab;
//初始地图
void StartGame()
{
for (int i = 0; i < RowCount; i++)
{
for (int j = 0; j < ColCount; j++)
{
grids[i, j] = new Grid();
//随机向格子中添加雷
grids[i, j].IsLei = Random.Range(1, 11) < 3 ? true : false;
//添加可点击按钮作为格子
GameObject grid = Instantiate(gridPrefab);
grid.transform.SetParent(gridContainer);
//给按钮命名,便于点击的时候检测
grid.name = i.ToString() + "_" + j.ToString();
tiles[i, j] = grid;
}
}
}
void Start()
{
StartGame();
}
//点击事件检测,获取点击的格子坐标
public void OnPointerClick(PointerEventData eventData)
{
GameObject enter = eventData.pointerEnter;
//如果点击的是格子
if (enter.name.Contains("_"))
{
//计算格子的坐标
int x = int.Parse(enter.name.Split('_')[0]);
int y = int.Parse(enter.name.Split('_')[1]);
GridClick(x, y);
}
}
//点击格子的结果判断
private void GridClick(int x,int y)
{
if (!grids[x, y].IsClicked)
{
grids[x, y].IsClicked = true;
//检测grids[x,y]是不是雷
if (grids[x, y].IsLei)
{
//是雷就输了
Debug.Log("输了");
return;
}
else {
//如果不是雷,则检测该格子周围八个格子的情况
for (int i = 0; i < dirs.Length; i++)
{
int temp_x = x + (int)dirs[i].x;
int temp_y = y + (int)dirs[i].y;
//如果周围有雷,则该格子雷数+1
if (temp_x >= 0 && temp_x < RowCount && temp_y >= 0 && temp_y < ColCount)
{
if (grids[temp_x, temp_y].IsLei)
{
grids[x, y].Count++;
}
}
}
//格子点击后变灰,并显示雷数
tiles[x, y].transform.GetChild(0).gameObject.SetActive(true);
tiles[x, y].GetComponent().color = Color.gray;
if (grids[x, y].Count > 0)
tiles[x, y].GetComponentInChildren().text = grids[x, y].Count.ToString();
else
Digui(x,y);
}
}
}
//当grids[x,y]这个格子周围雷数为0时,调用递归方法自动点开它周围的八个格子
private void Digui(int x, int y)
{
for (int i = 0; i < dirs.Length; i++)
{
int temp_x = x + (int)dirs[i].x;
int temp_y = y + (int)dirs[i].y;
//没被点击过
if (temp_x>=0&&temp_x=0&&temp_y |