• 使用WPF教你一步一步实现连连看(二)


    连连看算法


    第一步:我们考虑在同行或者同列的情况:

    同行或者同列又分三种情况:
      第一:边线,RowNum或者ColNum等于0或者9


      第二:两个相邻

      第三:同行不相邻,这种事有条件的,所在行(或列)的上下(或左右)紧邻行必须在两个按钮之间已全部消除?好,有出问题了,怎么根据已知的行和列,获取Button是否被消除呢?我们可以
    定义一个Button的二维数组。并在初始化的时候给它赋值

    MyButton[,] maps=new MyButton[10,10];

    maps[i, j] = btn;
    好,怎么获取Button是否隐藏已经解决。

    同行步相邻的又分是从上侧、右侧和中间连。

      第二步:既不同行又不同列的要考虑的更多,东西南北都要考虑到了,而连连看的规则是最多转两个弯,
    好了不说了直接上代码了:算法可以自己慢慢琢磨(如果想要最优算法你可以考虑研究下最短路径算法)

       private bool Check(MyButton btn1, MyButton btn2)
            {
                for (int c = 0; c < 10; c++)
                {
                    if (c != btn1.ColNum && !(btn1.RowNum == btn2.RowNum && btn1.ColNum == c) && maps[btn1.RowNum, c].Visibility == Visibility.Visible)   //不为A和B的障碍
                        continue;
                    if (!IsLine(btn1.RowNum, btn2.RowNum, btn1.RowNum, c))  //Aa
                        continue;
                    for (int c2 = 0; c2 < 10; c2++)
                    {
                        if (c2 != btn2.ColNum && !(btn1.RowNum == btn2.RowNum && btn1.ColNum == c2) && maps[btn2.RowNum, c2].Visibility == Visibility.Visible)
                            continue;
                        if (!IsLine(btn1.RowNum, c, btn1.RowNum, c2))   //ab
                            continue;
                        if (!IsLine(btn2.RowNum, c2, btn2.RowNum, btn2.ColNum)) //bB
                            continue;
                        return true;
                    }
                    for (int r = 0; r < 10; r++)
                    {
                        if (r != btn2.RowNum && !(r == btn1.RowNum && btn2.ColNum == btn1.ColNum) && maps[r, btn2.ColNum].Visibility == Visibility.Visible)
                            continue;
                        if (!IsLine(btn1.RowNum, c, r, btn2.ColNum))    //ab
                            continue;
                        if (!IsLine(r, btn2.ColNum, btn2.RowNum, btn2.ColNum))  //bB
                            continue;
                        return true;
                    }
                }
                for (int r = 0; r < 10; r++)
                {
                    if (r != btn1.RowNum && !(r == btn2.RowNum && btn1.ColNum == btn2.ColNum) && maps[r, btn1.RowNum].Visibility == Visibility.Visible)   //不为A和B的障碍
                        continue;
                    if (!IsLine(btn1.RowNum, btn1.ColNum, r, btn1.ColNum))  //Aa
                        continue;
                    for (int c2 = 0; c2 < 10; c2++)
                    {
                        if (c2 != btn2.ColNum && maps[btn2.RowNum, c2].Visibility == Visibility.Visible)
                            continue;
                        if (!IsLine(r, btn1.RowNum, btn2.RowNum, c2))   //ab
                            continue;
                        if (!IsLine(btn2.RowNum, c2, btn2.RowNum, btn2.ColNum)) //bB
                            continue;
                        return true;
                    }
                    for (int r2 = 0; r2 < 10; r2++)
                    {
                        if (r2 != btn2.RowNum && !(r2 == btn1.RowNum && btn2.ColNum == btn1.ColNum) && maps[r2, btn2.ColNum].Visibility == Visibility.Visible)
                            continue;
                        if (!IsLine(r, btn1.ColNum, r2, btn2.ColNum))    //ab
                            continue;
                        if (!IsLine(r2, btn2.ColNum, btn2.RowNum, btn2.ColNum))  //bB
                            continue;
                        return true;
                    }
                }
                return false;
            }
            private bool IsLine(int r1, int c1, int r2, int c2)
            {
                int max, min;
                if (r1 == r2)   //同行
                {
                    max = ((c1 > c2) ? c1 : c2) - 1;
                    min = ((c1 > c2) ? c2 : c1) + 1;
                    while (min <= max)
                    {
                        if (maps[r1, min].Visibility == Visibility.Visible)
                            return false;
                        min++;
                    }
                    return true;
                }
                if (c1 == c2)   //同列
                {
                    max = ((r1 > r2) ? r1 : r2) - 1;
                    min = ((r1 > r2) ? r2 : r1) + 1;
                    while (min <= max)
                    {
                        if (maps[min, c1].Visibility == Visibility.Visible)
                            return false;
                        min++;
                    }
                    return true;
                }
                return false;
            }


    第三步:上面我们完成了算法,也就是我们基本可以玩了。但是玩的过程我们又发现了新问题,

    我们没有保证每个图像都是偶数个,如图:


    这个问题要从初始化的时候着手,我们现在要做一百个背景,那么我们先做50个,然后再分别从这个50个中取出

    代码如下:

      

       public List<int> Get()
            {
                Random rand = new Random();
                List<int> ran = new List<int>();
                for (int n = 0; n < 50; n++)
                    ran.Add(rand.Next(1, 10));
                for (int i = 1; i < 50; i++)
                {
                    List<int> temp = new List<int>();
                    temp.AddRange(ran);
                    for (int n = 0; n < 50; n++)
                    {
                        int r = rand.Next(0, temp.Count);
                        ran.Insert(rand.Next(0, ran.Count), temp[r]);
                        temp.RemoveAt(r);
                    }
                }
    
                return ran;
            }

    这种思路应该是对的,但是没有达到预期的效果,还是会有剩下,由于缺少时间,可能要过一段时间来弄这个,有

    看出问题的高手可以帮我留言,我会争取早点解决问题的。

      我下一步准备是将动画连线与倒计时加上,这可能要等一段时间了。下面是我在网上找的一段练练看算法,希望

    能给大家一个参考:

    public class LineCore
    
    {
    
        //整体宽度
    
        public int width { get; set; }
    
        //整体高度
    
        public int height { get; set; }
    
        //前次被点击的图片
    
        public Position lastPicture { get; set; }
    
        //当前被电击的图片
    
        public Position currentPicture { get; set; }
    
        // 图片矩阵,-1表示没有图片,初始化时,任意matrix[x,y]当x==0或y==0时,matrix[x,y]=-1
    
        public int[,] matrix { get; set; }
    
    
    
        public bool testLine(Position current)
    
        {
    
            //上次连接成功后,第一次点击,
    
            if (currentPicture == null)
    
            {
    
                currentPicture = current;
    
                return false;
    
            }
    
            //连续点击了同一幅图片
    
            if (currentPicture.x==current.x&&currentPicture.y==current.y)
    
            {
    
                return false;
    
            }
    
            //不是相同的图像,不能消除
    
            if (current.picture != currentPicture.picture)
    
            {
    
                lastPicture = null;
    
                currentPicture = current;
    
                return false;
    
            }
    
            lastPicture = currentPicture;
    
            currentPicture = current;
    
            //记录连接路径
    
            List<Position> paths = new List<Position>();
    
            paths.Add(currentPicture);
    
            bool finded=false;
    
            //向东搜索
    
            finded = _find(paths, 2, Direct.East, lastPicture);
    
            if (finded)
    
            {
    
                return true;
    
            }
    
            //向南搜索
    
            finded = _find(paths, 2, Direct.South, lastPicture);
    
            if (finded)
    
            {
    
                return true;
    
            }
    
            //向西搜索
    
            finded = _find(paths, 2, Direct.West, lastPicture);
    
            if (finded)
    
            {
    
                return true;
    
            }
    
            //向北搜索
    
            finded = _find(paths, 2, Direct.North, lastPicture);
    
            if (finded)
    
            {
    
                return true;
    
            }
    
            //搜索失败
    
            return false;
    
        }
    
        /***
    
         * results-> 搜索路径
    
         * chance-> 还剩有转弯的机会,最多2次
    
         * direct-> 当前前进的方向
    
         * target-> 搜索的目标
    
         * **/
    
        protected bool _find(List<Position> results, int chance, Direct direct, Position target)
    
        {
    
            //路径中不能为空
    
            if (results.Count <= 0)
    
            {
    
                return false;
    
            }
    
            //取路径中最后一个
    
            Position currentPos = results.ElementAt(results.Count - 1);
    
            //构造下一个将要检测的路径
    
            Position nextPos = new Position();
    
            switch(direct){
    
                case Direct.East:
    
                    nextPos.x=currentPos.x+1;
    
                    nextPos.y=currentPos.y;
    
                    break;
    
                    case Direct.West:
    
                    nextPos.x=currentPos.x-1;
    
                    nextPos.y=currentPos.y;
    
                    break;
    
                    case Direct.South:
    
                    nextPos.x=currentPos.x;
    
                    nextPos.y=currentPos.y+1;
    
                    break;
    
                    case Direct.North:
    
                    nextPos.x=currentPos.x;
    
                    nextPos.y=currentPos.y-1;
    
                    break;
    
            }
    
            bool overFlow = false;
    
            //检测是否已经走出边界
    
            if (nextPos.x < 0 || nextPos.x >= width || nextPos.y < 0 || nextPos.y>=height)
    
            {
    
                overFlow = true;
    
            }
    
            if (overFlow)
    
            {
    
                return false;
    
            }
    
            //检测是否是目标
    
            if (target.x == nextPos.x&&target.y==nextPos.y)
    
            {
    
                results.Add(nextPos);
    
                return true;
    
            }
    
            //不是-1 说明该位置有图片,不能通过
    
            if (matrix[nextPos.x, nextPos.y]!=-1)
    
            {
    
                return false;
    
            }
    
            //加入路径
    
            results.Add(nextPos);
    
            bool find = false;
    
            //按照当前方向继续试探
    
            find = _find(results, chance, direct, target);
    
            if (find)
    
            {
    
                return true;
    
            }
    
            //转弯机会已经耗尽
    
            if (chance <= 0)
    
            {
    
                //此路不通,将路径最后一个位置删除
    
                results.RemoveAt(results.Count - 1);
    
                return false;
    
            }
    
            //当前方向向东,还可以转弯向南,向北继续试探
    
            if (Direct.East == direct)
    
            {
    
                find = _find(results, chance-1, Direct.North, target);
    
                if (find)
    
                {
    
                    return true;
    
                }
    
                find = _find(results, chance-1, Direct.South, target);
    
                if (find)
    
                {
    
                    return true;
    
                }
    
                results.RemoveAt(results.Count - 1);
    
                return false;
    
            }
    
            //当前方向向南,还可以转弯向东,向西继续试探
    
            else if (Direct.South == direct)
    
            {
    
                find = _find(results, chance-1, Direct.East, target);
    
                if (find)
    
                {
    
                    return true;
    
                }
    
                find = _find(results, chance-1, Direct.West, target);
    
                if (find)
    
                {
    
                    return true;
    
                }
    
                results.RemoveAt(results.Count - 1);
    
                return false;
    
            }
    
            //当前方向向西,还可以转弯向南,向北继续试探
    
            else if (Direct.West == direct)
    
            {
    
                find = _find(results, chance-1, Direct.North, target);
    
                if (find)
    
                {
    
                    return true;
    
                }
    
                find = _find(results, chance-1, Direct.South, target);
    
                if (find)
    
                {
    
                    return true;
    
                }
    
                results.RemoveAt(results.Count - 1);
    
                return false;
    
            }
    
            //当前方向向北,还可以转弯向东,向西继续试探
    
            else
    
            {
    
                find = _find(results, chance-1, Direct.East, target);
    
                if (find)
    
                {
    
                    return true;
    
                }
    
                find = _find(results, chance-1, Direct.West, target);
    
                if (find)
    
                {
    
                    return true;
    
                }
    
                results.RemoveAt(results.Count - 1);
    
                return false;
    
            }
    
        }
    
        //联通成功后,将两个位置设置成空
    
        public void onSuccess()
    
        {
    
            this.matrix[this.lastPicture.x, this.lastPicture.y] = -1;
    
            this.matrix[this.currentPicture.x, this.currentPicture.y] = -1;
    
            this.currentPicture = null;
    
            this.lastPicture = null;
    
        }
    
    
    
    
    
    }
    
     
    
    public class Position
    
    {
    
        public int x { get; set; }
    
        public int y { get; set; }
    
        //picture 表示不同图像,如果是-1,表示为空
    
        public int picture { get; set; }
    
    }
    
    
    
    public enum Direct : int
    
    {
    
        East = 0, South = 1, West = 2, North = 3
    
       }

    请高手多多指正……

  • 相关阅读:
    计算长度的方法
    自动装箱和拆箱
    基本数据包装类
    Date类
    文档参数解析
    权限修饰符
    IO流
    ArrayList集合类
    对象数组
    二维数组
  • 原文地址:https://www.cnblogs.com/smiler/p/3197226.html
Copyright © 2020-2023  润新知