连连看 算法 总结

连连看 算法 总结

首先 连连看 是 一款休闲小游戏,非常适合锻炼算法,一门语言的入门 也是不错的,
首先是 匹配算法, 匹配函数需要 接受两个 位置 进行 取得数据进行匹配,
取得数据 就只是 访问数组,因此 只要先判断这两个值 是否一样就 可以进行下一步匹配。

检测函数 很简单
判断结果 是否相同, 是否越界

0拐点

分 垂直遍历,水平遍历

垂直遍历:

垂直遍历 说明 x相同, 比较两点取最小y 遍历到 最大y

    //垂直 X 相等  取 最小y -> 最大y 遍历,判断 value是否为0  遇到不是0返回false
    public bool Vertical(Point a, Point b)
    {
        if (a.X != b.X) //垂直遍历 x必须相同
        {
            return false;

        }

        int yMax = Mathf.Max(a.Y, b.Y) - 1; //忽略自己
        int yMin = Mathf.Min(a.Y, b.Y) + 1; //从相邻的开始, 忽略自己


        for (int i = yMin; i < yMax; i++)
        {
            if (Map.Map[i][a.X] != 0) //0代表 空
            {
                return false;
            }
        }

        return true;
    }
水平遍历:

水平遍历 说明 y相同, 比较两点取最小x 遍历到 最大x

//水平 y 相等  取 最小x -> 最大X 遍历,判断 value是否为0  遇到不是0返回false
    public bool Horizontal(Point a, Point b)
    {
        if (a.Y != b.Y) //垂直遍历 x必须相同
        {
            return false;

        }
        int xMax = Mathf.Max(a.X, b.X) - 1; //忽略自己
        int xMin = Mathf.Min(a.X, b.X) + 1; //从相邻的开始, 忽略自己

        for (int i = xMin; i < xMax; i++)
        {
            if (Map.Map[a.Y][i]!= 0) //0代表 空
            {
                return false;
            }
        }

        return true;
    }

1拐点:

假设 输入两点 A ,B 他们x不同 y也不同,想象下 它们都是十字线的中心交点,

A的X直线 与B的Y直线 有个交点 D,D这一点 满足  Dy1=Ay1   ,Dx1 =Bx1

A的 Y直线 与B的x直线 有个交点C ,C这一点满足  Cx1=Ax1  , Cy1=By1

这俩个交点 就是要求的解了 ,且 这个交点 必须 是空的

假设 A B C D
从A 到点B 需要 经过C 点 ,或者 D 点,
C点 需要满足 Cx1=Ax1 , Cy1=By1
D点 需要 满足 Dy1=Ay1 ,Dx1 =Bx1

X相同 就说明 Y不相同, Y不相同 就需要用 垂直遍历,
因此 A 垂直遍历到C ,再从C 水平遍历到B

public bool OnePoint(Point a, Point b)
    {

        Point pointC=new Point(){ X=a.X,Y=b.Y}; //x 和 a相同  ,y和b相同
        Point pointD = new Point() { X = b.X, Y = a.Y };
        
  	 if(Map.Map[pointC.Y][pointC.X]==0)
        return (Vertical(a, pointC) && Horizontal(pointC, b)) 
   
  		 if(Map.Map[pointD.Y][pointD.X]==0)
  	 		return  Horizontal(a,pointD) && Vertical(pointD,b) ; //从 a-->c 再 从c-->b
   return false;

    }

2拐点

需要找到一个点 , 这个 点需要 满足 1 拐点 and 垂直|| 水平,
这个 点 必须 满足 是B的垂直点,或者是水平点, 且这个点需要满足 A的一 拐点。

也就是说 这一点 C 必须 满足一个条件。
Cx1 AX1 ||C x1Bx1 || Cy1Ay1||Cy1B1

