最近在做连连看小游戏,整体完成的差不多,还差一个死局判定,若为死局,即重新洗牌。
由于项目结构较为繁杂,建议大家先下载源码
源码下载链接:https://gitee.com/NKG/UnityWorks/blob/master/UnityPackages/LinkUp.unitypackage
和群里的大神讨论后,决定使用有向邻接表这一数据结构思想来实现这个目的。
直接讲实现方法也没用,先来复习一下C++版的邻接表吧
https://blog.csdn.net/qq_15020543/article/details/84178417
针对连连看这个项目,因为我们只需要将相同的牌存在一个链表里,所以我们可以利用C#自带的链表结构,字典结构,结合泛型来实现(有向邻接表思想)实现起来是比较容易的。
/// <summary>
/// 水果结点
/// </summary>
public class FruitNode
{
/// <summary>
/// X下标
/// </summary>
public int X;
/// <summary>
/// Y下标
/// </summary>
public int Y;
}
/// <summary>
/// 用来检测死局的有向邻接表
/// </summary>
public static Dictionary<int, LinkedList<FruitNode>> MapCollect = new Dictionary<int, LinkedList<FruitNode>>();
/// <summary>
/// 向邻接表表中添加元素
/// </summary>
/// <param name="x">x坐标</param>
/// <param name="y">y坐标</param>
/// <param name="value">水果类型</param>
private void AddItemToLinklist(int x, int y, int value)
{
if (MapCollect.ContainsKey(value))
{
FruitNode fruitNode = new FruitNode(x, y, value);
MapCollect[value].AddLast(fruitNode);
}
else
{
FruitNode fruitNode = new FruitNode(x, y, value);
LinkedList<FruitNode> tempFruitNodes = new LinkedList<FruitNode>();
tempFruitNodes.AddLast(fruitNode);
MapCollect.Add(value, tempFruitNodes);
}
}
/// <summary>
/// 依照当前地图生成邻接表
/// </summary>
public void CreateMapLink()
{
for (int i = 1; i < RowNum; i++)
{
for (int j = 1; j < ColumNum; j++)
{
AddItemToLinklist(j,i,TestMap[j,i]);
}
}
}
数据结构已经创建好了,那么具体方法为
1.玩家每次进行消除操作就更新此数据结构,并且判定是否为死局
- 遍历字典,判断其中的结点能否满足消除条件(消除逻辑已完善)
- 若找到可消除的,即返回,继续游戏
- 若没找到可消除的,重新洗牌
2.尽管已经做了算法上的优化,但可以预见,他仍是一个比较消耗性能的操作,所以我准备新开一个线程让它执行判断。
选择有向邻接表这一数据结构用来做死局判定,优势有:
- 时间复杂度低,只需要构建有向邻接表的时候完整遍历一次二维数组,维护的时候就比较轻松了。举个例子,10x10的矩阵,你直接要判定是否死局,最坏情况就是O(100^100)的时间复杂度。如果用有向邻接表...还真不好说是多少,反正比直接用矩阵好的多得多。
- 便于维护,由于是有向邻接表,删除结点只需要找到它删除就行了,时间复杂度为O(1),这同时也是为什么不用无向邻接表的理由,因为无向邻接表你要删除两个地方。不方便。