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

简介: 连连看算法 第一步:我们考虑在同行或者同列的情况:同行或者同列又分三种情况:  第一:边线,RowNum或者ColNum等于0或者9   第二:两个相邻  第三:同行不相邻,这种事有条件的,所在行(或列)的上下(或左右)紧邻行必须在两个按钮之间已全部消除?好,有出问题了,怎么根据已知的行和列,获取Button是否被消除呢?我们可以定义一个Button的二维数组。

连连看算法


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

同行或者同列又分三种情况:
  第一:边线,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

   }

请高手多多指正……

目录
相关文章
|
C#
WPF 界面实现多语言支持 中英文切换 动态加载资源字典
原文:WPF 界面实现多语言支持 中英文切换 动态加载资源字典 1、使用资源字典,首先新建两个字典文件en-us.xaml、zh-cn.xaml。定义中英文的字符串在这里面【注意:添加xmlns:s="clr-namespace:System;assembly=mscorlib】 zh-cn.
2901 0
|
IDE C# 开发工具
WPF钟表效果实现
中WPF中的RotateTransform实现UI元素的旋转,并模拟钟表的秒针、分针和时针。
1125 0
WPF钟表效果实现
|
IDE 编译器 C#
WPF实现强大的动态公式计算
数据库可以定义表不同列之间的计算公式,进行自动公式计算,但如何实现行上的动态公式计算呢?行由于可以动态扩展,在某些应用场景下将能很好的解决实际问题。本文就探讨一下如何在WPF中实现一种基于行字段的动态公式计算。
990 0
WPF实现强大的动态公式计算
|
网络协议 C# 移动开发
C# WPF上位机实现和下位机TCP通讯
C# WPF上位机实现和下位机TCP通讯下位机使用北京大华程控电源DH1766-1,上位机使用WPF。实现了电压电流实时采集,曲线显示。上午在公司调试成功,手头没有程控电源,使用TCP服务端模拟。昨天写的TCP服务端正好排上用场。
2337 0
|
C#
WPF中获取TreeView以及ListView获取其本身滚动条的方法,可实现自行调节scoll滚动的位置(可相应获取任何控件中的内部滚动条)
原文:WPF中获取TreeView以及ListView获取其本身滚动条的方法,可实现自行调节scoll滚动的位置(可相应获取任何控件中的内部滚动条) 对于TreeView而言: TreeViewAutomationPeer lvap = new TreeViewAuto...
2315 0
|
XML 自然语言处理 C#
WPF 多语言实现
原文:WPF 多语言实现 很多国际化的程序都提供了多语言的选项,这样方便不同国家的使用者更方便的使用软件。这篇博客中将介绍在WPF中实现多语言的方式。 方式一,使用WPF动态资源的方式实现。先简单介绍下StaticResource和DynamicResource,这两者的区别在于动态资源改变后会实时的体现出来,而静态资源只加载一次,后面对资源的任何改变都不会体现出来。
1508 0
|
C#
WPF实现三星手机充电界面
原文:WPF实现三星手机充电界面 GitHub地址:https://github.com/ptddqr/wpf-samsung-phone-s5-charging-ui/tree/master 先上效果图 这个效果来自于三星S5的充电界面,版权归三星所有,这里仅仅是技术实现.
1659 0
|
C# vr&ar
WPF实现物理效果 拉一个小球
原文:WPF实现物理效果 拉一个小球 一直以来都对物理效果有神秘感,完全不知道怎么实现的.直到看到了周银辉在老早前写的一篇博客:http://www.cnblogs.com/zhouyinhui/archive/2007/06/23/793724.
934 0
|
C#
WPF实现Twitter按钮效果
原文:WPF实现Twitter按钮效果 最近上网看到这个CSS3实现的Twitter按钮,感觉很漂亮,于是想用WPF来实现下. 实现这个效果,参考了CSS3 原文地址:http://www.html5tricks.
1205 0
|
C# UED 自然语言处理
在WPF中实现图片一边下载一边显示
原文 在WPF中实现图片一边下载一边显示 当我们上网查看一个较大的图片时,浏览器能一边下载一边显示,这样用户体验是比较好的,但在WPF程序中,当我们通过如下方式显示一幅图片时:     img.Source = new BitmapImage(new Uri("http://localhost:8000/www/test.jpg")); 只能等到图片下载完成时才能显示出来,当图片较大时需要等待很久,即使在旁边放个进度条给人的感觉仍然不好。
1027 0