public class LLKData
{
    /// <inheritdoc />
    public LLKData(MapData map)
    {
        //生成 地图TODO:
        Map = map;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="kind"></param>
    public void InitMap(int x, int y, int kind)
    {
    }



    public struct Point
    {
        public int X;
        public int Y;
      
    }

    public struct MapData
    {
        public int[][] Map;
        public int MaxX;
        public int Maxy;
    }

    public MapData Map;

    /// <summary>
    /// 不越界
    /// </summary>
    /// <param name="a"></param>
    /// <returns></returns>
    public bool CheckPoint(Point a)
    {
        //不越界的情况
        return a.X <= Map.MaxX && a.X >= 0 && (a.Y <= Map.Maxy && a.Y <= 0);
    }

	    public bool CheckResult(Point a, Point b)
    {

        return    CheckPoint(a) && CheckPoint(b) && Map.Map[a.Y][a.X]==Map.Map[b.Y][b.X];
    }

    #region  算法

    //垂直 X 相等  取 最小y -> 最大y 遍历,判断 value是否为0  遇到不是0返回false
    public bool Vertical(Point a, Point b)
    {
        if (a.X != b.X) //垂直遍历 x必须相同
        {
            return false;

        }

        int yMax = Mathf.Max(a.Y, b.Y) - 1; //忽略自己
        int yMin = Mathf.Min(a.Y, b.Y) + 1; //从相邻的开始, 忽略自己


        for (int i = yMin; i < yMax; i++)
        {
            if (Map.Map[i][a.X] != 0) //0代表 空
            {
                return false;
            }
        }

        return true;
    }

    //水平 y 相等  取 最小x -> 最大X 遍历,判断 value是否为0  遇到不是0返回false
    public bool horizontal(Point a, Point b)
    {
        if (a.Y != b.Y) //垂直遍历 x必须相同
        {
            return false;

        }
        int xMax = Mathf.Max(a.X, b.X) - 1; //忽略自己
        int xMin = Mathf.Min(a.X, b.X) + 1; //从相邻的开始, 忽略自己

        for (int i = xMin; i < xMax; i++)
        {
            if (Map.Map[a.Y][i]!= 0) //0代表 空
            {
                return false;
            }
        }

        return true;
    }

    public bool OnePoint(Point a, Point b)
    {

        Point pointC=new Point(){ X=a.X,Y=b.Y}; //x 和 a相同  ,y和b相同
        Point pointD = new Point() { X = b.X, Y = a.Y };

        return (Vertical(a, pointC) && horizontal(pointC, b))|| horizontal(a,pointD) && Vertical(pointD,b) ; //从 a-->c 再 从c-->b
    }

    public bool  TwoPointPath(Point a, Point b)
    {
        //找一点 满足 
        for (int i = 0; i < Map.Maxy; i++)
        {
            for (int j = 0; j < Map.MaxX; j++)
            {
                if ((i!=a.Y&&j!=a.X)&& (i!=b.Y&&j!=b.X ))
                {
                if (i!=a.Y &&i!=b.Y && j!=a.X && j!=b.X)
                    {
                    
                    Point c=new Point(){X = j,Y=i};
                    // 这个点 是a的一点拐点,且是 b的 垂直或者水平点
                    //或者这个点是 b的一点拐点, 且 是 a的垂直点 或者水平点
                    return 
                        (OnePoint(a, c) && (Vertical(c, b) || horizontal(c, b)) )
                           ||  
                        (OnePoint(c,b) &&  (Vertical(a,c) ||horizontal(a,c)))
                        ;
                        }
                }
            }
        }
        
        return false;
    }

    public bool GetMacth(Point a, Point b)
    {
        if (!CheckResult(a, b))
            return false;

        bool isMatch=false;
        if (a.X==b.X || a.Y==b.Y)  //处理  位置 处于  十字线情况  不存在 一拐点
        {
            if (a.X==b.X)
            {
                //垂直
                isMatch= Vertical(a, b);
            }
            else
            {
                isMatch = horizontal(a, b);
            }

            if (isMatch)
                return isMatch;

            isMatch = TwoPointPath(a, b);

            return isMatch;  
        }
        else
        {
            isMatch = OnePoint(a, b);
            if (isMatch)
                return isMatch;

            isMatch = TwoPointPath(a, b);
        }

        return isMatch;
    }

    #endregion

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值